entitymanager坚持

时间:2010-08-04 09:15:52

标签: java jpa ejb-3.0 ejb

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

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)lines 但这会在我需要做的下一个查询中导致LazyInitializationException。

我想要的就是这样:

UPDATE Raum SET FakultaetId = ?, StandortId = ? WHERE RaumID = ?
我做错了什么?有没有更好的方法呢?

1 个答案:

答案 0 :(得分:1)

问题是我已经将所有对象都处于分离状态并且执行查找导致整个对象树再次加载。

使用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);
}

其中所有参数都是分离的实例。

这仍然有问题(至少对我和我的hibernate版本3.2): 合并后,分离的对象(r​​aum)没有更新它的版本字段,所以做一个新的更新会导致异常,我不得不通过增加方法中的版本字段来解决这个问题

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;
 }
}

这更像是一个黑客但是......它有效并且我找不到更好的解决方案,因为这个代码适用于网站,使用分离的实例是最好的解决方案(创建对象树需要很多时间,我不希望每次请求都重新创建所有内容)