Отображение рассчитанных свойств с помощью JPA - PullRequest
11 голосов
/ 01 сентября 2009

Есть ли способ сопоставить вычисляемое свойство с использованием 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, что сопоставление является только одним способом и избежать создания избыточного метода сеттера .

Спасибо, Aleks

Ответы [ 3 ]

9 голосов
/ 01 сентября 2009

То, что вы описали, не является вычисляемым свойством в смысле JPA. Вы сами вычисляете его в своем методе - просто пометьте этот метод как @Transient, и JPA его проигнорирует.

Если вам действительно нужно вычисляемое свойство (где «вычислено» означает «вычислено с помощью выражения SQL»), вам необходимо аннотировать его в соответствии с вашим поставщиком JPA. Для Hibernate вы должны сделать это с помощью @Formula аннотации:

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

Другие провайдеры могут иметь свои собственные способы настройки этого; нет стандарта JPA.

5 голосов
/ 09 августа 2011

Я знаю, что я нахожусь в этой теме, но, возможно, это может кому-нибудь помочь.

Если вы хотите вычислить значение для чтения, аннотация @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;
}
4 голосов
/ 01 сентября 2009

Возможно, для этого можно использовать аннотацию 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...