Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query - spring

I'm working on a project using JSpring and JPA/Hibernate. I try to call a native query to update the DB. Here is the error trace:
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
at com.sun.proxy.$Proxy31.executeUpdate(Unknown Source)
at com.ncrm.dao.daoImpl.UpdateExt(daoImpl.java:124)
at com.ncrm.metier.MetierImpl.UpdateExt(MetierImpl.java:663)
at com.ncrm.loginBean.authentification(loginBean.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
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-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.ncrm.dao" />
<bean name="daoo" class="com.ncrm.dao.daoImpl"></bean>
<bean name="metier" class="com.ncrm.metier.MetierImpl">
<property name="dao" ref="daoo"></property>
</bean>
<!-- <bean name="paramEtat" class="com.ncrm.editionEtats.dao.paramEtatsImp"></bean> -->
<!-- ############################################################################## -->
<!-- le gestionnaire de transactions -->
<!-- ############################################################################## -->
<tx:annotation-driven transaction-manager="jpaTransactionManager" />
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="localContainerEntityManagerFactoryBean" />
</bean>
<tx:annotation-driven transaction-manager="jpaTransactionManager" />
<bean id="jpaTransactionManagerBPa" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="localContainerEntityManagerFactoryBeanBpa" />
</bean>
<!-- ############################################################################## -->
<!-- couche de persistance JPA -->
<!-- ############################################################################## -->
<bean id="localContainerEntityManagerFactoryBean"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:config/persistence.xml" />
<property name="persistenceUnitName" value="ncrm_extraction" />
<property name="dataSource" ref="basicDataSource" />
<property name="jpaVendorAdapter">
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<property name="generateDdl" value="false" />
<property name="showSql" value="false"></property>
</bean>
</property>
<property name="loadTimeWeaver">
<bean id="instrumentationLoadTimeWeaver"
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="localContainerEntityManagerFactoryBeanBpa"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:config/persistence.xml" />
<property name="persistenceUnitName" value="BpaProduciton" />
<property name="dataSource" ref="basicDataSourceBpa" />
<property name="jpaVendorAdapter">
<bean id="hibernateJpaVendorAdapterBpa"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<property name="generateDdl" value="false" />
<property name="showSql" value="false"></property>
</bean>
</property>
<property name="loadTimeWeaver">
<bean id="instrumentationLoadTimeWeaverBpa"
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<!-- ############################################################################## -->
<!-- DataSource -->
<!-- ############################################################################## -->
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/r_ncrmextraction" />
<property name="username" value="root" />
<property name="password" value="fast" />
</bean>
<bean id="basicDataSourceBpa" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/" />
<property name="username" value="root" />
<property name="password" value="fast" />
</bean>
<!-- traduction des exceptions -->
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<!-- annotations de persistance -->
<bean id="persistenceAnnotationBeanPostProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
My DAO Class
public class daoImpl implements Idao,Serializable {
String BDD_REF="r_multi_4";
private static final Logger logger = Logger.getLogger(daoImpl.class);
#PersistenceContext(unitName="ncrm_extraction")
EntityManager em;
#PersistenceContext(unitName="BpaProduciton")
EntityManager emBpa;
#Transactional
public int UpdateExt(String pk_obj_id_Rem,String Req) {
logger.debug("### DAO : Modifier le flag EXT table remise : "+pk_obj_id_Rem );
Query q = emBpa.createNativeQuery(Req);
// q.setParameter("Date", dteTr);
// q.setParameter("pk_obj_id_Rem", pk_obj_id_Rem);
int flag=q.executeUpdate();
return flag;
}
My persistence:
<?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="ncrm_extraction" transaction-type="RESOURCE_LOCAL">
<!-- <class>com.ncrm.dao.entities.user</class> -->
</persistence-unit>
<persistence-unit name="BpaProduciton" transaction-type="RESOURCE_LOCAL">
<!-- <class>com.ncrm.dao.entities.user</class> -->
</persistence-unit>
</persistence>

suppose you modify your DaoImpl as below.
#Modifying(clearAutomatically = true)
#Transactional
public int UpdateExt(String pk_obj_id_Rem,String Req) {
logger.debug("### DAO : Modifier le flag EXT table remise : "+pk_obj_id_Rem );
Query q = emBpa.createNativeQuery(Req);
int flag=q.executeUpdate();
return flag;
}
Hope this helps.
Refer this post for more details.

Related

Hibernate JPA Persistence multiple database with Spring

I'm trying to add a new connection to my project based on Spring, JPA and Hibernate. I dont know what's wrong with my settings when I add the second connection
database.properties
database.driverClassName=oracle.jdbc.OracleDriver
database.url=jdbc:oracle:thin:#192.33.333.33:1530:sid
database.username=user
database.password=pass
#DB2
database2.driverClassName=oracle.jdbc.OracleDriver
database2.url=jdbc:oracle:thin:#192.33.333.33:1530:sid
database2.username=user2
database2.password=pass
persistence.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnitUno" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="hibernate.default_schema" value="user"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
<persistence-unit name="persistenceUnitDos" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="hibernate.default_schema" value="user2"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<context:spring-configured/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:config/ehcache.xml"/>
<property name="shared" value="true"/>
</bean>
<bean id="cacheManager" class="com.project.cache.CacheManager">
<property name="cacheManager" ref="ehcache"/>
</bean>
<context:component-scan base-package="com.project">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
<context:exclude-filter type="regex" expression="com.project.interceptor.component.*" />
</context:component-scan>
<cache:annotation-driven/>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSourceUno">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1 FROM DUAL"/>
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSourceDos">
<property name="driverClassName" value="${database2.driverClassName}"/>
<property name="url" value="${database2.url}"/>
<property name="username" value="${database2.username}"/>
<property name="password" value="${database2.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
<property name="validationQuery" value="SELECT 1 FROM DUAL"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactoryUno">
<property name="persistenceUnitName" value="persistenceUnitUno"/>
<property name="dataSource" ref="dataSourceUno"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactoryDos">
<property name="persistenceUnitName" value="persistenceUnitDos"/>
<property name="dataSource" ref="dataSourceDos"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManagerUno">
<property name="entityManagerFactory" ref="entityManagerFactoryUno"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManagerDos">
<property name="entityManagerFactory" ref="entityManagerFactoryDos"/>
</bean>
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" >
<property name="defaultPersistenceUnitName" value="entityManagerFactoryUno"/>
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
Error:
INFO || || Class: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean || Line: 285 || Building JPA container EntityManagerFactory for persistence unit 'persistenceUnitUno'
INFO || || Class: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean || Line: 285 || Building JPA container EntityManagerFactory for persistence unit 'persistenceUnitDos'
INFO || Date: || Class: java.sql.DatabaseMetaData || Line: 147 || HHH000262: Table not found: TABLE
.....
Caused by: org.hibernate.HibernateException: Missing table: TABLE
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1335)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:155)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:525)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:845)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:67)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:288)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 22 more
the TABLE on the error belongs to the first user scheme, it should not happen in user2.
Assuming the Entities reside in different packages, you can control which entities are associated with each persitence unit by setting the packagesToScan property as below:
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactoryUno">
<property name="persistenceUnitName" value="persistenceUnitUno"/>
<property name="dataSource" ref="dataSourceUno"/>
<property name="packagesToScan">
<list>
<value>com.test.domain.entitiesforpu1.package1</value
<value>com.test.domain.entitiesforpu1.package2</value
</list>
<property>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactoryDos">
<property name="persistenceUnitName" value="persistenceUnitDos"/>
<property name="dataSource" ref="dataSourceDos"/>
<property name="packagesToScan">
<list>
<value>com.test.domain.entitiesforpu2.package1</value
</list>
<property>
</bean
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setPackagesToScan-java.lang.String...-
If the entities are not in separate packages then the other option is to explicity list the classes in each persistence unit and exclude any lised which would look like:
<persistence-unit name="persistenceUnitDos" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="hibernate.default_schema" value="user2"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
<class>com.acme.Entity1ForPu2</class>
<class>com.acme.Entity2ForPu2</class>
<class>com.acme.Entity3ForPu2</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>

Spring/Hibernate JPA NamedQuery not found

I have a weird issue: entity manager can't create named query, I'm getting java.lang.IllegalArgumentException: Named query not found while methods, like find() and merge(), works. createQuery() also works. I'm using Hibernate as JPA provider and Spring as DI container. Code and configs are follows:
spring-beans.xml:
<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:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="org.example.testapp.database" />
<bean id="newsForm" class="org.example.testapp.presentation.form.NewsForm">
<property name="newsMessage" ref="news" />
<property name="newsList">
<list>
<ref bean="news" />
</list>
</property>
</bean>
<bean name="news" class="org.example.testapp.model.News">
</bean>
<bean name="/news" class="org.example.testapp.presentation.action.NewsAction"
scope="prototype">
<property name="dao" ref="dao" />
</bean>
<bean id="dao" class="org.example.testapp.database.dao.JpaHibernateNewsDao"
scope="singleton">
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.example.testapp.model"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="login" />
<property name="password" value="password" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager" />
news.java
#Entity
#NamedQueries({
#NamedQuery(name="News.select", query="select n from News n order by news_date" ),
#NamedQuery(name="News.delete", query="delete from News where id in :value_list")
})
#Table(name="news")
public class News {
jpadao.java
public class JpaHibernateNewsDao implements Dao {
#PersistenceContext
private EntityManager entityManager;
#SuppressWarnings("unchecked")
#Override
#Transactional
public List<News> getList() throws DaoException {
List<News> news = entityManager.createNamedQuery("News.select").getResultList();
return news;
}
Found a answer: Spring just didn't see #Entity, so there was really no such #NamedQuery. Now I have to figure, why this config didn't work:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.example.testapp.model"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />

test and applicationContext

i use latest release of spring, spring data, jpa, hibernate and h2.
i try to run test (only repository test).
but i get this error: Failed to load ApplicationContext
my test class
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
#Transactional
#ContextConfiguration(
locations = {"classpath:applicationContext-test.xml"})
public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
...
}
my applicationContext-test.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<context:property-placeholder location="classpath:/jdbc.properties"/>
<context:component-scan base-package="com.test.*" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<jpa:repositories base-package="com.test.va.repository"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriodInMinutes" value="${jdbc.idleConnectionTestPeriodInMinutes}"/>
<property name="idleMaxAgeInSeconds" value="${jdbc.idleMaxAgeInSeconds}"/>
<property name="maxConnectionsPerPartition" value="${jdbc.maxConnectionsPerPartition}"/>
<property name="minConnectionsPerPartition" value="${jdbc.minConnectionsPerPartition}"/>
<property name="partitionCount" value="${jdbc.partitionCount}"/>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
<property name="statementsCacheSize" value="${jdbc.statementsCacheSize}"/>
<property name="releaseHelperThreads" value="${jdbc.releaseHelperThreads}"/>
</bean>
so it's a config error.

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;
}

Database connection exception using Spring, Hibernate, JPA e C3P0

I'm trying to configure my app to use C3P0 datasource (I can't use the datasource provided by the container).
But, when my app is starting, an exception has occurred:
The user must supply a JDBC connection
Bellow is my config files:
spring-config.xml:
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
</bean>
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:#host:1521:db" />
<property name="user" value="dbuser" />
<property name="password" value="passwd" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="maxStatements" value="0" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum" />
<property name="dataSource" ref="pooledDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
persistence.xml:
<persistence version="1.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_1_0.xsd">
<persistence-unit name="AppPU" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.jdbc.batch_size" value="50" />
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.EhCacheRegionFactory" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
</properties>
</persistence-unit>
</persistence>
Exception:
java.lang.UnsupportedOperationException: The user must supply a JDBC connection
at org.hibernate.connection.UserSuppliedConnectionProvider.getConnection(UserSuppliedConnectionProvider.java:54)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1573)
at org.hibernate.loader.Loader.doQuery(Loader.java:696)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2228)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2157)
at org.hibernate.loader.Loader.list(Loader.java:2117)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310)
at $Proxy286.getResultList(Unknown Source)
at com.embraer.core.jpa.DaoSupport.execQueryIndexedParameters(DaoSupport.java:327)
at com.embraer.core.jpa.DaoSupport.findByNamedQuery(DaoSupport.java:280)
at com.embraer.core.jpa.DaoSupport.findAll(DaoSupport.java:132)
at br.com.embraer.aheadpro.dao.imp.ConfigDAOImpl.findAll(ConfigDAOImpl.java:41)
at br.com.embraer.aheadpro.dao.ConfigRepoDAO.getAll(ConfigRepoDAO.java:35)
at br.com.embraer.aheadpro.service.ConfigService.refresh(ConfigService.java:27)
at br.com.embraer.aheadpro.service.ConfigService.getConfig(ConfigService.java:35)
at br.com.embraer.aheadpro.service.EmailService.init(EmailService.java:81)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:340)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:293)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:130)
... 91 more
Thanks everybody!
Maybe this might help: http://thejavablog.wordpress.com/2010/11/26/java-lang-unsupportedoperationexception-the-user-must-supply-a-jdbc-connection/ , it basically says that there's something missing from persistence.xml (<provider>org.hibernate.ejb.HibernatePersistence</provider> or maybe hibernate.connection.provider_class-property ?), and Hibernate's ConnectionProviderFactory chooses to create a UserSuppliedConnectionProvider, which has getConnection defined as such:
public Connection getConnection() {
throw new UnsupportedOperationException("The user must supply a JDBC connection");
}
I also compared this with one of our own Hibernate/JPA -setups that works just fine with C3PO, and the only differences I spotted were that we pass some more properties to c3p0.ComboPooledDataSource and some properties to org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter when defining EntityManagerFactory in the Spring configuration xml:
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="${jdbc.dialectClass}" />
</bean>
</property>
But I doubt that could be it. There are no properties defined in our persistence.xml (at all).

Resources