jpa - JPA 是否可嵌入值对象以及为什么它不能表示表

标签 jpa entity domain-driven-design value-objects embeddable

问题:我的表中有只读数据。它的行没有 id - 只有复合键定义它的身份。我希望它作为我的应用程序中的值对象(用 DDD 术语)。

研究:但是如果我使用 @Embeddable 注释而不是 @Entity@Id id 字段,那么 javax. persistence.metamodel 没有看到它,并在 Metamodel metamodel.embeddable(MyClass.class); 上显示 Not an embeddable。我可以用 @Entity 类包装它并自动生成 id,但这不是我在架构上想要实现的目标。

问题:JPA 是可嵌入的值对象吗? Embeddable 可以在没有父实体的情况下存在并表示表吗?

最佳答案

有关于该主题的许多文章表明这是一个真正的 JPA 不便:

他们中的大多数人建议基于规范化关系数据库的解决方案,其中 header 实体作为一个表,其值对象作为其他单独的表。

与非标准化只读表集成的必要性加剧了我的挫败感。 表没有 id 字段,用于存储对象值。没有与 header 实体表的绑定(bind)。使用 JPA 映射它是一个问题,因为只有具有 id 的实体才会被映射。

解决方案是用 MyEntity 类包装 MyValueObject 类,使 MyValueObject 成为其组合键:

@Data
@Entity
@Table(schema = "my_schema", name = "my_table")
public class MyEntity {

  @EmbeddedId MyValueObject valueObject;
}

作为一个小技巧,为了绕过 JPA 对默认空构造函数的要求,并且不破坏值对象的不变性,我们将其添加为私有(private)并牺牲字段的最终修饰符。隐私和没有 setter 符合值(value)对象最初的 DDD 思想:

// @Value // Can't use, unfortunately.
@Embeddable
@Immutable
@AllArgsConstructor
@Getter
@NoArgsConstructor(staticName = "private") // Makes MyValueObject() private.
public class MyValueObject implements Serializable {

  @Column(name = "field_one")
  private String myString;

  @Column(name = "field_two")
  private Double myDouble;

  @Transient private Double notNeeded;
}

还有一些 Lombok 的 @Value 注释来配置值对象。

关于jpa - JPA 是否可嵌入值对象以及为什么它不能表示表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59068602/

相关文章:

domain-driven-design - 领域驱动设计概念和与 CQRS 的关系

c# - 防止对象进入某种状态后被更改? (C#)

java - Hibernate删除了一条记录,但是记录并没有消失?

jpa - 当一个实体停止在 JPA 中进行管理时

wcf - 为什么我的 oData 服务( Entity Framework )不允许导航属性

Symfony2 : best approach to use business (repository) logic in entity or controller

c# - DDD(领域驱动设计)应用层

java - 查找时的 Eclipselink NPE

java - 创建完美的 JPA 实体

java - 如何使用@OneToMany 集合进行分页