dynamic @PersistenceContext unitName attribute for container-based EntityManager
Asked Answered
F

2

10

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

Financier answered 9/1, 2012 at 5:32 Comment(1)
This question help me to find a solution for a similar case. I thik can be util: #5104685Teressaterete
M
9

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.

Mikol answered 9/1, 2012 at 8:21 Comment(1)
anyone willing to update the sample code with @Qualifier used?Manhole
P
1

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

i.e. Persistence.createEntityManagerFactory()

You can still use JTA, just not injection.

Pavel answered 9/1, 2012 at 15:54 Comment(1)
it seemed like that to me but at that point i will have to deal with all transaction life-cycle in my app which wasn't designed that way. seems there is no way to supply configurations at runtime and leave the other operations to application server but thanks for the replyFinancier

© 2022 - 2024 — McMap. All rights reserved.