Issue
I'm storing money/currency stored in the database which I want to map using JPA/Hibernate but one column is needed for two different mappings on the same entity.
DB Schema:
id: number
currency_code: string
total: number
sub_total: number
POJOs:
public class MyEntity {
private long id;
private Money total;
private Money subTotal;
}
public class Money {
private CurrencyCode currencyCode;
private BigInteger value;
}
The problem I'm hitting with JPA/Hibernate is that the currency_code
is needed to be mapped with both total
and subTotal
:
@Entity
@Table(name = "MyTable")
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Type(type = "customMoneyType")
@Columns(columns = {
@Column(name = "currency_code"),
@Column(name = "total"),
})
private Money total;
@Type(type = "customMoneyType")
@Columns(columns = {
@Column(name = "currency_code"),
@Column(name = "sub_total"),
})
private Money subTotal;
}
which leads to Caused by: org.hibernate.MappingException: Repeated column in mapping for entity
Both fields need to be updatable and nullable. The sharing of the column is legacy but not changeable in the near future. With that said, I'm open to less than ideal solutions which could work until the DB schema can be changed.
Solution
Just make MyEntity
to align exactly to the table. Keep the currencyCode
, total
and subTotal
fields as internal to the class and use OOP encapsulation technique to expose a methods for client work with them though the Money
value object. Something like :
@Entity
@Table(name = "entity")
public class MyEntity {
@Id
@Column(name = "id")
private long id;
@Column(name = "currency_code")
private CurrencyCode currenyCode;
@Column(name = "total")
private BigInteger total;
@Column(name = "sub_total")
private BigInteger subTotal;
public Money getTotal(){
return new Money(currenyCode, total);
}
public Money getSubTotal(){
return new Money(currenyCode, subTotal);
}
public void updateTotal(Money m){
this.currencyCode = m.getCurrenyCode();
this.total = m.getValue();
}
public void updateSubTotal(Money m){
this.currencyCode = m.getCurrenyCode();
this.subTotal = m.getValue();
}
}
Answered By - Ken Chan
Answer Checked By - Timothy Miller (JavaFixing Admin)