具有一个自动递增的Spring JPA复合PK

时间:2019-05-27 01:28:54

标签: java hibernate spring-boot jpa spring-boot-jpa

我正在尝试使用复合主键持久化一个实体,该主键应使用Spring Boot 2.1.2.RELEASE + JPA(使用入门)和MySQL(InnoDB)自动递增。我有一个带有2个非抽象子类的抽象类,并且我在使用单表策略进行继承。

我一直在寻找如何实现这一目标的方法,但是每一个看起来与我一样的帖子最终都没有答案(example)。

我当前的设置是这样的(为清楚起见,省略了设置器,获取器和构造器)。

@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。事实证明,由于MyEntityPK与null不同(我设置了pk2),它返回了false。当然这不是我所期望的,因为考虑到我的PK是复合的并且我将一个字段留空,所以我实际上正在保存一个新实体。因此,我也认为这可能是一个错误。有一些类重写了isNew()方法,但似乎没有在使用它们。

我做错了什么,还是一个错误?感谢帮助:)

1 个答案:

答案 0 :(得分:0)

不支持@EmbededId或@IdClass上的

@GeneratedValue(strategy = GenerationType.IDENTITY)。

这是与您的请求完全相关的错误,已被休眠https://hibernate.atlassian.net/browse/ANN-268拒绝

这是另一个报告相同的错误。注意这里Vlad Mihalcea的评论:

  

这不是一个障碍,它只是一个重大问题。 例如,   JPA规范甚至没有说明是否允许在   复合标识符。

     

无论如何,这只能与具有基于序列的标识符的@IdClass一起使用,   如本文所述。

https://hibernate.atlassian.net/browse/HHH-9662

引文中的文章介绍了如何将@GeneratedValue(strategy = GenerationType.SEQUENCE)映射到组合上。