2013-08-17 8 views
6

を洗い流すか、返すために私は春の3.2.3を使用し、4.2.3およびJDK 7オブジェクトが保存されていない一時的なインスタンスを参照します:どのように保存されたオブジェクト

休止状態私は、単純なエンティティがあります

@Entity 
public class Language { 
    @Id 
    @GeneratedValue 
    private long id; 

    @Column(nullable = false, length = 3, unique = true) 
    private String code; 
} 

を私は私が使用その後

sessionFactory.getCurrentSession().save(object); 

持つエンティティを保存DAOを使用@Transactional注釈付きメソッドと@Service注釈付きクラスを使用してこのエンティティのインスタンスを保存D は、私は常に例外を取得

@Entity 
public class EntityX { 
    @ManyToOne 
    @JoinColumn(nullable = false) 
    private Language language; 
     // ... 
} 

... ...

lang=new Language(); 
// ... 
languageService.saveLanguage(lang); 
e=new EntityX(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

EntityXManyToOne関係でそれを使用しEntityXを作成するためのLanguageエンティティは次のように定義されてを保存しました

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: somepackage.Language 

私はいくつかのカスケード定義をEntityX '他の投稿に示唆されているようにLanguageとの関係ですが、効果はありません。

保存されたLanguageエンティティを、一部のHQLクエリを使用してcodeで検索して再読み込みすると、すべて正常に動作しますが、「良い」とはかなり離れています。

save(...)メソッドorg.hibernate.Sessionは、保存されたオブジェクトを返しません。

誰もがどのようにそれを解決するためのアイデアを持っていますか?

答えて

5

は、あなたのコードは、単一の@Transactional方法でますか?
サービスメソッドへの呼び出し後に、トランザクションがコミットされ、セッションがクリアされるという問題が発生する可能性があります。エンティティを保存しようとすると、言語オブジェクトはセッションで検出されず、一時インスタンスとして管理され、エラーが発生します。

あなたのコードが単一トランザクションの場合、HibernateストアLanguageを強制的に強制的にエンティティを保存して有効な@Idエンティティに割り当てるように、flush()を試しましたか?

@ManyToOne(cascade = CascadeType.ALL) 
private Language language; 

として、あなたのコードを変更します:

すべての後 - - IMHOあなたは、エンティティと言語の依存関係を持っている場合は最良の選択です

e=new EntityX(); 
Language lang = new Language(); 
// ... 
e.setLanguage(lang); 
otherService.saveEntity(e); 

、あなたがする必要はありませんエンティティを2つのステップ(言語+エンティティ)で保持する。言語+エンティティを単一のアイテムとして管理する

PS:オブジェクトが同じままであるため、org.hibernate.Sessionのsave(...)メソッドは保存されたオブジェクトを返しません。変更)、オブジェクトのプロパティの変更(例えば、@Idとマークされたもの)!

EDIT:
オブジェクトを永続化する(つまり、session.save()を意味します)、すぐに挿入/更新されません。カスケードヒントなしHibernate lookはEntityXとLanguage間の依存関係を検出せず、EntityXを保存する前にSQLの言語挿入を実行しません。
languageService.save(language)呼び出しは、同じ@Transactionalの下にあり、session.commit()を持たないためsession.flush()が実行されません。最良のオプションは、Languageオブジェクトが一過性
サービスチェックコード(language entityX)を抽出し、すべて@Transactionalに入れて、Hibernateが引き続きエラーを出すかどうかをチェックすることができます。
私の最善の選択肢は、途中でflush()を実行している、または他の方法でマッピングを変更しているところです。

+0

コードは単一の '@ Transactional'メソッド内にあります。サービスメソッドも '@ Transactional'ですが、新しいトランザクションは必要ないので、既存のものが使われていると思います。私は1つの言語エンティティと多くのEntityXを持ち、それぞれが同じ言語エンティティを使用しているため、独自の言語を保存しました。 – t777

+1

私の編集をチェックしてください。コメントが長すぎます。私は明確であることを願っています、英語は母国語ではありません、ごめんなさい –

+0

こんにちは@ LucaBassoRicci、私は同じ問題を抱えていますが、私の技術は異なっています、あなたはこれを見てみることができます.. http://stackoverflow.com/questions/28279304 /保存時のエラー - オブジェクト - 外部キーオブジェクト参照 - 非保存 - –

2

まず、codeフィールドが主キーである(またはあなたが少なくとも休止状態のためのプライマリIDとしてそれを使用している)場合は、@Idを指定:

@Id 
@GeneratedValue(generator="assigned") 
@Column(length = 3) 
private String code; 

は休止状態を混乱することができ、ID列を指定しません少し。それについて私を引用していませんが。 save()はまだその後に動作しない場合

、あなたはmerge()使用することができます。

Language lang = new Language("XYZ"); 
lang = session.merge(lange); 
+0

すみません。私は自分のコードをあまりにも短くしました。 IDフィールドがあります。私は自分の投稿のコードに追加しました。私は保存の代わりにマージを使用しているときに同じ問題が発生しました。 – t777

関連する問題