JPA 2.0持久化属性,没有setter

时间:2011-02-20 01:39:38

标签: java orm jpa properties eclipselink

我正在使用JPA 2.0,更准确地说是Eclipselink。这是我的问题:

我有一个像“isPaid”这样的属性的实体。该属性是实体执行某些其他字段的计算结果。因为这是从其他字段派生的,所以该属性没有setter方法。

举个例子,getter是这样的:

public boolean isPaid() {
  return this.totalAmount - this.amountPaid == 0;
}

这只是一个例子。问题是,我想要计算和保持这个属性,所以我可以做一个jpql查询,如:

SELECT d FROM Debt d WHERE d.isPaid = true

这可能吗?有没有解决方法呢?。

我不想检索所有实体来调用此方法,然后过滤那些返回true的实体。

2 个答案:

答案 0 :(得分:4)

看到这个:Mapping calculated properties with JPA

基本上你需要一个setter方式,以使JPA快乐。

答案 1 :(得分:4)

以下是几个选项:

1)创建一个直接执行所需操作的jpql查询:

select d from Debt d where (d.totalAmount - d.amountPaid) = 0

该方法的好处是它很简单并且始终有效。缺点是您的查询必须了解付费逻辑的计算方式。

2)创建一个存储计算值的持久付费值:

@Basic
private boolean paid;

public boolean isPaid() {
    return this.paid;
}

private void updateCalculations() {
    this.paid =  (this.totalAmount - this.amountPaid == 0);
}

// using int as example here
public void setTotalAmount(int totalAmount) {
    this.totalAmount = totalAmount;
    updateCalculations();
}
public void setAmountPaid(int amountPaid) {
    this.amountPaid = amountPaid;
    updateCalculations();
}

这种方法的好处是你可以创建一个直接检查布尔值的jpql查询,即

select d from Debt d where d.paid = true;

显然,该方法的缺点是您需要确保在更新值时随时重新计算值。但是,如果您只在访问时计算它,则可以减轻这种情况。这意味着在isPaid()方法中,您计算​​该值,将其分配给付费属性,然后返回该值。如果您决定采用这种方法,则需要添加一个执行付费计算的@PrePersist和@PreUpdate方法,并在将bean保留到数据存储区之前更新付费属性(确保始终覆盖付费值)

如果您对属性本身使用JPA注释,则可以使用没有setter的getter,并且仍然能够在数据库中正确检索和存储值。

相关问题