Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JPA映射计算属性_Java_Jpa_Persistence - Fatal编程技术网

Java 使用JPA映射计算属性

Java 使用JPA映射计算属性,java,jpa,persistence,Java,Jpa,Persistence,有没有一种方法可以使用JPA映射计算属性 假设我有一个Invoice对象,其中包含一个或多个InvoiceLineItems,我希望在Invoice类上有一个持久计算属性,该属性为我提供总金额: class Invoice { ... @Column(name = "TOTAL_AMOUNT") public BigDecimal getTotalAmount() { BigDecimal amount = BigDecimal.ZERO;

有没有一种方法可以使用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

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

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

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

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

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

我知道我正在坏死这根线,但也许它可以帮助别人

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

将属性标记为@Transient对我没有帮助。我不希望JPA忽略它——我希望数据库中保留的总量,这样我就可以直接查询它,而不必从子表中聚合信息。所以我要问的是如何持久化计算属性(在Java意义上,与持久化完全无关),而不必为它实现不必要的setter。如果您正在存储这个值并对其进行查询,为什么要在getter中重新计算它?然而,底线是,如果你要注释getter方法(而不是属性),你必须有一个相应的setter(它可能是私有的),以便JPA在你的实体上填充该值。我举的例子是我正在使用的域模型的过度简化,它有多个级别的一对多关系,在依赖于子级的每个级别上使用计算属性。在添加、删除或修改(深层)层次结构中的子对象时,根据需要在Java中计算值比尝试更新总计要容易得多,这就是我重新计算它的原因。但是,保留总计会使基于存储根对象的表的数量的查询大大简化,这就是我想在保存对象时保存它,但不想再次加载它(这就是为什么我不需要也不关心setter)。这就是为什么我希望有一种方法可以告诉JPA从持久性的角度将属性视为只写属性。无论如何,谢谢你的回答,我想我将不得不离开二传,因为二传除了让JPA开心之外没有其他用途:-(很高兴知道这一点,谢谢。但是,我需要在每次查看时更新总数,而不仅仅是在它被持久化之前,所以它在我的特定情况下不起作用。Braaains…我的意思是,你为什么不使用一个私有的
updateTotalAmount()
方法,并从
getTotalAmount()调用它呢?)
accessor,以及
@PrePersist
?这不是getter的作用吗?实际上不是OPs问题的答案,但顺便说一句,这正是我问题的正确答案,因为我想要与OP稍有不同的东西…所以感谢您在这里发布它!+1