Accessing objects to make them available after EntityManager close?!

#1

Hi,

I would like to get all the instances of an entity object. So I wrote a function which returns a list of these instances. My problem is if I print out these instances before closing the em and returning the list, it works as I expected; if not, the function returns only one field correctly, another field is always Null. The details is as follows:

public void testRandom() {
  Random random = new Random();

  List<Vifr_dic> questions= getVifr_dicODB();

  for (int i=1; i<=4; i++)
  {
   int indexR = random.nextInt(questions.size());

   Vifr_dic value = questions.get(indexR);
   System.out.println("** Random Value ** of " + indexR + " : \n" + value.getWord() + " : " + value.getMeanings());
  }
} 

private List<Vifr_dic> getVifr_dicODB() {

  EntityManagerFactory emf =
    Persistence.createEntityManagerFactory("$objectdb/db/vipack/vnfr_lessons.odb");
  EntityManager em = emf.createEntityManager();

  TypedQuery<Vifr_dic> query =
    em.createQuery("SELECT w FROM Vifr_dic w", Vifr_dic.class);

  List<Vifr_dic> dic = query.getResultList();  

 for (Vifr_dic vifr_w : dic) {
   System.out.println(vifr_w);

//without println(), testRandom() get the dic.word correctly but dic.meanings is null

}

em.close();
emf.close();

return dic;
}

@Entity
public class Vifr_dic implements Serializable {
private static final long serialVersionUID = 1L;

@Id @GeneratedValue
Long id;

@Unique
private String word;
private Set<String> meanings;

public Vifr_dic() {
}

public Vifr_dic(String word, Set<String> meanings) {
  this.word = word;
  this.meanings = meanings;
}

public String getWord() {
  return word;
}

public Set<String> getMeanings()
{
  return meanings;
}

@Override
public String toString() {
  return "The word " + word + " means: " + meanings;
}
}

What is wrong here? How can I get the list of entity objects? Many thanks

#2

Closing the EntityManager changes the state of the managed object to detached, and in detached objects only fields that have already been loaded when the EntityManager when it was open are available (and references to unloaded objects are null).

Accessing objects in a loop while the EntityManager is open loads data and makes it available. A more conventional method is to define the fetch policy as EAGER or run queries with JOIN FETCH.

Alternatively you may consider the non standard "objectdb.temp.no-detach" extension.

ObjectDB Support

Reply