Reputation: 27899
Employee employee = entityManager.find(Employee.class, 1L);
if (employee == null) {
throw new EntityNotFoundException();
}
Since EntityManager#find()
returns null
in case, the said entity is unavailable, the conditional test as shown above is necessary to avoid the possible java.lang.NullPointerException
which is otherwise likely. Repeating this trivial conditional test everywhere is pretty much unacceptable and discouraged which makes the business logic which should in turn be as simple as possible, pretty much unreadable.
To prevent this conditional check from being repeated all over the place, I have a generic method in a separate EJB like so,
@Stateless
public class EntityManagerUtils implements EntityManagerService {
@PersistenceContext
private EntityManager entityManager;
@Override
public <T extends Object> T find(Class<T> entityClass, Object primaryKey) {
T entity = entityManager.find(entityClass, primaryKey);
if (entity == null) {
throw new EntityNotFoundException();
}
return entity;
}
}
Invoking this method from inside another EJB like the following,
@Stateless
public class TestBean implements TestBeanService {
@PersistenceContext
private EntityManager entityManager;
@Inject
private EntityManagerService entityManagerService;
@Override
public void test(Employee employee) {
Department managedDepartment = entityManagerService.find(Department.class, employee.getDepartment().getDepartmentId());
System.out.println("contains : " + entityManager.contains(managedDepartment));
}
}
Here, despite the fact that everything happens within the same single transaction, entityManager.contains(managedDepartment)
returns true
i.e. the returned Department
entity is managed by both the EntityManager
s in both the EJBs.
Although it is expected, how does entityManager.contains(managedDepartment)
return true?
Is it the same EntityManager
instance using the same EntityManagerFactory
?
Upvotes: 1
Views: 992
Reputation: 19002
I doubt the EJB specification guarantees that the EntityManager
Java instances will be the same, but it guarantees they are backed by the same Persistence Context (the same set of managed entities), because you are in the same JTA transaction and because both EntityManagers
are container managed of the same persistence unit (the default in your case).
If you want to check whether the instances are the same in your environment, check the output of
System.out.println("EntityManager : " + entityManager);
but I would not rely on that as a guarantee for future versions of your Application Server.
If you want a new Persistence Context, you could either begin a new transaction or create manually an EntityManager
instance from an injected EntityManagerFactory
.
For performace considerations, I wouldn't want to use a new Persistence Context in your situation.
Edit: Add a quote from official JavaEE 7 Tutorial that explains/justify what it was just said
The persistence context is automatically propagated with the current JTA transaction, and
EntityManager
references that are mapped to the same persistence unit provide access to the persistence context within that transaction. By automatically propagating the persistence context, application components don't need to pass references toEntityManager
instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers.
Upvotes: 4