3

私はJBossでhibernate/JPAを数か月間使用してきましたが、答えや解決策が見つからない質問が1つあります。

新しいエンティティ Bean を作成するときに、少なくとも EntityManager.persist(entityBean) を呼び出す前にクエリを実行できないようです。そうしないと、次のエラーが発生します。

TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing

例:

Job job = new Job();
Collection<Task> tasks = job.getTasks();
//entityManager.persist(job);
ActionPlan actionPlan = (ActionPlan) entityManager.createNamedQuery("ActionPlan.findByCommand").
                setParameter("type", RunOperation.Install).getSingleResult();
Task task = Task.getTask(actionPlan);
task.setActionPlan(actionPlan);
tasks.add(task);
task.setJob(job);

私の問題は、最初に「ジョブ」(コメントアウトされた行) を保持しないと createNamedQuery を呼び出せないことです。ActionPlan は Job と関係がありますが、NamedQuery (findByCommand) は Job に参加しません。私を悩ませているのは、新しく作成された Job がこのコンテキストでは面白くない場合でも、データベースにクエリを実行するために Job を永続化する必要があることです。
persist() の呼び出しをスニペットの最後に移動すると、上記のエラーが発生します。

私が取り組んでいるオブジェクトが永続化されていないことは承知していますが、永続化するとエラーが発生した場合にロールバックできなくなります。

これには解決策があると思いますので、誰かが答えを持っていれば、とても感謝しています。私は何が欠けていますか?

4

4 に答える 4

3

データベースにまだ存在しないものを照会できないのは当然のことですよね? できることは、トランザクションの使用を開始することです。単純なケースでは、セッションには、セッションを閉じるまで開いている 1 つのトランザクションがあります。その時点でトランザクションがコミットされ、すべての変更が永続化されます。エラーが発生した場合に必要なのは、トランザクションをロールバックすることだけです。

PSここの下部に、「典型的なトランザクションは次のイディオムを使用する必要があります」があります。

Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
    //do some work
    ...
    tx.commit();
}
catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
}
finally {
    sess.close();
}
于 2008-11-12T11:09:57.047 に答える
0

まだ永続化されていないものを照会できないことは承知していますが、これも当てはまりません。私が見つけたいのは、他のエンティティ Bean です。同じタイプだけでなく、私が持っているエンティティ Bean のすべてのタイプです。そして、TransientObjectException を取得します。

JBoss を使用していると言いましたか? J2EE と JPA を使用すると、サーバーが私のトランザクションを制御していると思います。したがって、私にとっては、requireNew などを使用する以外に、トランザクションを台無しにすることはありません。サーバーが行います。

実際にJPAを使用しているため、休止状態タグを移動する必要があるかもしれません-JBossは休止状態を使用します。そのため、コード例でそれに関連してください。

于 2008-11-12T11:54:19.357 に答える
0

オブジェクトを永続化しても、ロールバックできます。EntityManager でフラッシュを呼び出した後にのみ、基礎となるデータベースとの同期が行われます。

于 2008-11-13T06:07:10.463 に答える
0

答えと Java EE 5Tutorial を少し読んだことで、正しい答えが得られたと思います。

私の考えに反して、persist() はデータベースにフラッシュせ、エンティティ Bean を永続化された状態に移行するだけです。私をだましてしまったのは、persist を呼び出した後、エンティティが実際にデータベースに永続化されることに気付いたことです (エラー メッセージに「保存」という単語が含まれている可能性があります)。これは、フラッシュがトランザクションの終了と呼ばれるものであると考えましたが、マルコムを正しく取得できれば、自分自身または例外でサーバーによってロールバックできます。

したがって、私が下す結論は次のとおりです。persist は、既に永続化されている別のエンティティに関連していない限り、新しいエンティティが作成されるたびに呼び出す必要があります。
その後、トランザクションは維持され、サーバーはあなたをもう少し好きになります ;)

彼女に残されているのは、すべてが永続化された状態にないとクエリを実行できない理由をまだ理解できないということです。

于 2008-11-13T08:17:46.003 に答える