使用JPA映射计算的属性

Ale*_*vic 11 java persistence 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢,亚历克斯

Chs*_*y76 10

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

如果您确实需要计算属性(其中"计算"表示"通过SQL表达式计算"),则需要根据JPA提供程序对其进行注释.对于Hibernate,你可以通过@Formula注释来做到这一点:

@Formula("col1 * col2")
public int getValue() {
 ...
}
Run Code Online (Sandbox Code Playgroud)

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

  • 你的例子很奇怪.如果你**存储**这个值并查询它,你为什么要在你的getter中重新计算它?然而,最重要的是,如果你要注释getter方法(而不是属性),你必须有一个相应的setter(它可能是私有的),以便JPA在你的实体上填充该值. (3认同)

LeC*_*Che 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;
}
Run Code Online (Sandbox Code Playgroud)