我正在尝试使用一个复合主键来持久化一个实体,其中一个应该是自动递增的,使用Spring Boot2.1.2.RELEASE+ JPA (使用启动器)和MySQL (InnoDB)。我有一个带有两个非抽象子类的抽象类,并且我使用单表策略来继承。
我一直在寻找如何做到这一点,但每一篇似乎和我一样的帖子最终都没有答案(example)。
我当前的设置如下所示(为清楚起见,省略了setter、getter和构造函数)。
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@IdClass(MyEntityPK.class)
public abstract class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
long pk1; //Should be auto-incremented
@Id
OffsetDateTime pk2;
//More fields...
public class MyEntityPK implements Serializable {
private static final long serialVersionUID = 1L;
long pk1;
OffsetDateTime pk2;
}
@Repository
public interface MyEntityRepository extends CrudRepository<MyEntity, MyEntityPK> {
//Some methods like save().
}
我发现的第一个问题是表的生成。如果声明如下,MySQL允许创建PK
PRIMARY KEY (pk1, pk2)
但不是以不同的顺序
PRIMARY KEY (pk2, pk1)
在创建表时,Hibernate使用第二个表,因此失败了。我还试图改变字段顺序,但无济于事。我认为这可能是Hibernate的一个问题,但我不确定。有人能证实吗?无论如何,我通过手动创建DDL脚本并通过Hibernate禁用自动DDL解决了这个问题。
下一个问题(我没有找到答案)是实体被正确地保存在表中,但是存储库的save方法返回的id总是0。我在保存之前手动设置了pk2,而将pk1留给数据库来完成。
entity.setPk2(OffsetDateTime.now());
Entity savedEntity = repository.save(entity); //savedEntity has id 1 in table but 0 in code
在调试过程中,我到达了这个isNew() method。事实证明它返回的是false,因为MyEntityPK不同于null (我设置了pk2)。这当然不是我所期望的,因为我实际上是在保存一个新的实体,因为我的PK是复合的,并且我把一个字段留空了。所以,我也认为这可能是一个bug。有一些类覆盖了isNew()方法,但它们似乎没有被使用。
是我做错了什么,还是这是个bug?感谢您的帮助:)
发布于 2019-05-28 18:02:33
不支持@EmbededId或@IdClass上的@GeneratedValue(策略= GenerationType.IDENTITY)。
这是一个被hibernate https://hibernate.atlassian.net/browse/ANN-268拒绝的与您的请求完全相关的错误
这是另一个更新的bug,报告了同样的错误。请注意这里的Vlad Mihalcea评论:
这不是一个拦截器,它只是一个大问题。例如,JPA规范甚至没有说明在组合标识符中是否允许生成的标识符。
无论如何,这只适用于带有基于序列的标识符的@IdClass,如本文所述。
https://hibernate.atlassian.net/browse/HHH-9662
引文中的文章解释了如何在组合上映射@GeneratedValue(策略= GenerationType.SEQUENCE)。
https://stackoverflow.com/questions/56318664
复制相似问题