在我的 OpenXava 应用程序中,我有一个带有 @OneToMany 实体集合的实体来创建主从结构。主实体 Invoice 有一个总的持久属性,每次用户添加、删除或更改细节时我都想更新它。OpenXava 生成的用户界面是这样的:
总计位于金额列的页脚,并在添加、修改或删除一行时更新。我使用 JPA 回调方法实现了这个效果,特别是细节类中的@PostPersist、@PostUpdate 和@PostRemove。
这是我的发票实体的代码:
@Entity @Getter @Setter
@View(members=
"year, number, date;" +
"customer;" +
"details;"
)
@Tab(properties="year, number, date, customer.name, total")
public class Invoice extends Identifiable {
@DefaultValueCalculator(CurrentYearCalculator.class)
@Column(length=4) @Required
int year;
@Column(length=6) @Required
int number;
@Required @DefaultValueCalculator(CurrentDateCalculator.class)
Date date;
@ManyToOne(optional=false, fetch=FetchType.LAZY)
Customer customer;
@Stereotype("MONEY")
BigDecimal total;
@OneToMany(mappedBy="invoice", cascade = CascadeType.ALL)
@ListProperties("product.number, product.description, unitPrice, quantity, amount[invoice.total]")
List<InvoiceDetail> details;
public void recalculateTotal() {
BigDecimal sum = BigDecimal.ZERO;
for (InvoiceDetail detail: details) {
sum = sum.add(detail.getAmount());
}
total = sum;
}
}
这对于 InvoiceDetail 实体:
@Entity @Getter @Setter
public class InvoiceDetail extends Identifiable {
@ManyToOne
Invoice invoice;
@ManyToOne(optional=false, fetch=FetchType.LAZY)
Product product;
@Required
BigDecimal unitPrice;
@Required
int quantity;
@Depends("unitPrice, quantity")
public BigDecimal getAmount() {
return new BigDecimal(getQuantity()).multiply(getUnitPrice());
}
@PostPersist @PostUpdate @PostRemove
private void recalculateInvoiceTotal() {
invoice.recalculateTotal();
}
}
上面的代码运行良好。但是,为了使用@ElementCollection 而不是@OneToMany 集合,我对其进行了重构,因此OpenXava 将生成一个用户可以在其中内联编辑详细信息的UI,方式如下:
为此,我将 Invoice 实体中的集合定义更改为:
@ElementCollection
@ListProperties("product.number, product.description, unitPrice, quantity, amount[invoice.total]")
List<InvoiceDetail> details;
我将 InvoiceDetail 重构为 @Embeddable:
@Embeddable @Getter @Setter
public class InvoiceDetail {
@ManyToOne(optional=false, fetch=FetchType.LAZY)
Product product;
@Required
BigDecimal unitPrice;
@Required
int quantity;
@Depends("unitPrice, quantity")
public BigDecimal getAmount() {
return new BigDecimal(getQuantity()).multiply(getUnitPrice());
}
@PostPersist @PostUpdate @PostRemove
private void recalculateInvoiceTotal() {
// invoice.recalculateTotal(); I no longer can access to invoice
System.out.println("[InvoiceDetail.recalculateInvoiceTotal()] "); // NEVER PRINTED
}
}
第一个问题是我无法从 InvoiceDetail 访问发票,但更糟糕的是 recalculateInvoiceTotal() 方法没有执行,从来没有。也就是说,JPA 回调方法不会在 @ElementCollection 的 @Embeddable 中执行。
JPA回调方法可以在@Embeddable中执行吗?有没有办法解决这个案子?