2009-08-31 23 views
11

JPA kullanılarak hesaplanan bir özelliği eşlemek için bir yol var mı?JPA ile hesaplanan özellikleri eşleme

ben onun içinde bir veya birden fazla InvoiceLineItems ile Invoice nesne var varsayarsak, bana toplam miktarı verir Invoice sınıfına kalıcı hesaplanmış özelliği vardır istiyorum: Şimdi

class Invoice { 
    ... 

    @Column(name = "TOTAL_AMOUNT") 
    public BigDecimal getTotalAmount() { 
     BigDecimal amount = BigDecimal.ZERO; 
     for (InvoiceLineItem lineItem : lineItems) { 
      amount = amount.add(lineItem.getTotalAmount()); 
     } 
     return amount; 
    } 
} 

, ben oluşturabilir JPA'yı mutlu etmek için No-op setTotalAmount yöntemini korumalı, ancak JPA'nın haritalamanın tek yol olduğunu ve gereksiz bir setter metodu oluşturmasını engellemenin bir yolu olup olmadığını merak ediyorum.

sayesinde Aleks

cevap

9

Ne tarif ettik JPA anlamda bir hesaplanmış özellik değildir. Kendi yönteminiz içinde kendiniz hesaplıyorsunuz - bu yöntemi @Transient olarak işaretleyin ve JPA bunu yoksaymayacaktır.

Hesaplanmış bir özelliğe ihtiyacınız varsa ("hesaplanan" ifadesi "SQL ifadesiyle hesaplanır" anlamına gelir), JPA sağlayıcınıza göre ek açıklama eklemeniz gerekir.

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

Diğer sağlayıcılar bu yapılandırmak için kendi yollarını olabilir;: hazırda için, @Formula açıklama yoluyla aynı şeyi yaparım JPA standardı yok.

+0

İşaretleme özelliği bana yardımcı olmaz: Eğer okuma üzerinde değerini hesaplamak istiyorsanız

, @PostLoad açıklama istediğini olabilir. JPA'nın bunu görmezden gelmesini istemiyorum - Toplam miktarın bir veritabanında kalmasını istiyorum, böylece çocuk masasından bilgi toplamak zorunda kalmadan doğrudan sorgulayabiliyorum. Öyleyse sorduğum şey, hesaplanmış bir özelliği (Java anlamında, kalıcılık ile tamamen ilgisiz), bunun için gereksiz ayarlayıcı uygulamak zorunda kalmadan nasıl devam ettirileceğidir. –

+3

Örneğiniz o zaman garip. ** bu değeri ** kaydedip üzerinde sorgulama yapıyorsanız, neden bunu alıcınızda yeniden hesaplıyorsunuz? Bununla birlikte, alt satırda, getto yöntemini (mülkün karşıtı olarak) ekliyorsanız, JPA'nın bu değeri kuruluşunuzda doldurması için karşılık gelen bir ayarlayıcı (özel olabilir) olması gerekir. – ChssPly76

+0

Verdiğim örnek, üzerinde çalıştığım etki alanı modelinin, birden çok ilişki düzeyine sahip, her bir düzeyde, çocuklara bağlı olarak hesaplanan özellik ile brüt aşırı basitleştirilmesidir. Gerektiğinde Java'daki değerin hesaplanması, (derin) bir hiyerarşi içindeki alt nesneler eklendiğinde, kaldırıldığında veya değiştirildiğinde, toplamı güncelleştirmeye çalışmaktansa, toplamı yeniden hesaplamaya başladığımdan önemli ölçüde daha kolaydır. –

4

Belki de PrePersist ek açıklaması bunun için kullanılabilir.

@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; 
} 
+0

Bu kesinlikle bilindiği için teşekkürler, teşekkürler Ancak, baktığımda her zaman güncellenmesi gereken toplama, sadece ısrar edilmeden önce değil, bu yüzden benim özel durumumda çalışmayacak. –

+0

Braaaains ... Yani, neden sadece özel bir 'updateTotalAmount'a sahip olmadınız?) metodunu alıp getTotalAmount() 'ın akseptörünün yanı sıra' @ PrePersist'' olarak adlandırın mı? Bu bir getterin anlamı değil mi? –

5

Bu ileti dizisini izlediğimi biliyorum, ancak belki de birilerine yardımcı olabilir. @Transient olarak

@Transient 
private BigDecimal totalAmount; 

@PostLoad 
public void onPostLoad() { 
    BigDecimal amount = BigDecimal.ZERO; 
    for (InvoiceLineItem lineItem : lineItems) { 
     amount = amount.add(lineItem.getTotalAmount()); 
    } 
    this.totalAmount = amount; 
} 
+1

Aslında OP'lerin sorusu yanıtı değil, tesadüfen, sadece doğru OP'den biraz farklı bir şey istediğim gibi MY soruma cevap verin ... Bu yüzden buraya gönderdiğiniz için teşekkürler! +1 –