2013-02-17 15 views
5

私は1つの関係に多くのでPAYMENTMETHOD Entityクラスを持つエンティティクラス支払いを持っています。@ManyToOne一方向のマッピング

私のPaymentMethodはマスターテーブルです。

マスターテーブルPaymentMethodに影響を与えずに支払いを保存したいと思います。

しかし、支払いを保存するたびに、PaymentMethodに新しい行が挿入されます。なぜ私は理解できませんでした。

SpringData saveを使用しています。

Payment.java

@Entity 
@Table(name="payment") 
public class Payment implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne(cascade={CascadeType.REFRESH,CascadeType.MERGE,CascadeType.PERSIST}) 
    @JoinColumn(name="payment_method_id") 
    private PaymentMethod paymentMethod; 

    //getter and setters 
} 

PaymentMethod.java

@Table(name="paymentmethod") 
public class PaymentMethod implements Serializable { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

@Column(name="name",unique=true ,nullable=false) 
private String name; 

//GETTER AND SETTERS 
} 

PAYMENT_METHOD DATA

ID | NAME 
1 | AA 
2 | BB 
3 | CC 

支払い後に重複名 PAYMENT_METHODのエントリを保存しますか?

私は理由を理解できませんか?私は、リポジトリの実体保存呼び出し支払いタイプ

のための簡単なCRUDRepositoryを作成している節約のために

私はどこから落ちているのかを教えてください。

コードは、この行を実行するたびに:

paymentMethodRepository.findByName(payment.getPaymentMethod().getName()); 

それは私が、コードは私がリポジトリから検索メソッドを呼び出すときに、それをフラッシュしようとした場合どのように把握することができません

Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.enrollment.domain.Payment.paymentMethod -> com.enrollment.domain.PaymentMethod 
    at org.hibernate.engine.spi.CascadingAction$8.noCascade(CascadingAction.java:380) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:176) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:448) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:448) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:423) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:264) 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) 
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:78) 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.firePersistOnFlush(SessionImpl.java:870) 
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:863) 
    at org.hibernate.engine.spi.CascadingAction$8.cascade(CascadingAction.java:346) 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:160) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:151) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) 
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) 
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1186) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1241) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) 
    at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:285) 

としてエラーが発生します。

私に何か不足していますか?

おかげで@JBと@spiritwalkerが解決しましたが、正確な根本原因を見つけることができないため、単に行動を議論することであまりにも多くの知識が追加されます。

Behaviour .. 

Open Transaction 
    1. validate 
    2. save child 
    3. validate and update 
    4. save parent 
Close Transaction 

it was giving above error. 

Now, after code change it worked 

Open Transaction 
    1. validate 
    2. validate and update 
    3. save child 
    4. save parent 
Close Transaction 
+1

問題は、ステップ3で、データベースのクエリを実行していることです。したがって、Hibernateを実行する前に、メモリ内の変更をフラッシュして、メモリに保存された新しい値がクエリに確実に反映され、データベースにまだ格納されていないことを確認します。メモリ内の状態が有効でないため、この例外が発生します。 –

+0

しかし、私はまだトランザクション(readonly = false)であるので、選択クエリを実行すると、フラッシュは起こらないはずです。 [注:マスタデータに対して選択が実行されました]。 –

+0

いいえ、私はそうは思わない。取引で多くの支払いを作成し、後で同じ取引で、特定のタイプのすべての支払いを一覧表示するとします。作成した支払いは(JDBCを使用して支払いを挿入した場合と同じように)結果に含める必要があります。セッションがフラッシュされるのはこのためです。 –

答えて

2

お支払いエンティティからカスケード= {CascadeType.REFRESH、CascadeType.MERGE、CascadeType.PERSIST}を削除します。

あなたが言ったように、PaymentMethodはマスターテーブルなので、PaymentMethodまでの支払いからカスケード操作が発生しないようにする必要はありません。

+0

私がそれを削除すると、分離しようとしているエンティティを保存しようとしています。 –

+0

PaymentMethodエンティティインスタンスを取得し、それをPaymentエンティティに割り当てる必要があります。 – spiritwalker

+0

これを行う場合は、同じトランザクションでPaymentMethodの取得と支払いの保存が行われていることを確認できますか? –

3

支払いの作成/変更時にPaymentMethodを作成/修正したくないので、まずカスケードを削除します。その後

、あなたが支払いを作成し、あなたはそれがに関連付ける既存のPAYMENTMETHODそれを割り当てます。

PaymentMethod existingPaymentMethod = em.find(PaymentMethod.class, idOfThePaymentMethod); 
Payment payment = new Payment(); 
payment.setPaymentMethod(existingPaymentMethod); 
em.persist(payment); 
+0

springリポジトリは、idがnullの場合に内部的に同じ処理を行うsaveメソッドを提供します –

+0

nullのIDがある場合は?春のリポジトリはあなたが彼に与えるオブジェクトを取ります。あなたが彼に既存のものを与えるのではなく新しいPaymentMethodを与えるなら、それはあなたが望むようにうまくいかないでしょう。 –

+0

正しいオブジェクトを設定した後も、同じ方法で正しく動作します。理由を理解できませんでしたか? –

関連する問題