如何使用JPA的@Formula注解?
背景描述
我们经常会在项目中用到一些数据字典,在存储和传输时使用Code,在前端展示时使用Name,这样做的好处是便于系统维护,比如项目中用到了"医院"这个名称,如果后期需求发生变化不叫"医院"了,改成"医疗机构",假如不使用数据字典,那么我们代码中、数据库中所有用到"医院"的地方都要修改,麻烦不说,漏掉一个就是一个小Bug。在处理这个Code/Name的转化的时候,我思考了几种处理方式,第一种,使用@ManyToOne注解关联字典查询,这样是最容易想到的方式,但是这种方式得到的结果是字典对象整体包含在查询到的实体中,我们所需要的只是字典里的name,所以我尝试寻找一种直接将字典表里的name映射到实体对象上的方式。第二种,使用HQL关联查询映射到自定义对象,这种方式可以达到我的预期,但是HQL写起来很麻烦,尤其是当需要关联查询的字典特别多的时候。并且我的项目中动态用的是JPA的Specification,如果使用这种方式,那么项目中的动态查询需要改写,也是不小的工作量。第三种,使用@Formula注解的方式,下面重点说说这种方式。
使用介绍
@Formula的作用是计算出一个临时的属性值,我们可以利用它,去关联查询其他表中的某个字段为对象的属性赋值,而这个属性是不持久化到数据库中的。
用代码描述一下会比较直观:
建立两个实体类
班级字典
@Data
@Entity
public class DictClass {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String classCode;//班级编号
private String className;//班级名称
}
学生类
@Data
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name; //名字
@Column(name = "CLASS_CODE")
private String classCode;//班级编号
@Formula("(select d.class_name from dict_class as d where d.class_code = class_code)")
private String className;//班级名称
}
@Formula("(select d.class_name from dict_class as d where d.class_code = class_code)")意思就是从数据库的dict_class表中查询到class_name字段的数据,赋值到className属性上。"="后面的class_code对应的时@Column里的class_code
持久层
public interface StudentRepo extends JpaRepository<Student, Long> {
//很持久
}
控制层
@RestController
@RequestMapping("/formula")
@Api(tags = "formula测试接口")
public class FormulaController {
@Autowired
StudentRepo studentRepo;
@GetMapping
public List<Student> findAll(){
return studentRepo.findAll();
}
}
测试一下,获取成功

注意事项
虽然看起来很简单,不过还是有好些个需要注意的地方,一言不合就失效。
1.网上好多人说@Formula必须用在属性上,其实不是的,@Formula 要与@Id注解同时用在属性上,或者同时用在在get方法上,否则@Formula失效。
2.如果查询中用到了where,那么需要给表起一个别名,否则@Formula失效。
3.@Formula与@Transient不能同时使用,否则@Formula失效。
4.使用@Formula注解的属性不需要在数据库表中建立与之对应的字段,并且即使建立了也没有作用,加上@Column注解也不行。
使用过程中遇到的坑
当持久层使用原生sql查询时,会造成NPE异常。
在持久层添加
@Query(nativeQuery = true,value = "select * from student")
List<Student> findByNative();
测试一下

这似乎是因为@Formula屏蔽了className字段,框架获取@Column对应的name时拿到null导致的,我未能找到具体原因,所以用起来还是很不随心,不知道大家是否有好的处理方案,欢迎指教!
如何使用JPA的@Formula注解?的更多相关文章
- Hibernate @Formula 注解方式
1.Formula的作用 Formula的作用就是用一个查询语句动态的生成一个类的属性 就是一条select count(*)...构成的虚拟列,而不是存储在数据库里的一个字段.用比较标准的说法就是: ...
- JPA学习(2)注解
上一篇学习了JPA的helloworld,也初略的使用了一些注解,接下来就细细的了解一下有哪些注解,和这些注解的作用 JPA的基本注解: ①@Entity,@Table,@Id,@GeneratedV ...
- 利用Eclipse的JPA自动生成注解实体
新公司用的SSH(springmvc)框架,看代码的时候,发现没有hbm.xml文件,全部使用的注解形式.在一次闲聊的时候问同事,这么多entity 写起来不麻烦么.同事说根据数据库自动生成的.于是 ...
- 使用JPA中@Query 注解实现update 操作
spring使用jpa进行update操作主要有两种方式: 1.调用保存实体的方法 1)保存一个实体:repository.save(T entity) 2)保存多个实体:repository.sav ...
- JPA之@GeneratedValue注解(转)
JPA的@GeneratedValue注解,在JPA中,@GeneratedValue注解存在的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键), ...
- 二十、springboot之jpa开发@MappedSuperclass 注解说明
@MappedSuperclass使用条件: 当我们进行开发项目时,我们经常会用到实体映射到数据库表的操作,此时我们经常会发现在我们需要映射的几个实体类中,有几个共同的属性,例如编号ID,创建者,创建 ...
- JPA之@GeneratedValue注解
JPA的@GeneratedValue注解,在JPA中,@GeneratedValue注解存在的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键), ...
- jpa和hibernate注解
http://www.objectdb.com/api/java/jpa/JoinColumns 用hibernate和jpa annotation 大概一年多了,今天闲来无事,对他们关联关系元数据写 ...
- JPA的事务注解@Transactional使用总结
在项目开发过程中,如果您的项目中使用了Spring的@Transactional注解,有时候会出现一些奇怪的问题,例如: 明明抛了异常却不回滚? 嵌套事务执行报错? ...等等 很多的问题都是没有全面 ...
随机推荐
- Jenkins 部署(基于 Linux)
1.安装 JDK 我不列出来了,自行百度 java -version 2.安装 tomcat (1)创建目录 tomcat8 (2)导入 tomcat 文件到 tomcat8 录中并解压 (3)启动 ...
- 《新版阿里巴巴Java开发手册》提到的三目运算符的空指针问题到底是个怎么回事?
最近,阿里巴巴Java开发手册发布了最新版--泰山版,这个名字起的不错,一览众山小. 新版新增了30+规约,其中有一条规约引起了作者的关注,那就是手册中提到在三目运算符使用过程中,需要注意自动拆箱导致 ...
- dbcp数据源连接池
一.数据源连接池 我们之前利用jdbc连接数据库,每次都要创建连接对象,销毁连接对象,如果并发访问量比较大,这样肯定比较辣 浪费数据库的效率,我们可以像之前mybatis中缓存查询到的数据一样,可以把 ...
- STM32 TIM1高级定时器配置快速入门
layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 重点内容 时基单元 计 ...
- 技术人的福音!教你如何使用Typora+PicGo实现图片自动上传功能
前言 写技术文章的小伙伴,对于 Typora 肯定不陌生,用来编写 Markdown 特别的方便. 但是,有个问题,就是当我们插入一个图片,并且使之可以在公网访问时,操作流程特别的麻烦. 首先,你需要 ...
- [poj1741 Tree]树上点分治
题意:给一个N个节点的带权树,求长度小于等于K的路径条数 思路:选取一个点作为根root,假设f(root)是当前树的答案,那么答案来源于两部分: (1)路径不经过root,那么就是完全在子树内,这部 ...
- 小心了!Kubernetes自动化操作工具将让你失去工作
运行Kubernetes的人已经花费太多时间在操作上,企业正在考虑为Kubernetes编写自动化工具. 尽管IT部门的大部分职位都会增加,但职业顾问说,计算机操作员预计会减少.这个角色涉及运行She ...
- spring boot构建restful服务
使用spring boot快速构建出restful服务 JPA实现REST 创建spring boot项目,在项目文件pom.xml中添加以下依赖: <dependency> <gr ...
- 这或许是最详细的JUC多线程并发总结
多线程进阶---JUC并发编程 完整代码传送门,见文章末尾 1.Lock锁(重点) 传统 Synchronizd package com.godfrey.demo01; /** * descripti ...
- jquery监听input
$(function(){ //输入框正在输入时 $("#ipt").on('input',function(){ if(!($('#ipt').val()=='')){ $(&q ...