X
とY
という2つのエンティティが次のように定義されています。 Y
がX
との一対一の関係に多く持っている:私は、エンティティX
を更新するとJPA:子の照会時に親の変更が反映されない
public class X {
@Id
@Column(name = "xId", unique = true, nullable = false, length = 50)
private Integer id;
@Column(name = "description", nullable = true, length = 50)
private String description;
...
}
そして
public class Y {
@Id
@Column(name = "yId", unique = true, nullable = false, length = 50)
private Integer id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="x", nullable=false)
private X x;
...
}
を私はY
をロードする際に、変更が正しく反映されません。 Xテーブルの行はすでに値(1、 "2222")であると仮定します。 Yを最初に印刷すると、Xは(1、 "2222")と表示されます。しかし、私はDBのXテーブルが変更されたが、再び照会するとき、私はまだXの古いバージョンにリンクされているY参照コミット後:
Y y = yDao.findById(ABC);
System.out.println(y); // y.x.description is "2222"
xDao.beginTransaction();
X x = new X(1, "4444");
xDao.update(x);
xDao.commitTransaction();
Y y2 = yDao.findById(ABC); // y.x.description is still "2222" instead of "4444"
System.out.println(y2);
私の結論は、Yがキャッシュから2番目の時間を取得されています。私は、Xが変わったことをYに知らせるために何が欠けていますか?
つまり、yはy2と同じです。つまり、2番目の検索でキャッシュから情報を取得していますか?
Xが変更されたことをYに認識させるには、何が欠けていますか?
追加出力SQL:
Hibernate: // first findById()
select
y0_.yId as yId12_1_,
y0_.address as address12_1_,
y0_.x as x12_1_,
x1_.xId as xId17_0_,
x1_.description as descript2_17_0_
from
daoTest.Y y0_
inner join
daoTest.X x1_
on y0_.x=x1_.xId
where
y0_.yId=?
Y [id=11, x=X [id=1, description=0000]] // System.out
Hibernate: // merge(x)
select
x0_.xId as xId5_0_,
x0_.description as descript2_5_0_
from
daoTest.X x0_
where
x0_.xId=?
Hibernate: // commitTransaction()
update
daoTest.X
set
description=?
where
xId=?
Y [id=11, x=X [id=1, description=0000]] //System.out, theres no select again
GenericDAOクラス
public class GenericDAOImpl<T, ID extends Serializable> implements
GenericDAO<T, ID> {
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistenceUnit");
private EntityManager em = emf.createEntityManager();
protected EntityManager getEntityManager() {
if (em == null) {
throw new IllegalStateException(
"EntityManager has not been set on DAO before usage");
} else {
return em;
}
}
public void refresh(T entity) {
this.getEntityManager().refresh(entity);
}
...
}
新しいxオブジェクトをyオブジェクトに割り当てる場所はわかりません。私はあなたが望むものを手に入れないと思う。 – maerch
読み込み時にトランザクションを使用するとどうなりますか? 'y'のマニュアル' EntityManager.refresh'は 'x'を正しく更新しますか? – ewernli
私はそれを照会するときにYが新しい値をX上で選ぶようにします。これは単なる例です。私のポイントは全く別の場所の誰かが更新を行うことができる(x)と私はまだ新しいXに接続されている古いXの値を取得するでしょう – javaNoober