handle EntityManager dynamically with multiples persistences units

entitymanager, java, jpa

Solution

You need to set the "eclipselink.target-server" to the application server you are using when using application managed persistence units (some servers set this automatically then using container managed persistence units). Then the EntityManager will bind with the JTA transaction that is active when it is created. If you create the EntityManager before the start of the JTA transaction then you can use joinTransaction().

If you still have issues, include the server you are using, and the full exception stack trace.

If you have a lot of schemas, you could consider using EclipseLink multi-tenant support, which allows each tenant to have their own schema.

http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_multitenant.htm#BABEGBIJ

Problem

I have a database with multiples schemas so I have a persistence.xml file with multiples `<persistence-unit />` (named 01, 02, ...). Problematic : I want to create an EntityManager dynamically function of some user criteria. I have tested 2 cases. First case : basically, I tested this code (inside stateless EJB) : ``` String criteria = "01"; EntityManagerFactory emf = Persistence.createEntityManagerFactory(criteria); EntityManager em = emf.createEntityManager(); Joueur joueur = new Joueur(); // Joueur is an Entity joueur.setPseudo("olivier"); em.persist(joueur); ``` but I received exception : Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException: ERREUR: la transaction est annulée, les commandes sont ignorées jusqu'à la fin du bloc de la transaction I thought, (with help of some Stackoverflow posts), that my EntityManager wasn't "linked" to my transaction context due to the fact it wasn't injected by container. Second case : thus, I used injection : ``` @PersistenceContext(unitName="00") private EntityManager em00; @PersistenceContext(unitName="01") private EntityManager em01; ``` Code in my function : ``` String criteria = "01"; EntityManager em = getEm(criteria); ... ``` and getEm() method : ``` private EntityManager getEm(String criteria){ if (criteria == "00") return em00; else if (criteria == "01") return em01; return null; } ``` No problem, it's work but I have to inject as many EntityManagers that I have persistence-unit. - What will be the cost if I have 50 schemas...? - Is there a way to really manage entities managers dynamically ? (1 EntityManger only) - If I have to create 1 EntityManager per schema even if I don't use it, how can I improve my code to consume the least amount of resources possible ? Thank you for advices and feedbacks EDIT : My configurations files : Persistence.xml : ``` <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="00" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/sim/00</jta-data-source> <mapping-file>orm_00_beta.xml</mapping-file> <class>com.sim.entities.Joueur</class> <properties> <property name="eclipselink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> <persistence-unit name="01" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/sim/01</jta-data-source> <mapping-file>orm_01_beta2.xml</mapping-file> <class>com.sim.entities.Joueur</class> <properties> <property name="eclipselink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence> ``` orm_00_beta.xml : ``` <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd" version="2.0"> <persistence-unit-metadata> <persistence-unit-defaults> <schema>beta</schema> </persistence-unit-defaults> </persistence-unit-metadata> ``` orm_01_beta2.xml : ``` <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd" version="2.0"> <persistence-unit-metadata> <persistence-unit-defaults> <schema>beta2</schema> </persistence-unit-defaults> </persistence-unit-metadata> ```

Original source