尝试更新外键时出现问题。
使用合并功能时,我总是会遇到内存不足错误,或者超时

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,但是...有效,考虑到此代码是用于网站的,因此我找不到更好的解决方案,在该网站上使用分离的实例是最佳解决方案(创建对象树需要大量时间,并且我不想每次请求都重新创建所有内容)

10-02 10:11