私には2つのエンティティがX
あり、次のようにY
定義されています。Y
と多対1の関係がありX
ます:
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;
...
}
エンティティを更新するX
と、ロード時に変更が正しく反映されませんY
。Xテーブルに値(1、 "2222")の行がすでにあると仮定します。Yを最初に印刷すると、Xは(1、 "2222")と表示されます。ただし、コミット後、DBのXテーブルが変更されているのがわかりますが、再度クエリを実行すると、Yは古いバージョンのXにリンクされたままになります。
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);
}
...
}