2009-08-31 12 views
11

JPAを使用して計算されたプロパティをマップする方法はありますか?JPAで計算されたプロパティをマッピングする

私はその中の一つ以上のInvoiceLineItemsInvoiceオブジェクトを持っていると仮定すると、私は私の総量与え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; 
    } 
} 

を、私が作成することができますJPAを幸せにするための保護されていないsetTotalAmountメソッドがありますが、JPAにマッピングが片方だけであることを知らせ、余分なセッターメソッドを作成しないようにする方法があるのだろうかと思いました。

おかげで、 ALEKS

答えて

9

何を説明してきたことはJPAの意味での計算プロパティではありません。メソッド内で自分自身を計算しています。そのメソッドを@Transientとマークするだけで、JPAはそのメソッドを無視します。

実際に計算されたプロパティが必要な場合(「計算された」とは「SQL式によって計算された」を意味します)、JPAプロバイダに従って注釈を付ける必要があります。休止状態のためには、@Formula注釈を経由してそれを行うだろう:

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

他のプロバイダがこれを設定するには、独自の方法を有していてもよいです。 JPA標準はありません。

+0

マーキング性が私を助けにはなりません:あなたは、読み取り上の値を計算したい場合は

@PostLoad注釈は何をしたいかもしれません。私はJPAがそれを無視しないようにしたい - 私はそれが直接子テーブルから情報を集約することなくそれを照会することができるように、データベースに残っている総量します。 私が求めているのは、不必要なセッターを実装しなくても、計算されたプロパティ(永続性とは完全に無関係なJavaの意味で)を永続化する方法です。 –

+3

あなたの例はかなり奇妙です。あなたが**この値を保存してそれに照会しているなら、どうしてあなたのゲッターでそれを再計算していますか?しかし、要点は、JPAがその値をあなたのエンティティに移入するために、(プロパティではなく)getterメソッドに注釈を付ける場合、対応するセッター(プライベートでもよい)を持たなければならないということです。 – ChssPly76

+0

私が与えた例は、私が働いているドメインモデルの過度の単純化です。これは、子どもに依存する各レベルで計算されたプロパティを持つ、1対多の関係のいくつかのレベルを持っています。 必要に応じてJavaの値を計算するのは、(深い)階層の子オブジェクトが追加、削除、または変更されるたびに合計を更新するよりもはるかに簡単です。そのため再計算します。 –

4

おそらく、このために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; 
} 
+0

これは間違いなく知ってうれしい、感謝。 しかし、私は –

+0

Braaaains ...私は、なぜあなたはプライベートの 'updateTotalAmount()を持っていないのでしょうか? ) 'メソッドを呼び出し、それを' getTotalAmount() 'アクセサと' @ PrePersist'から呼び出すのですか? –

5

私はこのスレッドを壊していることを知っていますが、おそらく誰かを助けるかもしれません。 @Transientとして

@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

実際にはOPの質問に対する答えではありませんが、 OPと少し違ってほしいので、私の質問に答えてください...ここに投稿していただきありがとうございます!+1 –

関連する問題