Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic @PersistenceContext unitName attribute for container-based EntityManager

basically, what i wanna do is assigning 'unitName' attribute of @PersistenceContext with a value that i will get from the Session at runtime.

in details;

my application will be a SaaS application and i will have separate DBs for every different tenants. i am using Glassfishv3 and managing the entities container-based so i dont get any instance from EntityManagerFactory explicitly. All i am doing for creating an entity manager is ;

@PersistenceContext(unitName = "DBNAME")
private EntityManager entityManager;

i need to pass unitName attribute according to the current user. it shouldn't be hard-coded.

I have updated Eclipselink 2.3 but all examples are creating an instance from EMF which you can pass property Map like

Map memberProps = new HashMap();
memberProps.put("memberPu1", props1);
memberProps.put("memberPu2", props2);

Map props = new HashMap();
props.put("eclipselink.jdbc.exclusive-connection.mode", "Always");
props.put("eclipselink.composite-unit.properties", memberProps);

EntityManager em = emf.createEntityManager(props);

unlikely in my app, container does that job so i am not being able to do this

EntityManager em = emf.createEntityManager(props);

Even though i have all the persistence units and classes in my persistence.xml by using JNDI definitions, i am not being able to tell app server which DB(persistence unit) it should use at the time

any help would be appreciated

like image 330
Joe Javac Avatar asked Jan 09 '12 05:01

Joe Javac


2 Answers

Values in annotations cannot be assigned at runtime, and therefore you will need to find a strategy where you can create multiple PersistenceContexts. If you can use CDI, it will probably make your life easier.

With CDI you might be able to create a producer as follows:

public class EntityManagerProducer {

  @PersistenceContext(unitName="firstUnit") private EntityManager firstEntityManager;
  @PersistenceContext(unitName="secondUnit") private EntityManager secondEntityManager;

  @Produces
  public EntityManager getEntityManager(InjectionPoint injectionPoint) {
     if(<your_first_criteria>) {
       return firstEntityManager;
     } else if (<your_second_criteria>) {
       return secondEntityManager;
     }
  }

Then you can use your producer method in e.g. your DAO:

@Inject private EntityManager entityManager;

EDIT: I would probably recommend to use a @Qualifier annotation as it makes it clear where are you getting the EntityManager from.

like image 168
Gonzalo Garcia Lasurtegui Avatar answered Nov 01 '22 15:11

Gonzalo Garcia Lasurtegui


You need to use an application managed persistence unit, not container.

i.e. Persistence.createEntityManagerFactory()

You can still use JTA, just not injection.

like image 38
James Avatar answered Nov 01 '22 15:11

James