Spring Boot JPA 复合主键只查询部分主键
来源:互联网 发布:ups 寿命 知乎 编辑:程序博客网 时间:2024/05/29 12:36
Spring Data JPA给了我们很强大的功能,我们只需要通过编写一个继承自JpaRepository的接口就能完成数据访问。最近使用过程中,碰到一个问题:
数据库的表中有多个主键,我们和数据库交互的实体(Entity)中只定义了其中部分主键,也就是数据库表中的字段多于Entity中定义的字段。当我们查询时发现,查询返回的结果和我们预想的完全不一致。
接下来我们来逐步验证并进行完善:
- 首先是建表,我们采用的是MySql数据库:
SET FOREIGN_KEY_CHECKS=0;-- ------------------------------ Table structure for `order_info`-- ----------------------------DROP TABLE IF EXISTS `order_info`;CREATE TABLE `order_info` ( `id` varchar(20) NOT NULL DEFAULT '', `time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `flag` varchar(1) DEFAULT NULL, `memo` varchar(100) CHARACTER SET utf8 DEFAULT NULL, PRIMARY KEY (`id`,`time`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;-- ------------------------------ Records of order_info-- ----------------------------INSERT INTO `order_info` VALUES ('1', '2017-07-12 10:18:35', '0', '1号订单');INSERT INTO `order_info` VALUES ('1', '2017-07-12 10:19:21', '1', '1号订单子订单1');INSERT INTO `order_info` VALUES ('1', '2017-07-12 10:19:59', '2', '1号订单子订单2');INSERT INTO `order_info` VALUES ('2', '2017-07-12 10:19:14', '0', '2号订单');INSERT INTO `order_info` VALUES ('3', '2017-07-12 10:19:17', '0', '3号订单');
设置了订单号(id)及下单时间(time)两个字段作为主键。
- Entity定义上,我们只引用了订单号(id)这一个主键
@Entity@Table(name = "order_info")public class OrderEntity implements Serializable { @Id private String id; private String flag; private String memo; //省略get、set语句…}
- 编写调用接口,根据订单编号获取订单信息
@RestController@RequestMapping(value = "/order")public class OrderController { @Autowired private OrderService orderService; @RequestMapping(value ="/get/{id}") @ResponseBody public List<OrderEntity> getOrder(@PathVariable("id") String id) { return orderService.getById(id); }}
- 启动工程后访问接口,发现返回的值和我们预期的值不一样,返回的3条记录竟然是一样的!!!
查看下Hibernate的运行日志:
Hibernate: select orderentit0_.id as id1_0_, orderentit0_.flag as flag2_0_, orderentit0_.memo as memo3_0_ from order_info orderentit0_ where orderentit0_.id=?
补全id后我们手动运行sql发现运行结果和数据库一致,并不是JPA返回给我们的结果。
- 分析下来,发现是JPA构建OrderEntity实体类时判断主键仅为id,将查询结果转换为实体时默认取第一条数据进行反序列化,导致返回的三条数据都是默认数据库返回结果中id=1的第一条数据。
对于这种情况,我们可以通过添加@IdClass注解的方式来完善我们的查询结果。@IdClass故名思意说明主键是一个集合类,类包含的全部字段均为主键。
所以我们目前有两种方案可以实施:
- 新建一个类,添加@IdClass注解,将表结构的全部主键都引入(id,time);
- 在现有类上添加@IdClass,将我们查询的所有字段都标记为主键。
这里我们选择了方案2。
@Entity@Table(name = "order_info")@IdClass(OrderEntity.class)public class OrderEntity implements Serializable { @Id private String id; private String flag; private String memo; //省略get、set语句…}
添加@IdClass(OrderEntity.class)后,JPA认为我们实体类中所有字段均为主键,将查询结果反序列化的时候会判定全部字段来取出,而不仅仅判定id就取出。我们看下执行的结果:
添加后,我们得到的结果和预期的一致了。小伙伴们有需求的话,也可以自行尝试下第一种方案。
最后附上源码下载链接。
https://github.com/Shallow-Xu/union_primary_key
阅读全文
1 0
- Spring Boot JPA 复合主键只查询部分主键
- Spring Data Jpa 复合主键
- Spring Data JPA使用复合主键
- Spring Data JPA使用复合主键
- JPA 复合主键
- JPA复合主键使用
- JPA复合主键案例
- JPA 复合主键
- 复合主键JPA
- JPA 复合主键
- JPA 复合主键
- jpa嵌入式复合主键
- Hibernate复合主键查询
- JPA 复合主键源码案例
- jpa复合主键的使用
- 复合主键的查询方法
- JPA双向关系配置&复合主键
- JPA关联映射 - 复合主键映射
- python ltp使用
- 从零开始学java(八)流程控制
- 数据库账号创建顺序问题
- hdu 1272 小希的迷宫(并查集)
- java.lang.UnsupportedClassVersionError 解决方案
- Spring Boot JPA 复合主键只查询部分主键
- 背包问题(动态规划)
- Gson转list
- hbase安装
- Android Studio 运行时乱码
- FastJson高性能JSON开发包
- CodeForces569C【你会不会暴力啊】
- Retrofit基础入门
- Python 3从入门到精通13-读文件内容