尝试更新外键时出现问题。
使用合并功能时,我总是会遇到内存不足错误,或者超时
Fakultaet和Standort是Raum表中的外键(多对一,并且延迟获取)
劳姆(Raum)渴望为Fakultaet和Standort买单
@Stateless
@Local (IRaumHomeLocal.class)
@Remote (IRaumHomeRemote.class)
public class RaumHome implements IRaumHome {
@PersistenceContext private EntityManager em;
void merge(Raum r, Integer fid, Integer sid) {
Fakultaet f = em.find(Fakultaet.class, fid);
Standort s = em.find(Standort.class, sid);
r.setFakultaet(f);
r.setStandort(s);
f.getRaums().add(r);
s.getRaums().add(r);
em.merge(r);
}
....
}
然后,我尝试使用getReference()而不是find(),因为我只想进行更新,
所以我有方法:
void merge(Raum r, Integer fid, Integer sid) {
Standort s = em.getReference(Standort.class, sid);
Fakultaet f = em.getReference(Fakultaet.class, fid);
s.getRaums().add(r); // now it lags here
f.getRaums().add(r);
em.merge(r);
}
还是行不通
之后,我删除了s.getRaums()。add(r)和f.getRaums()。add(r)行
但这会在我需要执行的下一个查询中导致LazyInitializationException。
我想要的是这样的:
UPDATE Raum SET FakultaetId = ?, StandortId = ? WHERE RaumID = ?
我究竟做错了什么 ?有更好的方法吗?
最佳答案
问题是我已经使所有对象处于分离状态,并且进行查找导致整个对象树再次被加载。
使用em.getReference
不能解决问题,因为访问对象的任何属性都会导致对象被加载,因此它具有与find相同的问题。
解决方案是仅使用分离的实例
新的合并功能看起来像这样:
void merge(Raum r, Fakultaet f, Standort s) {
r.setFakultaet(f);
r.setStandort(s);
f.getRaums().add(r);
s.getRaums().add(r);
em.merge(r);
}
其中所有参数都是分离的实例。
这仍然有一个问题(至少对于我和我的休眠版本3.2):
合并分离对象(raum)之后,它的版本字段没有更新,因此执行新的更新将导致异常,因此我不得不通过在方法中增加版本字段来解决此问题
void merge(Raum r, Fakultaet f, Standort s) {
try {
r.setFakultaet(f);
r.setStandort(s);
f.getRaums().add(r);
s.getRaums().add(r);
em.merge(r);
r.setVersion(r.getVersion() + 1);
}
catch(RuntimeException re) {
// logging
throw re;
}
}
这更像是一种hack,但是...有效,考虑到此代码是用于网站的,因此我找不到更好的解决方案,在该网站上使用分离的实例是最佳解决方案(创建对象树需要大量时间,并且我不想每次请求都重新创建所有内容)