Error using OneToOne/ManyToOne with JPA and Multiple Data Sources - spring

I've managed to configure JPA with multiple datasources, but I get the following error when bringing up my server (Websphere liberty):
org.hibernate.AnnotationException: #OneToOne or #ManyToOne onxxx.AccountBalance.currency references an unknown entity: xxx.Currency
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(T oOneFkSecondPass.java:109)
at org.hibernate.cfg.Configuration.processEndOfQueue( Configuration.java:1521)
at org.hibernate.cfg.Configuration.processFkSecondPas sInOrder(Configuration.java:1446)
at org.hibernate.cfg.Configuration.secondPassCompile( Configuration.java:1351)
at org.hibernate.cfg.Configuration.buildSessionFactor y(Configuration.java:1733)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>( EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityMan agerFactory(Ejb3Configuration.java:905)
The application deploys correctly if all the DAO are declared in the same database, but it fails if I move any of them to a second database. Is it possible to used JPA bags (OneToOne, ManyToOne, ManyToMany) with multiple data sources?
Relevant parts of the configuration:
Context:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/xxxwas"
cache="true" resource-ref="true" lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />
<bean id="h2dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url"
value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=3" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<tx:jta-transaction-manager />
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit .DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="h2" value-ref="h2dataSource" />
<entry key="mysql" value-ref="dataSource" />
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="integrationEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="integrationEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="h2dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="H2" />
<!-- <property name="generateDdl" value="true" /> -->
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="databaseEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<jpa:repositories base-package="xxx.impl.repository.integration"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="integrationEntityManagerFactory">
</jpa:repositories>
<!-- Configures Spring Data JPA and sets the base package of my DAOs. -->
<jpa:repositories base-package="xxx.impl.repository"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="entityManagerFactory">
</jpa:repositories>
Server.xml
<dataSource id="xxxwas" jndiName="jdbc/xxxwas" supplementalJDBCTrace="true" type="javax.sql.XADataSource">
<jdbcDriver javax.sql.ConnectionPoolDataSource="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" javax.sql.DataSource="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" javax.sql.XADataSource="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" libraryRef="MySQLLib"/>
<properties databaseName="xxx" password="xxx" portNumber="3306" serverName="localhost" user="root"/>
</dataSource>
Web.xml
<resource-ref>
<res-ref-name>jdbc/xxxwas</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="databaseEntityManagerFactoryPU" transaction-type="JTA">
<class>xxx.impl.bo.AccountBalance</class>
<!-- WORKS IF DEFINED HERE -->
<!-- <class>xxx.impl.bo.Currency</class> -->
<properties>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<!-- <property name="hibernate.current_session_context_class"value="thread" /> -->
<!--<prop key="hibernate.transaction.flush_before_completion">false</prop>-->
<!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
<!--<prop key="hibernate.current_session_context_class">thread</prop>-->
<!--<prop key="javax.persistence.transactionType">JTA</prop>-->
<!--<prop key="hibernate.connection.release_mode">auto</prop>-->
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="net.sf.ehcache.configurationResourceName" value="ehcache_database.xml"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
<!-- <property name="hibernate.archive.autodetection" value="class, hbm"/> -->
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> -->
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
<property name="hibernate.use_sql_comments" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
</properties>
</persistence-unit>
<persistence-unit name="integrationEntityManagerFactoryPU" transaction-type="JTA">
<!-- DOES NOT WORK IF DEFINED HERE -->
<class>xxx.impl.bo.Currency</class>
<properties>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
</persistence>

I know its too late, but I had the same probleme.
I'm working on Oracle database, the same database with two schemas (users)
My solution was to give the first user access to all tables in the second user schema.
After that, on JPA Entity annotation, precise the schema for each entity.
This way, hibernate generate SQL queries with schema :
select field1, field2 from USER1.Table1 INNER JOIN USER2.TABLE2 ON .....
It work this way because user1 have access to user2 tables with a grant, but the two schemas must be in the same database, otherwise you have to create a dblink and a synonym.

Related

Multiple database Schema with Spring+Hibernate+JPA

I have same database schema database_1 and database_2 and want to configuration of these two database(database schema is same) and decide run time which database is use.
My persistence.xml is as below:
<persistence-unit name="first" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.model.AboutUs</class>
<class>com.model.AccessCards</class>
<properties>
<property name="hibernate.dialect" value="com.util.customMySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
<property name="hibernate.jdbc.batch_size" value="20"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
</properties>
</persistence-unit>
Persistence name second configure here as below :
<persistence-unit name="second" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.model.AboutUs</class>
<class>com.model.AccessCards</class>
<properties>
<property name="hibernate.dialect" value="com.util.customMySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
<property name="hibernate.jdbc.batch_size" value="20"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
</properties>
</persistence-unit>
Both persistence units load same classes .
and now my database-configure.xml as where i configure persistence unit with data source. as below first persistence unit name configare with datasource name datasource as :
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="first" />
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${datasource.driverClassName}" />
<property name="jdbcUrl" value="${datasource.url}" />
<property name="user" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
<property name="acquireIncrement" value="1" />
<property name="acquireRetryAttempts" value="1" />
<property name="maxIdleTime" value="300" />
<property name="maxPoolSize" value="20" />
<property name="minPoolSize" value="3" />
<property name="maxStatements" value="300" />
<property name="testConnectionOnCheckin" value="true" />
</bean>
Now this code for configure second persistence unit name with data source name datasource5 as below :
<bean id="transactionManager5" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory5" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource5" />
<property name="persistenceUnitName" value="second" />
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="dataSource5" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${datasource.driverClassName}" />
<property name="jdbcUrl" value="${datasource5.url}" />
<property name="user" value="${datasource5.username}" />
<property name="password" value="${datasource5.password}" />
<property name="acquireIncrement" value="1" />
<property name="acquireRetryAttempts" value="1" />
<property name="maxIdleTime" value="300" />
<property name="maxPoolSize" value="20" />
<property name="minPoolSize" value="3" />
<property name="maxStatements" value="300" />
<property name="testConnectionOnCheckin" value="true" />
</bean>
Now i use entity manager for save data in database and i am using mysql database . I got entity manager with persistence unit name first and second .
#PersistenceContext(unitName="first")
private EntityManager entityManager;
#PersistenceContext(unitName="second")
private EntityManager entityManager2;
Now entity manager save data in database using persist( object) method successfully .
entityManager.persist(project);
and entityManager2 save data in database using persist( object ) method successfully (No Exception here). But data does not store in database datbase_2 .
entityManager2.persist(project);
If I change the order of persistence unit first and second in persistence.xml then entityManager2 save data in database and entitymanager does not save data in database .
Any one have idea how i can make multiple entitymanager for same database schema .
There are a few limitations:
#Transactional corresponds to single TransactionManager.
JpaTransactionManager corresponds to single EntityManager(Factory).
Thus use separate methods with #Transactional annotation for each transaction manager:
#Transactional(transactionManager = "tmBeanName")
After that entity managers will work fine.
Also, some workaround exists to break the second limitation (DO NOT USE IT in this case):
It is possible to use single JtaTransactionManager instead of several JpaTransactionManager: distributed transaction will cover both entity managers and they will work fine too.

multiple entityManagerFactory for 2 different datasources

I want keep 2 datasources for 2 different databases (both are mysql) like below :
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="database" value="MYSQL" />
</bean>
<bean id="dataSource-A"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url-A}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="entityManagerFactory-A"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource-A" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<!-- spring based scanning for entity classes -->
<property name="packagesToScan" value="com.package-A" />
</bean>
<bean id="dataSource-B"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url-B}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="entityManagerFactory-B"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource-B" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<!-- spring based scanning for entity classes -->
<property name="packagesToScan" value="com.package-B" />
</bean>
Now when i do simply this, beanInitializer gives error that entityManagerFactory is not found.
How can i have multiple entityManagerFactory, for multiple data base and what is best way to do in xml.
I googled quite a lot, but none is able to solve my problem.
It works well if i define only one entityManagerFactory, I am just stuck to have miltiple entityManagerFactory in same application context.
Below is the example for keeping multiple persistence unit for different type of database. Similarly 2 unit can be kept for both of your sql databases.
<?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="oraPersistent" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.kulhade.us.ora.entity.BilltoAddress</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<validation-mode>AUTO</validation-mode>
<properties>
<property name="javax.persistence.jdbc.driver" value="${db.driver}"/>
<property name="javax.persistence.jdbc.url" value="${db.url}"/>
<property name="javax.persistence.jdbc.user" value="${db.username}"/>
<property name="javax.persistence.jdbc.password" value="${db.password}"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
<property name="hibernate.jdbc.batch_size" value="50"/>
</properties>
</persistence-unit>
<persistence-unit name="mongoPersistent" transaction-type="JTA">
<!-- Use Hibernate OGM provider: configuration will be transparent -->
<provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
<class>com.kulhade.us.mongo.entity.Sample</class>
<class>com.kulhade.us.mongo.entity.SampleLine</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.ogm.datastore.provider" value="mongodb" />
<property name="hibernate.ogm.datastore.database" value="${mongodb.name}"/>
<property name="hibernate.ogm.mongodb.host" value="${mongodb.host}"/>
<property name="hibernate.ogm.datastore.port" value="${mongodb.port}"/>
<!--<property name="hibernate.ogm.datastore.document.association_storage" value="ASSOCIATION_DOCUMENT"/>
<property name="hibernate.ogm.mongodb.association_document_storage" value="COLLECTION_PER_ASSOCIATION"/>-->
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
These multiple persistence unit can be used in Spring orm. Below is the example for it.
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
<value>classpath:/my/package/**/custom-persistence.xml</value>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="localDataSource" value-ref="local-db"/>
<entry key="remoteDataSource" value-ref="remote-db"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum"/>
<property name="persistenceUnitName" value="myCustomUnit"/>
</bean>

Spring Entity Manager Factory using JNDI

I am getting confused on how to get the entity Manager Factory in spring spring-datasource.xml using
I did the following :
spring-datasource.xml file:
<tx:jta-transaction-manager id="transactionManager" />
<tx:annotation-driven mode="proxy"
transaction-manager="transactionManager" />
<jee:jndi-lookup id="entityManagerFactory" jndi-name="jdbc/mysqldatasource" />
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="ebankingUnit"
transaction-type="JTA">
<jta-data-source>jdbc/mysqldatasource</jta-data-source>
<class>com.datamodel.Product</class>
<properties>
<property name="eclipselink.logging.level" value="INFO" />
<property name="eclipselink.query-results-cache.expiry"
value="5000" />
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="hibernate.hbm2ddl.auto" value="none" />
</properties>
</persistence-unit>
but I am getting thid
which version of Spring are you using? You don't even need persistence.xml in the latest versions.
Here is the configuration using Spring 3.x, for oracle.
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- FactoryBean that creates the EntityManagerFactory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="false" />
</bean>
</property>
<property name="packagesToScan" value="blah.com..domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/myoracledb}" />
</bean>
Now define myoracledb jndi resource in your web.xml
<Resource name="myoracledb" auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
maxActive="50"
url="your db url"
username="dbuser" password="dbpwd" />
Regards

Spring, OpenJPA, multiple persistence unit

There is a spring no-web application Apache James (Java Mail server).
It uses openjpa. It has a persistence unit and datasource and entitymanager factory definition.
I must manipulate it to use one more persistence unit, for an external DB.
I added one more unit into persistence.xml
<persistence-unit name="James" transaction-type="RESOURCE_LOCAL">
<!-- Mailbox stuff-->
<class>org.apache.james.mailbox.jpa.mail.model.JPAMailbox</class>
<class>org.apache.james.mailbox.jpa.mail.model.JPAUserFlag</class>
<class>org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMessage</class>
<class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage</class>
<class>org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage</class>
<class>org.apache.james.mailbox.jpa.mail.model.JPAProperty</class>
<class>org.apache.james.mailbox.jpa.user.model.JPASubscription</class>
<class>org.apache.james.domainlist.jpa.model.JPADomain</class>
<class>org.apache.james.user.jpa.model.JPAUser</class>
<class>org.apache.james.rrt.jpa.model.JPARecipientRewrite</class>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
<property name="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade"/>
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
<property name="openjpa.jdbc.QuerySQLCache" value="false"/>
</properties>
</persistence-unit>
<persistence-unit name="myPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>package.EmailAddress</class>
<class>package.Message</class>
<properties>
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/kepsDb" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="hibernate.hbm2ddl.auto" value="none" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.dialect" value=" org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.max_fetch_depth" value="0" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
<property name="hibernate.ejb.naming_strategy" value="web.app.persistence.util.AppImprovedNamingStrategy"/>
</properties>
</persistence-unit>
I do not define a second entity manager factory in spring-server.xml, instead, i generate my own entitymanager factory inline with:
EntityManagerFactory emf=Persistence.createEntityManagerFactory("myPU");
EntityManager entityManager=emf.createEntityManager();
entityManager.getTransaction().begin();
But i am getting exception:
Caused by: org.springframework.beans.FatalBeanException: Unable to execute lifecycle method on beanmailetcontext; nested exception is <openjpa-2.1.0-r422266:1071316 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: This operation cannot be performed while a Transaction is active.
myPU is configured to use JTA transaction. Calling entityManager.getTransaction() when using JTA will cause exception as this method is supposed to use with RESOURCE_LOCAL transaction type .
I don't know if your posted exception messages is due to this , but you can try to change the <persistence-unit> of myPU to :
<persistence-unit name="myPU" transaction-type="RESOURCE_LOCAL">
Please note that if you have to access both databases in the same transaction , you must use JTA .
Following code explains how to configure multiple persistence units with JPA + spring:
First of all, we define two persistence units in the persistence.xml, lets call them unit1 and unit2 respectively:
<persistence 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_1_0.xsd"
version="1.0">
<persistence-unit name="Unit1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" />
<property name="hibernate.connection.url" value="jdbc:oracle:thin:#my.company.com:1522:D1" />
<property name="hibernate.connection.password" value="my_user" />
<property name="hibernate.connection.username" value="my_password" />
</properties>
</persistence-unit>
<persistence-unit name="Unit2" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" />
<property name="hibernate.connection.url" value="jdbc:oracle:thin:#my.company.com:1522:D2" />
<property name="hibernate.connection.password" value="my_user" />
<property name="hibernate.connection.username" value="my_password" />
</properties>
</persistence-unit>
</persistence>
Since we dealt with a stand-alone Java applicatie, we defined our data sources in the Spring application context, but for web applicaties one typically defines JNDI references to these datasources in the persistence.xml file itself.
From within the application-context.xml these persisetence units are referred to like so:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config />
<tx:annotation-driven />
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:#my.company.com:1521:D1" />
<property name="user" value="my_user" />
<property name="password" value="my_password" />
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#my.company.com:1521:D2" />
<property name="username" value="my_user" />
<property name="password" value="my_password" />
</bean>
<!-- DEFINITION OF BOTH ENTITY MANAGER FACTORIES -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource1" />
<property name="persistenceUnitName" value="Unit1" />
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform"
value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
</bean>
<bean id="entityManagerFactory2"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="persistenceUnitName" value="Unit2" />
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform"
value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
</bean>
<!-- PERSISTENCE UNIT MANAGER and TRANSACTION MANAGERS -->
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="dataSources">
<map>
<entry key="d1" value-ref="dataSource1" />
<entry key="d2" value-ref="dataSource2" />
</map>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entity-manager-factory-ref="entityManagerFactory" />
<bean id="abwTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entity-manager-factory-ref="entityManagerFactory2" />
</beans>
Now all that is left to do is denote the #PersistenceContext in your DAOs like so:
#Required
#PersistenceContext(unitName = "Unit1")
public void setEntityManager(final EntityManager entityManager) {
this.entityManager = entityManager;
}

Spring Hibernate Configuration resulting in session NPE

I'm having issues properly setting up my Hibernate configuration. After trying to extend the HibernateDaoSupport into a GenericDao and extending those to class-specific daos, but when I call findByNamedQuery in my dao, getSession() throws an NPE.
When I tried switching to extending HibernateTemplate, the hibernateTemplate doesn't get instantiated properly, and is still null:
java.lang.NullPointerException
at org.springframework.orm.hibernate3.support.HibernateDaoSupport.getSession(HibernateDaoSupport.java:143)
at com.jmt.hibernate.dao.GenericDaoImpl.findByNamedQuery(GenericDaoImpl.java)
What am I missing??
I used maven2 to build the project,
1. added the hibernate plugin into my pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>3.0</version>
<configuration>
<components>
<component>
<name>hb2ddl</name>
<implementation>jpaconfiguration</implementation>
</component>
</components>
<componentProperties>
<drop>true</drop>
<outputfilename>output.sql</outputfilename>
<format>false</format>
<persistenceunit>MyEntityManager</persistenceunit>
<ejb3>true</ejb3>
</componentProperties>
</configuration>
</plugin>
2. defined my entity manager in persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
version="2.0">
<persistence-unit name="MyEntityManager" transaction-type="RESOURCE_LOCAL"> <!-- "JTA"> -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<class>com.jmt.model.UserEntity</class>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<validation-mode>CALLBACK</validation-mode>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/><!-- org.hibernate.dialect.HSQLDialect" -->
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.url" value="${jdbc.url}"/>
<property name="hibernate.connection.username" value="${jdbc.username}"/>
<property name="hibernate.connection.password" value="${jdbc.password}"/>
</properties>
</persistence-unit>
</persistence>
3. wired up my daos in applicationContext.xml:
<bean id="hibernateDaoSupport" abstract="true"
class="org.springframework.orm.hibernate3.support.HibernateDaoSupport">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="hibernateHelper" class="org.springframework.orm.hibernate3.HibernateTemplate" >
<constructor-arg ref="sessionFactory"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="hibernateManagedSession" value="true"/>
</bean>
<bean class="com.jmt.model.UserEntity"/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1" />
</bean>
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="order" value="2" />
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename"><value>messages</value></property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="logAbandoned" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<property name="minEvictableIdleTimeMillis" value="60000"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
<prop key="hibernate.jdbc.batch_size">15</prop>
<prop key="hibernate.connection.isolation">2</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.jmt.model</value>
<value>com.jmt.hibernate.dao</value>
</list>
</property>
</bean>
<bean id="userDao" class="com.jmt.hibernate.dao.UserDaoImpl">
<constructor-arg value="com.jmt.hibernate.dao.UserDaoImpl"/>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
4. even added a filter into my web.xml hoping that would inject the session properly:
<filter>
<filter-name>sessionLoadingFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
I didn't add in a manager yet, hoping that fewer layers would make SOMETHING work...
Any help/ideas would be much appreciated!
I think you should try to do openSession() rather doing getSession(). Because at that point there might be the case that your session is not opened and you are trying to get it and hence it will result in a NPE.
Hope this helps you. Cheers.
Yuck, I did not think about where the call to the dao was being made, and yes, that's why there wasn't an open session. Someone had used spring dwr to call the dao directly from a jsp file. Once I got rid of that and made the call from my Controller, the session was finally being instantiated properly. Thanks for the help, Japs!

Resources