Question

i need to select an EntityManager in my JavaEE6 project (JBoss7) depending of a login session. A user "Peter" will result in using databse dbPeter and a user "Paul" will result in using database dbPaul.

The question is now, how can i produce an entity manager that is automatically bind to the according database/persistence unit?

I use CDI to inject the EntityManager. So my first step is to have a producer for EntityManager that looks for the login information from the session and selects the database. So, how do i select the database/persistence context in this prducer?? Since Jboss7 i can't see any jndi entry for the persistence unit anymore, so a jndi lookup can not be considered.

I tried using

@Produces
public EntityManager produceEM() {
    EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory( "dbPaul" );

    return managerFactory.createEntityManager();
}

but this fails during deployment with

HHH000231: Schema export unsuccessful: java.sql.SQLException: You cannot set autocommit during a managed transaction!

Thats ok because the place where the em is injected is mostly inside a transaction. Anyone an idea?

Was it helpful?

Solution

First off, I would be reluctant to create an EntityManagerFactory on the fly. I suppose you would have to do that in every single DAO instance creation (or whatever EJB object you are using to access your db). If that's the case, think twice about it: creating an EntityManagerFactory is very expensive and should usually be done once in an app lifecycle. As an alternative I would probably create different DAOs for each persistence unit, moving the responsibility of using one or the other to an upper layer, so that you can still rely on the container for creating the EntityManager.

That being said, in your context and assuming that the method produceEM() is in an EJB and you are using container managed security, you can inject the EJBContext via:

@Resource
EJBContext ejbContext;

From here you can get the Principal and create your EntityManager depending on it.

If any of the assumptions is not valid, let me know and will try to update my answer.

EDITED:

@Stateless
public class EntityManagerService {

   @Resource
   EJBContext ejbContext;

   @Produces
   public EntityManager produceEM() {

   EntityManagerFactory managerFactory = Persistence.createEntityManagerFactory(ejbContext.getCallerPrincipal().getName());

   return managerFactory.createEntityManager();

   }
}

You can also create your own mapping between user names and db names which is probably a good idea if you want some decoupling between those.

OTHER TIPS

Not exactly an answer to your question, but have you considered JPA multitenancy? AFAIK both Hibernate and EclipseLink support it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top