3 Replies Latest reply on Dec 29, 2016 3:25 AM by prutus

    How to use multiple JPA sources for one entity.

    ssjcory

      Example:

       

      I have one Customer class

       

      There are 2 separate databases. One is progress(openedge) and one is mysql.

      The entity can be represented with mostly the same fields in both... But the field names are different.

      so Progress's version is table: customer fields: first-name, last-name, phone

      and Mysql's version is table: Customer fields: first_name, last_name, phone_number

       

      Is there any way to use jpa annotations so that I can store or retrieve from one or the other and the mappings will be different?

       

      Thanks!

        • 1. Re: How to use multiple JPA sources for one entity.
          ssjcory

          Answering my own question.

           

          Talking with the guys in the #hibernate IRC channel they seem to recommend the following:

           

          1) Create 2 persistence units (which will be injected into 2 separate EntityManager via @PersistenceContext(unitName='unitname1') or EntityManagerFactory via @PersistenceUnit(unitName='unitname1')

          2) In the persistence.xml for the primary persistence unit the annotations will be used entirely

          3) In the persistence.xml for the secondary persistence unit an xml mapping file will be used to override the annotations.

          4) In the code that utilizes the PUs (in my case the DAO object) it will use the individual entityManager objects choosing the right one depending on the job.

           

          I will update the thread with more information once I have actually implemented the suggested solution.

          1 of 1 people found this helpful
          • 2. Re: Re: How to use multiple JPA sources for one entity.
            ssjcory

            Ok here is the full source on how to set up 2 separate databases with a single entity.

             

            persistence.xml

            <?xml version="1.0"?>
            <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
               <persistence-unit name="mysqlPU" transaction-type="JTA">
                  <provider>org.hibernate.ejb.HibernatePersistence</provider>
                 
                  <jta-data-source>java:/MySQLDataSource</jta-data-source>
                  <non-jta-data-source>java:/MySQLDataSource</non-jta-data-source>
                  <class>com.somecompany.data.entity.Rep</class>
                  <properties>
                  <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
                  </properties>
               </persistence-unit>
               <persistence-unit name="progressPU" transaction-type="JTA">
                  <provider>org.hibernate.ejb.HibernatePersistence</provider>
                 
                  <jta-data-source>java:/ProgressDataSource</jta-data-source>
                  <non-jta-data-source>java:/ProgressDataSource</non-jta-data-source>
                  <mapping-file>META-INF/persistence-progress-mapping.xml</mapping-file>
                  <class>com.somecompany.data.entity.Rep</class>
                  <properties>
                  <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
                  <property name="hibernate.dialect" value="org.hibernate.dialect.ProgressDialect" />
                  </properties>
               </persistence-unit>
            </persistence>
            
            

             

            Progress(open edge) mapping file that overrides the annotations only for the progressPU persistence unit:

            META-INF/persistence-progress-mapping.xml

            <?xml version="1.0" encoding="UTF-8"?>
            
            
            <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 http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
                version="1.0">  
            
            
                <entity class="com.somecompany.data.entity.Rep" access="FIELD">
                    <table name="salesrep"/>
                    <attributes>
                        <id name="id">
                            <column name="`rep-id`" length="6"/>
                        </id>
                    </attributes>
                </entity>
            </entity-mappings>
            

             

            DAO

            com/somecompany/jpa/RepDao.java

            package com.somecompany.jpa;
            
            
            import java.io.Serializable;
            
            
            import javax.ejb.LocalBean;
            import javax.ejb.Stateless;
            import javax.persistence.EntityManager;
            import javax.persistence.Persistence;
            import javax.persistence.PersistenceContext;
            import javax.persistence.PersistenceContextType;
            
            
            import com.somecompany.data.entity.Rep;
            
            
            @Stateless
            @LocalBean
            public class RepDao implements Serializable {
            
              private static final long serialVersionUID = 12345;
            
              @PersistenceContext(
              unitName="mysqlPU",
              type=PersistenceContextType.TRANSACTION)
              private EntityManager mysqlEm;
            
              @PersistenceContext(
              unitName="progressPU",
              type=PersistenceContextType.TRANSACTION)
              private EntityManager progressEm;
            
            
                public Rep get(String repid)
                {
            //     EntityManagerFactory emf = Persistence.createEntityManagerFactory("mysqlPU");
            //     EntityManager em = emf.createEntityManager();
            
            
                // Find the Rep by id
                return mysqlEm.find(Rep.class, repid);
                }
                
                public Rep getFromMaster(String repid)
                {
                return progressEm.find(Rep.class, repid);
                }
            }
            

             

            Rep entity:

            com/somecompany/data/entity/Rep.java

            package com.somecompany.data.entity;
            
            
            import java.io.Serializable;
            
            
            import javax.persistence.Column;
            import javax.persistence.Entity;
            import javax.persistence.Id;
            import javax.persistence.Table;
            
            
            @Entity
            @Table(name = "somedb.rep")
            public class Rep implements Serializable {
            
              static final long serialVersionUID = 12345;
            
            
              @Id
              @Column(name = "rep_id")
              protected String id;
            
              public String getId()
              {
              return id;
              }
            
              public void setId(String id)
              {
              this.id = id;
              }
            }
            

             

            Example service demonstrating that both are working:

            com/somecompany/webservice/rest/Rep.java

            package com.somecompany.webservice.rest;
            
            
            import javax.ejb.EJB;
            import javax.ejb.LocalBean;
            import javax.ejb.Stateless;
            import javax.inject.Inject;
            import javax.ws.rs.Produces;
            import javax.ws.rs.GET;
            import javax.ws.rs.Path;
            
            
            import com.somecompany.jpa.RepDao;
            
            
            @Stateless
            @LocalBean
            @Path("/rep")
            public class Rep {
            
              @EJB
              private RepDao repDao;
            
              public Rep()
              {
            
              }
            
            
              @GET()
              @Produces("application/json")
              public String getRep() throws Exception {
            
              com.somecompany.data.entity.Rep rep = repDao.getFromMaster("1023");
            
              // Null rep
              if (rep == null) {
              throw new Exception("Could not find rep with ID " + "1023");
              }
            
              return rep.getId().toString() + "-" + repDao.get("1023").getId().toString();
              }
            }
            
            1 of 1 people found this helpful
            • 3. Re: How to use multiple JPA sources for one entity.
              prutus

              Hey,

                how can I get which percistance unit entity is coming from? I need it because depend on entity I have to choose exact entity manager to persist entity.