如何使用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注解,有时候会出现一些奇怪的问题,例如: 明明抛了异常却不回滚? 嵌套事务执行报错? ...等等 很多的问题都是没有全面 ...
随机推荐
- Recursion and System Stack
递归是计算机科学中一个非常重要的概念,对于斐波那契那种比较简单的递归,分析起来比较容易,但是由于二叉树涉及指针操作,所以模仿下遍历过程中系统栈的情况. 以二叉树中序遍历为例演示: //二叉树定义 st ...
- 数据库SQL语言从入门到精通--Part 6--单表查询(快来PICK)
数据库从入门到精通合集(超详细,学习数据库必看) 查询操作是SQL语言中很重要的操作,我们今天就来详细的学习一下. 一.数据查询的语句格式 SELECT [ALL|DISTINCT] <目标列表 ...
- 别了,JavaScript;你好,Blazor
Web开发与JavaScript开发向来是同义词.直到WebAssembly的横空出世,WebAssembly (Wasm)是一种在浏览器中可以执行的二进制指令. WebAssembly 的 官方工具 ...
- python基础的一些题目
第一部分: 第二部分: 第三部分:
- commons-logging slf4j log4j 区别
日志门面 1.Apache通用日志接口(commons-logging.jar) Apache Commons包中的一个,包含了日志功能,必须使用的jar包.这个包本身包含了一个Simple Logg ...
- 布局问题杂(html和css)
\(一.删除线可以用一对strike标签括起来\) <p><strike>删除线可以用一对strike标签括起来</strike></p> \(\col ...
- SpringData Redis的简单使用
SpringDate Redis是在Jedis框架的基础之上对Redis进行了高度封装,通过简单的属性配置就可以通过调用方法完成对Redis数据库的操作,而且SpringData Redis使用了连接 ...
- Mysql常用sql语句(18)- union 全连接
测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 其实Mysql并没有全连接,Oracle才有全连 ...
- HBuilderX 打包 uniapp 项目 图片路径不显示(不正确)
打包h5项目本地服务运行正常 部署后页面显示空白 在根目录manifest.json中配置h5下的publicPath即可 "h5" : { "template" ...
- [hdu5375 Gray code]DP
题意:给一个二进制码,其中有一些位上为'?',对每个问号确定是'0'还是'1',最后以它对应的格雷码来取数,第i位为1则取第i个数,求取得的数的和的最大值. 思路:二进制码B转换成格雷码G的方法是,G ...