Hibernate JTA : Read DB connection parameters per environment
Asked Answered
E

5

7

I am writing a javaEE application, using hibernate. The application will be running on multiple environments (dev, qa, prod etc.) & will have separate dbs's associated with each of them. I would like to set the hibernate properties like jdbc-url, username , password etc. separately for each of these environments.

My current persistence.xml looks like :

    <persistence-unit name="PU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <validation-mode>CALLBACK</validation-mode>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
            <property name="hibernate.hbm2ddl.auto" value="validate" />

            <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
            <property name="hibernate.event.merge.entity_copy_observer" value="allow"/>

            <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
            <property name="hibernate.connection.url" value="jdbc:oracle:thin:@host/schema"/>

            <property name="hibernate.connection.username" value="abc"/>
            <property name="hibernate.connection.password" value="***"/>    

        </properties>
    </persistence-unit>

I am using the persistence unit as follows in my java code:

@PersistenceContext(unitName = "PU")
private EntityManager em; 

Is there a way that I can inject the hibernate properties, which are stored in separate properties files, into EntityManager for different environments ?

Please note that I am using JTA and hence cannot use EntityManagerFactory. Also I am not & do not want to use spring.

Explanation answered 16/10, 2015 at 8:48 Comment(3)
when you mean different environments , you dont include the Application Server ? because the datasource / db properties will be shared by the application server , so the production server will have the production db properties and the developments server will have the development propertiesEpitaph
Yes. The application will also have different VM's in different environments.Explanation
then you should make hibernate conf rely on the server's datasource conf , f.e. if you have a tomcat server , you should define 3 different database contextsEpitaph
A
5

It is really a BAAAAAAD idea to include environment-specific information in your application WAR/EAR bundle (either by including multiple configs, or by creating different bundles for different environment). Different database, for example, should be maintained in the container.

In your case, your persistence.xml should look like:

<persistence>
   <persistence-unit name="PU">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>jdbc/fooAppDs</jta-data-source>
      <properties>
         ... ...
      </properties>
   </persistence-unit>
</persistence>

and of course you should have corresponding resource-ref for jdbc/fooAppDs.

By doing so, you can deploy your application in any environment. You just need to create correct datasource in your container and assign it to jdbc/fooAppDs.


Another approach I believe will work, though I will not recommend, is by creating hibernate.cfg.xml in classpath. You may want to have a local file system location and add that in classpath, instead of putting the file in your JAR/WAR/EAR.

Archival answered 19/10, 2015 at 6:25 Comment(0)
S
1

Since you do not want to use external library such as Spring to bootstrap your persistence units, why not use your build system to do this. If you are using maven, you can use mix of maven filtering and profiles to filter based on properties file or if you are using any other build tool, you can add a task (or equivalent) to copy file contents from different files to actual file depending upon some external system/environmental variable.

San answered 19/10, 2015 at 5:3 Comment(0)
E
1

We used maintain property files for each environment such as DEV,QA,PROD,UAT etc in different files and copy one of them during build.

Ant build

<property environment="env" /> 
                <!-- ***** COMMAND LINE ARGUMENTS DEMOED HERE -->
                <property name="build_type" value= "${env.build_type}"/>

<copy todir="deploy">
    <fileset dir="src_dir"/>
    <globmapper from=${env.build_type}".persistence.xml" to="persistence.xml"/>
 </copy>

Run build like this

ant -Denv.build_type=PROD

This will copy PROD.persistence.xml to persistence.xml

ant -Denv.build_type=DEV

This will copy DEV.persistence.xml to persistence.xml

Ear answered 23/10, 2015 at 16:28 Comment(0)
A
0

With Spring Profile you could initiate entity manager beans depending upon the active profile that will refer to the persistence.xml like dev-persistence.xml, test-persisitence.xml, prod-persistence.xml of your environment. And you can set Active profile using web.xml. Mostly the web.xml won't change that much so you can keep the web.xml in your repository with the spring profile active property set for that enviornment.

Apocrine answered 19/10, 2015 at 5:25 Comment(0)
P
0

you can configure your spring-config.xml file as following

  1. MYSQL
<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/kaya_db" />
    <property name="username" value="root" />
    <property name="password" value="nxtlife" />
</bean>
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="packagesToScan" value="com.nxtlife.model" />
    <property name="hibernateProperties">

        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory">
</bean>

2.Similar for other database like oracle,postgre with different name of datasource,sessionfactory and transactionmanager. 3. Finally you can get object of session factory using following sessionfactory name

@Modifier("sessionfactoryname")
@Autowired
private SessionFactory obj;

similar for different database

Pommard answered 23/10, 2015 at 18:42 Comment(3)
As I had mentioned in the question, I am not using and do not wish to use spring.Explanation
Oh my, JPA doesn't seem to have any SessionFactory. Clearly re-reading the question would helpConceited
you can use EntityManager in jpa and set unitname .Pommard

© 2022 - 2024 — McMap. All rights reserved.