我正在使用Spring Data JPA和Hibernate。
我有一个类,其复合键映射到数据库表。
当我使用JPARepository扩展接口对象执行保存操作时,在控制台中看到以下日志:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
Hibernate: insert into RoleFunctionality_Mapping (functionalityId, roleId) values (?, ?)
这是当我用相同的数据重复该操作时看到的:
Hibernate: select rolefuncti0_.functionalityId as function1_4_0_, rolefuncti0_.roleId as roleId2_4_0_ from RoleFunctionality_Mapping rolefuncti0_ where rolefuncti0_.functionalityId=? and rolefuncti0_.roleId=?
看起来Spring Data首先检查数据库中是否存在Key,然后继续执行插入操作。
应该有一种方法可以捕获休眠中找到的信息(数据库中的条目/密钥存在于数据库中)吗?我们如何检查呢?
最佳答案
没有这样的方法。 Hibernate无法确定主键是否存在,除非它本身会发出SQL查询。 Hibernate假定此检查是由应用程序逻辑完成的,以使其成为性能优化的问题。
Hibernate唯一注意到重复键问题的机会是来自数据库(或JDBC层)的SQLException,通知有关id字段的唯一约束冲突。并且一如既往,如果发生SQLException,则应将Hibernate会话视为无效(因为Hibernate不能确保考虑拦截器和侦听器处理的有效状态)。
因此,发出额外查询的春季方式是必经之路,除非您可以使用其他计数器,批量获取和保留免费ID或使用应用程序范围内的事件/消息传递来提供其他逻辑来确保该密钥在数据库中尚不存在,同步实体ID分配的解决方案。