Отображение расчетных свойств с помощью JPA
Есть ли способ сопоставить вычисленное свойство с помощью JPA?
Предполагая, что у меня есть объект Invoice
с одним или несколькими InvoiceLineItems
внутри него, я хочу иметь постоянное вычисляемое свойство в классе Invoice
, которое дает мне общую сумму:
class Invoice {
...
@Column(name = "TOTAL_AMOUNT")
public BigDecimal getTotalAmount() {
BigDecimal amount = BigDecimal.ZERO;
for (InvoiceLineItem lineItem : lineItems) {
amount = amount.add(lineItem.getTotalAmount());
}
return amount;
}
}
Теперь я мог бы создать защищенный метод no-op setTotalAmount
, чтобы сделать JPA счастливым, но мне было интересно, есть ли способ дать JPA знать, что сопоставление является только одним способом и чтобы избежать создания избыточного метода setter.
Спасибо,
Aleks
Ответы
Ответ 1
То, что вы описали, не является рассчитанным свойством в смысле JPA. Вы сами вычисляете его в своем методе - просто отметьте этот метод как @Transient
, и JPA проигнорирует его.
Если вам действительно нужно вычисленное свойство (где "вычисленное" означает "вычисленное через выражение SQL" ), вам нужно будет аннотировать его в соответствии с вашим поставщиком JPA. Для Hibernate вы можете сделать это через аннотацию @Formula
:
@Formula("col1 * col2")
public int getValue() {
...
}
У других поставщиков могут быть свои собственные способы настройки; нет стандарта JPA.
Ответ 2
Я знаю, что я не занимаюсь этой нитью, но, возможно, это может помочь кому-то.
Если вы хотите вычислить значение при чтении, аннотация @PostLoad
может быть тем, что вы хотите:
@Transient
private BigDecimal totalAmount;
@PostLoad
public void onPostLoad() {
BigDecimal amount = BigDecimal.ZERO;
for (InvoiceLineItem lineItem : lineItems) {
amount = amount.add(lineItem.getTotalAmount());
}
this.totalAmount = amount;
}
Ответ 3
Возможно, для этого можно использовать аннотацию PrePersist.
@Column(name = "TOTAL_AMOUNT")
private BigDecimal totalAmount;
@PrePersist
public void updateTotalAmount() {
BigDecimal amount = BigDecimal.ZERO;
for (InvoiceLineItem lineItem : lineItems) {
amount = amount.add(lineItem.getTotalAmount());
}
this.totalAmount = amount;
}