我正在尝试使用域驱动开发来实现基于JPA的解决方案,并且已经找到了一个我找不到任何解决方案的用例。我正在将JPA与Hibernate和Spring Boot结合使用。
这是一个简化的示例。假设您有一个值对象:
@Embeddable
public class AmountWithCurrency {
private BigDecimal amount;
@Embedded
@AttributeOverride(name="id", column=@Column(name = "CURRENCY_ID"))
private CurrencyId currencyId;
protected AmountWithCurrency() {
//for JPA
}
public AmountWithCurrency(BigDecimal amount, CurrencyId currencyId) {
this.amount = amount;
this.currencyId = currencyId;
}
其中CurrencyId是另一个@Embeddable,仅包含长ID字段。
然后我有一个包含两个字段的实体:
@Embedded
@AttributeOverrides({
@AttributeOverride(name="amount", column=@Column(name = "AMOUNT1")),
})
private AmountWithCurrency amount1;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="amount", column=@Column(name = "AMOUNT2")),
})
private AmountWithCurrency amount2;
请注意,我希望这两个字段在表中共享相同的DB列CURRENCY_ID。显然,如果尝试使用此代码,则会出现以下异常:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Repeated column in mapping for entity: com.MyEntity column: currency_id (should be mapped with insert="false" update="false")
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:402)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
我尝试过在线搜索,但没有找到任何解决方案。
可能的解决方案: 只需在表中创建两个不同的currency1Id和currency2Id列,然后将每个值对象映射到该列即可-可以,但是在两个字段上都无法使用共享货币。我可以在实体级别上处理共享货币验证,但是我认为如果我不希望在此处添加额外的db列,这只是一个不必要的设计。另外,如果我在涉及列的表上有诸如PRIMARY KEY或UNIQUE约束之类的东西,那一切就会失去控制。
也许我没有想到过与实体生命周期挂钩相关的魔术?
感谢您的评论,感谢您的宝贵时间。
答案 0 :(得分:0)
仅供参考,我确实找到了一种方法来实现此目的,方法是将第二个字段更改为裸机金额-因此在内部,currencyId只有一个字段。 接下来,我为amount2作了一个吸气剂,它将使用第一个金额中的currencyId来重建整个实例。 像这样:
"legend": {
"valueWidth": 100,
"valueAlign": "left",
"valueText": "[[close]]",
"periodValueText": "[[value.close]]",
},
这仍然不是一个完美的解决方案,因为它仍然可能导致查询等问题。但是目前看来,这对我来说是有用的。希望对别人有帮助。