I have an app using JSF 2, JPA 2 and EJB 3.1 running on GlassFish v3 (so it uses EclipseLink 2). This application has two JPA entities, Person
and Message
and each Message
has a reference for two Person
s, the message sender and the message receiver. The Person
class has attributes providing access to sent or received Message
s. The Message
class is something like this:
@Entity
public class Message {
@ManyToOne
@JoinColumn(name="sender")
private Person sender;
@ManyToOne
@JoinColumn(name="receiver")
private Person receiver;
// ... some stuff ...
}
and the Person
class is like the following one:
@Entity
public class Person {
@OneToMany(fetch=FetchType.EAGER, mappedBy="sender")
private List<Message> sentMessages;
@OneToMany(fetch=FetchType.EAGER, mappedBy="receiver")
private List<Message> receivedMessages;
// ... more stuff ...
}
Message
instances are created through a method in a DAO class:
@Stateless
public class MessageDAOImpl implements MessageDAO {
public Message crete(Person sender, Person receiver) {
Message message = new Message();
message.setSender(sender);
message.setReceiver(receiver);
entityManager.persist(message);
// Puting in other objects, hoping it will work
sender.getSentMessages().add(message);
receiver.getReceivedMessages().add(message);
// Saving sender and receiver: here comes the interesting part
entityManager.merge(sender); // [1]
entityManager.merge(receiver); // [2]
return message;
}
}
However, something amazing happens. When I comment out the lines marked [1]
and [2]
and call the method, the message does not appear in sender
's sent messages and receiver
's received messages lists when I use these entities elsewhere, even if they are retrieved from entity manager (e.g. through EntityManager.find()
). If I uncomment it, then the message is present in the lists as expected.
I find it intriguing because I envision two situations for the case when the lines are commented out:
- the
sender
andreceiver
entities are directly retrieved from the database and the message should appear in their lists because I saved the message and therefore the relationship is persisted in database; or - the
sender
andreceiver
entities are retrieved from some cache, so they are already have the messages added to the list.
Apparently, it does not work this way.
I found this awesome article about cache in Hibernate. Based on it, I cogitate that the issue is that, since the cache is not of objects but of values, the EntityManager.merge()
method is required for "refresh" the entities with the cached values.
Is it so? If not, what is the reason of this behavior? Is calling EntityManager.merge()
the best solution?
Thank you all in advance!