49

通常はうまく機能する次のコードがあります。

public void delete(T object)
{
  EntityManager em = getPersistence().createEntityManager();
  EntityTransaction et = em.getTransaction();
  try
  {
    et.begin();
    object = em.find(object.getClass(), object.getId());
    em.remove(object);
    em.flush();
    et.commit();
  }
  catch(Exception e)
  {
    error("Unable to delete " + object.toString() + ": there are references to it.");
  }
  finally
  {
    if (et.isActive()) et.rollback();
    em.close();
  }
}

私のエンティティクラスの多くでは、これはうまくいきます。ただし、そのうちの 2 つは何もせず、例外をスローせず、オブジェクトを削除しません。休止状態からのログは、休止状態がいくつかの選択クエリを実行することを示していますが、削除を実行しようとさえしません。

他の同様の質問hereおよびhereで見つかった提案を既に試しましたが、役に立ちませんでした (まあ、後者は使用できないことを示唆していますが、ステートメントをと@Transactionalで囲んだだけです)。begin()commit()

これらの 2 つのクラスが他のクラスより多い (または少ない) ものを見つけることができないようです。彼らは@PrimaryKeyJoinColumn私が持っている他のほとんどすべてのエンティティ@OneToMany@ManyToOne同じように使用します。正直に言うと、彼らには@OneToOne(optional = false)別のクラスを参照するフィールドがあり、他のエンティティにはありませんが、理由がある可能性があると言われない限り、それを変更する (そしてその結果としてデータベース スキーマを変更する) という面倒なことはしません。それのための。

@OneToOne責任者ですか?または、削除コードにバグがありますか?

4

5 に答える 5

30

cascade = CascadeType.ALL関連付けのbyorphanRemoval = trueを置き換えると@OneToMany、期待どおりの結果が得られます。親レコードを削除しなくても、子レコードが正しく削除されます。

エラーがより明確に記録されていないのは残念です。

于 2014-04-13T15:45:02.623 に答える
7

次のものが集まったときに同じ問題が発生しました。

  1. 休止状態 3.6.10.Final
  2. Child への参照を持たない親エンティティ。
  3. 親を参照するいくつかの子エンティティ。レガシーコードです。

    class ChildEntity {
      @ManyToOne(cascade = CascadeType.ALL)
      private ParentEntity parent;
    }
    
  4. 子エンティティはセッション コンテキストにロードされ、トランザクション内で JPA 通知なしでテーブルから削除されます (ストアド プロシージャ、ネイティブ SQL)

  5. その後、親は削除できません。削除も例外もありません。TRACE ログに「削除のスケジュールを解除しました」というメッセージが表示されるだけです。

解決策: カスケード属性を削除しました。どの子エンティティが親の削除をブロックしているかを見つけるのは少し難しかったです。また、親エンティティを削除すると子のカスケードが影響する理由がわかりません。

于 2015-06-17T15:35:13.430 に答える