使用JPA映射计算的属性

时间:2009-08-31 22:21:58

标签: java jpa persistence

有没有办法使用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;
    }
}

现在,我可以创建一个受保护的无操作setTotalAmount方法来让JPA高兴,但我想知道是否有办法让JPA知道映射只是一种方式,并避免创建多余的setter方法。

谢谢, 阿莱克斯

3 个答案:

答案 0 :(得分:9)

您所描述的不是JPA意义上的计算属性。您在自己的方法中自己计算 - 只需将该方法标记为@Transient,JPA将忽略它。

如果您确实需要计算属性(其中“计算”表示“通过SQL表达式计算”),则需要根据JPA提供程序对其进行注释。对于Hibernate,您可以通过@Formula注释执行此操作:

@Formula("col1 * col2")
public int getValue() {
 ...
}

其他提供商可能有自己的方式来配置它;没有JPA标准。

答案 1 :(得分:5)

我知道我正在破坏这个帖子,但也许它可能有助于某人。

如果要计算读取值,@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;
}

答案 2 :(得分:4)

也许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;
}