如何使用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注解,有时候会出现一些奇怪的问题,例如: 明明抛了异常却不回滚? 嵌套事务执行报错? ...等等 很多的问题都是没有全面 ...
随机推荐
- OSG程序设计之更新回调
更新回调(Update Callback)涉及到一个类:osg::NodeCallback.这个类重载了函数调用操作符.当回调动作发生时,将会执行这一操作符的内容. 如果节点绑定了更新回调函数,那么在 ...
- django 整理数据库文档时,从mysql导出的表中没有注释的解决方案
公司要将Django项目重构成Java项目,也就有了整理数据库文档的经历....... 由于django从model迁移时没有将注释(也就是模型类中的verbose_name)写进mysql的表中,导 ...
- 201771030120-王嫄 实验一 软件工程准备 <课程学习目的思考>
项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/nwnu2020SE 这个作业要求链接 https://www.cnblogs.com/nwnu- ...
- 如何将项目上传至GitHub?
心血来潮的一天,突然想写点什么哈哈哈哈. 那就写写如何将项目上传到GitHub(矫情,上传个项目还要写个文章) 第一步:下载Git https://git-scm.com/download/win 下 ...
- 新书《OpenShift云原生架构:原理与实践》第一章第三节:企业级PaaS平台OpenShift
近十年来,信息技术领域在经历一场技术大变革,这场变革正将我们由传统IT架构及其所支撑的臃肿应用系统时代,迁移至云原生架构及其所支撑的敏捷应用系统时代.在这场变革中,新技术的出现.更新和淘汰之迅速,以及 ...
- 【Hadoop离线基础总结】linux基础增强
linux基础增强 查找命令 grep命令 (print lines matching a pattern) 概述: grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打 ...
- Node教程——封装一个token验证器
重要说明 这个轮子是 使用 express@5.0 + MongoDB构建起来的一个 node后台通用的验证器,里面主要讲的就是使用jwt,token进行验证,当然你想使用session也没问题,但是 ...
- DNSlog注入学习
之前一直有看到过DNSlog这个字眼,但一直没有好好去了解一下,最近又接触到了刚好来深入学习下 0x01 什么是DNSlog 我们都知道DNS就是将域名解析为ip,用户在浏览器上输入一个域名A.com ...
- zookeeper和Eureka的区别
RDBMS==>(MySql,Oracle,SqlServer等关系型数据库)遵循的原则是:ACID原则 A:Atomicity 原子性 C:Consistency 一致性 I:Isolatio ...
- android 防止多次点击,导致事件监听响应到其他界面
下面有个案例: A点击的时候就跳转到B界面,点击B界面后结束,返回到A界面中 1.此时在B界面中,设置点击事件,点击后结束B v.setOnClickListener(new OnClickListe ...