質問

私はこの簡単な状況を持っています:

@Entity
public class Customer{

    @ManyToMany(fetch=FetchType.EAGER)
    @Cascade(CascadeType.SAVE_UPDATE)
    private List<Product> products=new ArrayList<Product>();

}

@Entity
public class Produtc{

    @ManyToOne
    @Cascade(CascadeType.SAVE_UPDATE)
    private Category category;
}

@Entity
public class Category{

    private String name;
}

新しい顧客を挿入するためのルーチン:

Customer customer=new Customer();
//customer.set data
Product p=dao.getProductBySomeUserInput...
if(p==null){
   p=new Product();
   //p.set data
}
customer.addProduct(p);
dao.save(customer);  //this row throw NonUniqueObjectException on Category class

この問題を解決するにはどうすればよいですか?問題はcascadeType.save_updateに関連していると思いますが、必要なのは...ありがとうございます。


アップデート

私は問題を見つけました、そしてこれがそれを複製する方法です:

Customer c=new Customer();
// Load two products by id
Product p=dao.get(Product.class, 2);
Product p1=dao.get(Product.class, 3);
c.addProduct(p);
c.addProduct(p1);
// This try to update products, and category of products becouse CascadeType is SAVE_UDPATE
dao.save(c);

したがって、PとP 1に異なるカテゴリがある場合、Probsはありませんが、PとP1に同じカテゴリがある場合、同じカテゴリがセッション中であるため、カテゴリに非UniqueObjectExceptionがあり、Hibernateがその保存を試みます。

製品エンティティとカテゴリエンティティの両方でcascadeType.save_updateが必要です。この問題を解決するにはどうすればよいですか?ありがとう。

役に立ちましたか?

解決

問題はおそらく、トランザクション管理が悪いためです。すべてのコードは、DAOコールごとにトランザクションを使用するのではなく、単一のトランザクションで実行する必要があります。サービスレイヤーは、DAOレイヤーではなく、トランザクションを区別するものである必要があります。

私は冬眠が何をするか想像できます:

  1. あなたが呼ぶ dao.get(Product.class, 2). 。これにより、ID 67(たとえば)のカテゴリを指すデタッチされた製品が返されます。 DAOへの呼び出しが終了すると、トランザクションが終了するため、結果は分離されます。
  2. あなたが呼ぶ dao.get(Product.class, 3). 。これにより、ID 67(たとえば)のカテゴリを指すデタッチされた製品が返されます。ただし、コールは別のトランザクションで実行されるため、2番目の異なるカテゴリインスタンス(最初のIDと同じIDを使用)を取得します。
  3. 製品のSaveorUpDateを呼び出します。これはカテゴリにカスケードされるため、HibernateはCategory1とcategory2をセッションに添付する必要があります。どちらも同じIDを持っているため、カスケードの1つは行われない可能性があります。

単一のトランザクションを使用して両方の製品を取得すると、どちらも同じカテゴリインスタンスがあり、問題は発生しません。電話 merge それ以外の saveOrUpdate また、機能する必要があります。Hibernateは、両方のカテゴリの状態を3番目のカテゴリにコピーします。しかし、正しいことは、DAOへの両方の呼び出しを含むトランザクションを使用することです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top