5

ユーザーとデバイスの 2 つのエンティティ クラスがあります。

ユーザー エンティティ:

public class User {
    private Long userId;

    @OneToMany( mappedBy = "userId", fetch = FetchType.LAZY)
    private Collection<Device> deviceCollection;

およびデバイス エンティティ:

public class Device implements Serializable {
    @JoinColumn(name = "user_id", referencedColumnName = "user_id")
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private User userId;

親ユーザーが削除された後、以前に分離されたデバイス エンティティをエンティティ マネージャーにマージすると、(以前に削除された) ユーザーとデバイスの両方がデータベースに再挿入されます。ユーザーまたはデバイス エンティティにカスケード アノテーションはありません。したがって、ユーザー エンティティが再挿入されるとは思いませんが、再挿入されました。

マージ操作がユーザー エンティティにカスケードするのを防ぐにはどうすればよいですか?

前もって感謝します。

4

4 に答える 4

0

エンティティが誤って復活するのを防ぐために、バージョン番号を使用する必要があります。これにより、例外が強制されます。仕様は、カスケードオールまたはマージとマークされていないリレーションをマージするときに何が起こるかについて少し不明確です。仕様では、管理対象エンティティはデータベースに同期されると規定されていますが、マージを扱うセクションでは、カスケードマージ/すべてのオプションのないリレーションによって参照されるエンティティも後で管理されることを示しています。この動作はおそらく意図されたものではありませんが、明確になるまで信頼されるべきではありません。

于 2012-09-11T17:47:44.767 に答える
0

JoinColumn にinsertable=false, updateable=falseを追加してみてください。

@JoinColumn(name = "user_id", referencedColumnName = "user_id", insertable=false, updatable=false)
于 2012-08-15T01:05:46.570 に答える
0

デタッチされた状態で行った変更は、Session Manager がそれを知る方法がないため、変更は常にマージする必要がある新しいオブジェクトです (マージを呼び出している場合)。

したがって、マージを呼び出すと、データベースからロードされるため、オブジェクトには前の新しい変更が含まれます。そのため、前述の動作が発生しています。

できることは、最初にエンティティをセッションにロードして変更を適用し、次にマージを呼び出すことです。

あなたができることは、以下のようなものです。Eclipse Link を使用したプロジェクトの 1 つで、同様の関係を使用しました。

Query query = entityManager
            .createNamedQuery("User.FindByUserId");
    User fromDatabase = null;
    try {
        query.setParameter("userId", device.getUser().getUserId());
        fromDatabase = (User) query.getSingleResult();

    } catch (NoResultException noResultException) {
        // There is no need to do anything here.
    }
    if (fromDatabase == null) {
        User user= entityManager.merge(device.getUser());
         device.setUser(user);
    } else {
        device.setUser(user);
    }
    entityManager.persist(device);
于 2012-08-14T17:29:31.703 に答える
-1

私は同じ問題を抱えていて、これに関するバグを見つけました: EntityManager.merge() はデフォルトでカスケードします が、なぜこの動作が修正されなかったのか本当にわかりません。私が EclipseLink を使用しない理由の 1 つです (しかし、それはここでは重要ではありません)。

編集:

クリス、「私は専門家ではありません」で始まるコメントは、頭に浮かんだ議論が正しくないと思います。私が理解しているのは、cascade=MERGE または cascade=ALL のない関係を持つエンティティだけです。ナビゲートするだけです。それだけです。

そうでなければ、なぜ Merge アノテーションを使用するのですか? 意味がありません。

于 2012-09-11T13:26:55.653 に答える