1

EclipseLinkを使用してStatというオブジェクトを保存しようとしています。IDがデータベースに存在する場合は、そのオブジェクトを更新します。そうでない場合は、新しいオブジェクトを作成します。これが私のオブジェクトです:

@Entity
public class Stat {

    @Column
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long id;

    @JoinColumn
    @ManyToOne
    public User user;


    @Column
    public boolean accepted;

    @Column
    public boolean finished;

    public Stat() {
    }
}

そして、これがオブジェクトを追加/更新するための私のメソッドです。

public long addReplaceStat(Stat stat) {
            em.getTransaction().begin();
            Stat oldStat = em.find(Stat.class, stat.id);
            if (oldStat == null)
                em.persist(stat);
            else
                em.merge(stat);
            em.getTransaction().commit();

            em.getTransaction().begin();
            Stat newStat = em.find(Stat.class, stat.id);
            if (newStat != null)
                em.refresh(newStat);
            em.getTransaction().commit();

            return stat.id;
        }

私の問題は、em.refresh()で「クラス[User]の属性[id]がデータベースの主キー列にマップされています。更新は許可されていません」という例外が発生することです。そして、その理由がわかりません。管理対象オブジェクトの値を問題なく更新するだけで更新するべきではありませんか?

私がやりたいこと(追加または更新)を行うための最良のイディオムは何ですか?

4

1 に答える 1

3

JPA仕様によると:

エンティティXに適用されるマージ操作のセマンティクスは次のとおりです。

  • Xが切り離されたエンティティである場合、Xの状態は、同じIDの既存の管理対象エンティティインスタンスX'にコピーされるか、Xの新しい管理対象コピーX'が作成されます。
  • Xが新しい管理対象エンティティインスタンスの場合、新しい管理対象エンティティインスタンスX'が作成され、Xの状態が新しい管理対象エンティティインスタンスX'にコピーされます。

[...]

したがって、存在しない場合に追加するか、存在する場合は更新するには、次の操作を行う必要があります。

Stat attachedStat = em.merge(stat);

リフレッシュの問題については、なぜ起こるのかわかりません。しかし、データベースからロードしたばかりのエンティティを更新するのはなぜですか?リフレッシュするものは何もありません。

于 2012-11-04T12:38:38.810 に答える