Reputation: 131
Is there a way to map a calculated property using JPA?
Assuming I have an Invoice
object with one or more InvoiceLineItems
within it, I want to have a persistent calculated property on the Invoice
class that gives me the total amount:
class Invoice {
...
@Column(name = "TOTAL_AMOUNT")
public BigDecimal getTotalAmount() {
BigDecimal amount = BigDecimal.ZERO;
for (InvoiceLineItem lineItem : lineItems) {
amount = amount.add(lineItem.getTotalAmount());
}
return amount;
}
}
Now, I could create a protected no-op setTotalAmount
method to make JPA happy, but I was wondering if there is a way to let JPA know that the mapping is one way only and to avoid creating a superfluous setter method.
Thanks, Aleks
Upvotes: 11
Views: 19224
Reputation: 1286
I know that I am necro-ing this thread, but maybe it might help somebody out.
If you want to calculate the value on read, the @PostLoad
annotation might be what you want:
@Transient
private BigDecimal totalAmount;
@PostLoad
public void onPostLoad() {
BigDecimal amount = BigDecimal.ZERO;
for (InvoiceLineItem lineItem : lineItems) {
amount = amount.add(lineItem.getTotalAmount());
}
this.totalAmount = amount;
}
Upvotes: 5
Reputation: 34014
Perhaps the PrePersist annotation can be used for this.
@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;
}
Upvotes: 5
Reputation: 100706
What you've described is not a calculated property in JPA sense. You're calculating it yourself within your method - just mark that method as @Transient
and JPA will ignore it.
If you truly need a calculated property (where "calculated" means "calculated via SQL expression"), you'll need to annotate it according to your JPA provider. For Hibernate you'd do that via @Formula
annotation:
@Formula("col1 * col2")
public int getValue() {
...
}
Other providers may have their own ways to configure this; there's no JPA standard.
Upvotes: 10