Thursday, April 19, 2018

Configuring multiple databases with multiple entitymanagerfactory in spring data jpa

Leave a Comment

I want to configure 2 entity manager factories for 2 different databases(postgres & sql server) in spring 4.

persistence.xml contains 2 persistence units for 2 databases:

 <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">     <persistence-unit name="entityManager">         <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>         <properties>             <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>             <property name="hibernate.show_sql" value="false"/>             <property name="hibernate.hbm2ddl.auto" value="validate"/>             <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>         </properties>     </persistence-unit>      <persistence-unit name="sqlEntityManager">         <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>         <properties>             <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>             <property name="hibernate.show_sql" value="false"/>             <property name="hibernate.hbm2ddl.auto" value="validate"/>             <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>         </properties>     </persistence-unit> </persistence> 

spring-context.xml contains 2 datasources and 2 entitymanager factories :

    <bean id="postgresDataSource"           class="org.springframework.jdbc.datasource.DriverManagerDataSource"           p:driverClassName="org.postgresql.Driver"           p:url="jdbc:postgresql://localhost:5432/test?createDatabaseIfNotExist=true"           p:username="test"           p:password="test"/>      <bean id="sqlDataSource"           class="org.springframework.jdbc.datasource.DriverManagerDataSource"           p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"           p:url="jdbc:sqlserver://localhost:1433;databaseName=test"           p:username="test"           p:password="test"/>       <bean id="persistenceUnit" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">         <property name="persistenceXmlLocations">             <list>                 <value>classpath*:META-INF/persistence.xml</value>             </list>         </property>         <property name="defaultDataSource" ref="postgresDataSource"/>     </bean>      <bean id="sqlPersistenceUnit" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">         <property name="persistenceXmlLocations">             <list>                 <value>classpath*:META-INF/persistence.xml</value>             </list>         </property>         <property name="defaultDataSource" ref="sqlDataSource"/>     </bean>        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">         <property name="persistenceUnitManager" ref="persistenceUnit"/>         <property name="persistenceUnitName" value="entityManager"/> <property name="packagesToScan" value="com.test.entities.postgres"/>     </bean>      <bean id="sqlEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">         <property name="persistenceUnitManager" ref="sqlPersistenceUnit"/>         <property name="persistenceUnitName" value="sqlEntityManager"/> <property name="packagesToScan" value="com.test.entities.sql"/>     </bean> 

When i run the application it could not create entitymangerfactory as it is checking for tables in postgres which are in sql server.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring-context.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Missing table:<SqlServerTableName> 

5 Answers

Answers 1

I am able to solve the issue by removing the persistence.xml and creating entitymanagerfactory and pchentitymanagerfactory in context.xml as below:

<bean id="entityManagerFactory"       class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"       p:dataSource-ref="phoenixDataSource">     <property name="packagesToScan">         <array>             <value>com.test.entities.postgres</value>         </array>     </property>      <property name="jpaVendorAdapter">         <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>     </property>      <property name="jpaProperties">         <props>             <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>             <prop key="hibernate.show_sql">false</prop>             <prop key="hibernate.hbm2ddl.auto">update</prop>         </props>     </property>      </bean> 

because packagesToScan does not work if we use persistence.xml.

Answers 2

Refer this SE discussion spring jpa hibernate with more datasources

It explains the same problem and might help in your case.

Answers 3

Please update your hibernate configuration by this. I think this would help you

<property name="hibernate.hbm2ddl.auto">create</property> or  <property name="hibernate.hbm2ddl.auto">update</property> 

Answers 4

I have an application with two entitymanager. This is my config:

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1"     xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">      <persistence-unit name="myapp" transaction-type="RESOURCE_LOCAL">         <class>...</class>         <class>...</class>     </persistence-unit>      <persistence-unit name="proxies" transaction-type="RESOURCE_LOCAL">         <class>...</class>         <class>...</class>     </persistence-unit>  </persistence> 

spring-context.xml:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"     xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"     xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"     xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd         http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">      <tx:annotation-driven transaction-manager="transactionManager" />     <tx:annotation-driven transaction-manager="transactionManagerProxy" />      <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">         <property name="dataSource" ref="myappDataSource" />         <property name="entityManagerFactory" ref="entityManagerFactory" />     </bean>      <bean id="transactionManagerProxy" class="org.springframework.orm.jpa.JpaTransactionManager">         <property name="dataSource" ref="proxyDataSource" />         <property name="entityManagerFactory" ref="entityManagerFactoryProxy" />     </bean>      <jpa:repositories base-package="com.example.myapp.repository" entity-manager-factory-ref="entityManagerFactory" />     <jpa:repositories base-package="com.example.myapp.repository.proxy" entity-manager-factory-ref="entityManagerFactoryProxy" />      <task:annotation-driven />      <!-- holding properties for database connectivity /-->    <context:property-placeholder location="classpath:database.properties"/>      <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">         <property name="packagesToScan" value="com.example.myapp.model" />         <property name="persistenceUnitName" value="myapp" />         <property name="dataSource" ref="myappDataSource" />         <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>     </bean>      <bean id="entityManagerFactoryProxy" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">         <property name="packagesToScan" value="com.example.myapp.model.proxy" />         <property name="persistenceUnitName" value="proxy" />         <property name="dataSource" ref="proxyDataSource" />         <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>     </bean>      <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">         <property name="database" value="MYSQL"/>         <property name="showSql" value="false"/>         <property name="generateDdl" value="false"/>         <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>     </bean>      <bean id="dataSource" abstract="true" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">         <property name="driverClass" value="${jdbc.driverClassName}" />         <property name="maxPoolSize" value="${jdbc.maxPoolSize}" />         <property name="minPoolSize" value="${jdbc.minPoolSize}" />         <property name="maxStatements" value="${jdbc.maxStatements}" />         <property name="testConnectionOnCheckout" value="${jdbc.testConnectionOnCheckout}" />         <property name="checkoutTimeout" value="${jdbc.checkoutTimeout}"/>         <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>         <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/>         <property name="preferredTestQuery" value="${jdbc.preferredTestQuery}"/>     </bean>      <bean id="myappDataSource" parent="dataSource">         <property name="jdbcUrl" value="${jdbc.url}" />         <property name="user" value="${jdbc.username}" />         <property name="password" value="${jdbc.password}" />     </bean>      <bean id="proxyDataSource" parent="dataSource">         <property name="jdbcUrl" value="${jdbc.proxy.url}" />         <property name="user" value="${jdbc.proxy.username}" />         <property name="password" value="${jdbc.proxy.password}" />     </bean>  </beans> 

I have 2 connections to MySql, but it should be the same for two different databases.

Answers 5

Note. Defining multiple persistence managers within one Java application has for J2EE with EclipseLink been addressed in: Handle multiple EntityManager in Java EE application

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment