views:

47

answers:

1

I have a problem when trying to update foreign keys. Using the merge function I always get a out of memory error, or I get a timeout

Fakultaet and Standort are foreign keys in the Raum table (many to one, and lazy fetching) Raum does eager fetching for the Fakultaet and 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);
 }
 ....
}

I then tried using getReference() instead of find() since I only want to do an update, so I have the method:

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

still not working
afterwards I removed the s.getRaums().add(r) and f.getRaums().add(r) lines but this causes a LazyInitializationException in the next query I need to do.

all I want is something like this:

UPDATE Raum SET FakultaetId = ?, StandortId = ? WHERE RaumID = ?

what am I doing wrong ? is there a better method of doing this ?

A: 

The problem was that I already had all the objects in a detached state and doing a find caused the entire object tree to be loaded once more.

Using em.getReference didn't solve the problem because accessing any of the attributes of the object caused it to be loaded, so it had the same problem as find.

the solution is to only use the detached instances
the new merge function looks something like this:

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

where all the parameters are detached instances.

This still has a problem (at least for me and my hibernate version 3.2): after merge the detached object (raum) doesn't have it's version field updated, so doing a new update will cause an exception, and I had to fix this by incrementing the version field in my method

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

This is more of a hack but... it works and I couldn't find a better solution considering that this code is for a website, where working with detached instances is the best solution (creating the object tree takes a lot of time and I don't want to recreate everything with every request)

Ha11owed