问题:我的表中有只读数据。它的行没有 id - 只有复合键定义它的身份。我希望它作为我的应用程序中的值对象(用 DDD 术语)。
研究:但是如果我使用 @Embeddable
注释而不是 @Entity
和 @Id id
字段,那么 javax. persistence.metamodel
没有看到它,并在 Metamodel metamodel.embeddable(MyClass.class);
上显示 Not an embeddable
。我可以用 @Entity 类包装它并自动生成 id,但这不是我在架构上想要实现的目标。
问题:JPA 是可嵌入的值对象吗? Embeddable 可以在没有父实体的情况下存在并表示表吗?
最佳答案
有关于该主题的许多文章表明这是一个真正的 JPA 不便:
- http://thepaulrayner.com/persisting-value-objects/
- https://www.baeldung.com/spring-persisting-ddd-aggregates
- https://paucls.wordpress.com/2017/03/04/ddd-building-blocks-value-objects/
- https://medium.com/@benoit.averty/domain-driven-design-storing-value-objects-in-a-spring-application-with-a-relational-database-e7a7b555a0e4
他们中的大多数人建议基于规范化关系数据库的解决方案,其中 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/