6

次のエンティティに対して(EclipseLinkとtransaction-type = "RESOURCE_LOCAL"を使用して)JPA永続性を正しく設定する方法を理解するのに問題があります。

@Entity
public class User {
    // snip various members

    @ManyToMany
    private List<Company> companies;

    public void setCompanies(List<Company> companies) {
           this.companies = companies;
    }
}

@Entity
public class Company {
    // snip various members
}

私がやろうとしているのは、会社リストのカスケードを設定して、以前に永続化されていない新しい会社がリストに含まれている場合に、ユーザーと一緒に自動的に永続化されるようにすることです。

User newUser = new User();

Company newCompany = new Company();
List<Company> companies = new ArrayList<Company>();
companies.add(newCompany);

newUser.setCompanies(companies);

entityManager.persist(newUser);

@ManyToManyにcascadeType.PERSISTを設定すると、これは問題なく機能します。しかし、会社のリストに以前に永続化された会社が含まれている場合、同じ主キーを持つ新しい会社を永続化(INSERT)しようとしているため、MySQLIntegrityConstraintViolationExceptionが発生します。

User newUser = new User();

Company oldCompany = companyDAO.find(oldCompanyId);
List<Company> companies = new ArrayList<Company>();
companies.add(oldCompany);

newUser.setCompanies(companies);

entityManager.persist(newUser);

では、新しい会社が自動的に永続化されるようにこれをどのように設定する必要がありますが、既存の会社は単にユーザーと会社のマッピングに追加されますか?

4

2 に答える 2

10

Hibernate でのカスケードについて考える最良の方法は、親でメソッド X を呼び出すと、各子でメソッド X が呼び出されるということです。そうです、ユーザーに対してpersistを呼び出すと、永続化されているかどうかに関係なく、各子に対してpersistが呼び出されます。

この状況は、理想的にはカスケードで処理されません。Cascade persist は、すべての子が親と共に作成される状況 (たとえば、用途に「スキル」のリストがある場合) を対象としており、1 対多を対象としています。

個人的には、この状況ではカスケードを使用しません。カスケードが不要なときに目に余るほど使用すると、アプリケーションの速度が低下する可能性があります。

カスケードを使用する必要があると思われる場合は、カスケード マージを使用できます。エンティティがまだ永続化されていない場合、Merge はエンティティを永続化します。ただし、マージにはいくつかの非常に奇妙な副作用があり、おそらくそれが機能していることに気付かなかったのでしょう。次の例を検討してください。

x = new Foo();
y = new Foo();

em.persist(x);
Foo z = em.merge(y);

//x is associated with the persistence context
//y is NOT associated with the persistence context
//z is associated with the persistence context
于 2012-09-19T12:13:36.513 に答える
5

あなたの問題はあなたがあなたの永続性コンテキストを破壊しているということです。管理対象オブジェクトは、他の管理対象オブジェクトのみを参照する必要があります。したがって、新しいオブジェクトに既存の分離オブジェクトを参照させるのは間違っています。

あなたがする必要があるのは、find()を実行して、既存のデタッチされたオブジェクトの管理されたバージョンを取得し、新しいオブジェクトにそれを参照させてから、persistを呼び出します。

永続化の代わりにmerge()を使用することもでき、オブジェクトの参照を解決する必要があります。マージはデタッチされたオブジェクトを管理対象にするのではなく、管理対象のデタッチされたオブジェクトのコピーを返すことに注意してください。

于 2012-09-19T13:44:57.850 に答える