Spring JPA 复合 PK,带一个自动递增
Spring JPA composite PK with one auto-incremented
我正在尝试使用 Spring Boot 2.1.2.RELEASE + JPA(使用启动器)和 MySQL (InnoDB)。我有一个带有 2 个非抽象子 class 的抽象 class,我正在使用单个 table 继承策略。
我一直在寻找如何实现这一点,但每个 post 似乎都在寻找与我相同的答案,但最终都没有答案 (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().
}
我发现的第一个问题是 table 代。 MySQL 允许创建 PK,如果它被声明为
PRIMARY KEY (pk1, pk2)
但顺序不同
PRIMARY KEY (pk2, pk1)
创建 table 时,Hibernate 使用第二个,因此失败。还尝试更改字段顺序但无济于事。我认为这可能是 Hibernate 的问题,但我不确定。任何人都可以确认吗?无论如何,我通过手动创建 DDL 脚本并通过 Hibernate 禁用自动 DDL 解决了这个问题。
下一个问题,我没有找到答案,是实体在 table 中正确保存,但存储库的保存方法返回的 id 始终为 0。我是保存前手动设置 pk2,而 pk1 由 DB 完成。
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 是复合的并且我将一个字段留空。所以,我也认为这可能是一个错误。有一些 class 覆盖了 isNew() 方法,但它们似乎没有被使用。
我是不是做错了什么或者这是一个错误?帮助表示赞赏:)
不支持 @EmbededId 或 @IdClass 上的 @GeneratedValue(strategy = GenerationType.IDENTITY)。
这是一个与您的请求完全相关的错误,该错误已被 hibernate 拒绝 https://hibernate.atlassian.net/browse/ANN-268
这是另一个更近期的错误报告。注意这里 Vlad Mihalcea 评论:
This is not a Blocker, it's merely a Major issue. For instance, the
JPA spec does not even say if generated identifiers are allowed in a
Composite Identifier.
Anyway, this only works as @IdClass with sequence-based identifiers,
as explained in this article.
https://hibernate.atlassian.net/browse/HHH-9662
引用中的文章解释了如何在复合上映射@GeneratedValue(strategy = GenerationType.SEQUENCE)。
我正在尝试使用 Spring Boot 2.1.2.RELEASE + JPA(使用启动器)和 MySQL (InnoDB)。我有一个带有 2 个非抽象子 class 的抽象 class,我正在使用单个 table 继承策略。
我一直在寻找如何实现这一点,但每个 post 似乎都在寻找与我相同的答案,但最终都没有答案 (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().
}
我发现的第一个问题是 table 代。 MySQL 允许创建 PK,如果它被声明为
PRIMARY KEY (pk1, pk2)
但顺序不同
PRIMARY KEY (pk2, pk1)
创建 table 时,Hibernate 使用第二个,因此失败。还尝试更改字段顺序但无济于事。我认为这可能是 Hibernate 的问题,但我不确定。任何人都可以确认吗?无论如何,我通过手动创建 DDL 脚本并通过 Hibernate 禁用自动 DDL 解决了这个问题。
下一个问题,我没有找到答案,是实体在 table 中正确保存,但存储库的保存方法返回的 id 始终为 0。我是保存前手动设置 pk2,而 pk1 由 DB 完成。
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 是复合的并且我将一个字段留空。所以,我也认为这可能是一个错误。有一些 class 覆盖了 isNew() 方法,但它们似乎没有被使用。
我是不是做错了什么或者这是一个错误?帮助表示赞赏:)
@GeneratedValue(strategy = GenerationType.IDENTITY)。
这是一个与您的请求完全相关的错误,该错误已被 hibernate 拒绝 https://hibernate.atlassian.net/browse/ANN-268
这是另一个更近期的错误报告。注意这里 Vlad Mihalcea 评论:
This is not a Blocker, it's merely a Major issue. For instance, the JPA spec does not even say if generated identifiers are allowed in a Composite Identifier.
Anyway, this only works as @IdClass with sequence-based identifiers, as explained in this article.
https://hibernate.atlassian.net/browse/HHH-9662
引用中的文章解释了如何在复合上映射@GeneratedValue(strategy = GenerationType.SEQUENCE)。