Java JPA中带有@EmbeddedId的@GeneratedValue的可能替代方案

Java JPA中带有@EmbeddedId的@GeneratedValue的可能替代方案,java,hibernate,jpa,spring-data-jpa,Java,Hibernate,Jpa,Spring Data Jpa,我的实体有这样一个包装标识符 @Entity public class Article { @EmbeddedId private ArticleId articleId; .... } ArticleId articleId = ArticleRepository.nextIdentity(); 在我的体系结构中,多个应用程序实例(都相同)连接到同一数据源 所以@GeneratedValue(strategy=GenerationType.IDENTITY)看

我的实体有这样一个包装标识符

@Entity
public class Article {
   
   @EmbeddedId
   private ArticleId articleId;

   ....
}

ArticleId articleId = ArticleRepository.nextIdentity();
在我的体系结构中,多个应用程序实例(都相同)连接到同一数据源
所以
@GeneratedValue(strategy=GenerationType.IDENTITY)
看起来不错
因为即使实例A和实例B尝试同时创建
帐户
,其Id也由数据库保证

问题是
@GeneratedValue
只能与
@Id
注释一起使用(
@Id
不适用于
EmbeddedId

PersistenceUnitUtil.getIdentifier(对象实体)
可以作为替代方案吗?像这样,

@Entity
public class Article {
   
   @EmbeddedId
   private ArticleId articleId;

   ....
}

ArticleId articleId = ArticleRepository.nextIdentity();
我不确定它是否会导致比赛状态。
PersistenceUnitUtil.getIdentifier(对象实体)
能否保证跨不同应用程序实例(JVM)的唯一id?我不这么认为


在这种情况下,有什么替代方案是可能的?

一种解决方案是使用
@IdClass
来摆脱嵌套属性并能够生成标识符(因为嵌套属性是“分配”的,无法生成,所以调用
PersistenceUnitUtil.getIdentifier(对象实体)
在这里没有帮助)。如需完整指南,请参阅(也可在注释中@SternK的链接答案中链接)

@IdClass
可以如下所示:

public class ArticleId implements Serializable {
  private Long id;
}
实体可以使用它:

@Entity
@IdClass(ArticleId.class) // specified dependency
public class Article {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  private Long id;

  // expose "typed" id:
  public ArticleId getId() {
    return new ArticleId(id);
  }
}
Spring数据
@Repository
s还可以与相应的
@IdClass
对象一起使用,例如:

@Repository
public interface UserEntityRepository extends JpaRepository<Article, ArticleId> {
}

// would offer e.g. this method:
repository.findById(new ArticleId(123L));
@存储库
公共接口UserEntityRepository扩展了JpaRepository{
}
//例如,将提供以下方法:
findById(新的ArticleId(123L));

也许会有帮助。我最初也考虑使用复合标识符,但没有理由使用复合标识符。我的第一种方法是使用两个身份(指IDDD,沃恩·弗农)。一个是作为UUID(不同JVM中的唯一id)的域模型,另一个是数据库的代理标识(代理标识隐藏在继承层次结构中)。我只想使用一个数字序列Id,但hibernate似乎没有办法。我决定不创建类型ID,而是将其用作基本的长ID,因为我认为复杂性会增加。
@IdClass
方法也只适用于一个(生成的)字段!因此,您也可以通过这种方式实现一个类型化ID(例如,包装的Long),而不需要在
@IdClass
中有额外的
@ID
字段(调整了示例代码)。我的意思是“类型化ID”为
mediaccountId.class
,而不是
Long.class
。我想创建一个对
MediaAccountId.class
非原始
long
long.class
的依赖项。我更新了答案,即使实体有一个“非类型化”字段(已生成),它至少公开为“类型化”id,这与您想要实现的接近吗?是的,这接近我想要实现的目标。我认为你的答案是代理身份的另一个实现。我可以在继承层次结构中隐藏JPA机制的
Long id
,在域模型中只保留
ArticleId
。(即使与JPA机制相关的注释保留在域模型中,我也允许使用注释。为了便于实现,例如@Transactional)