Configuring Spring + Hibernate JPA Transaction Manager through JTA - java

I previously had this config for Hibernate using RESOURCE-LOCAL transaction type:
persistence.xml:
<persistence-unit name="myPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
</persistence-unit>
applicationContext (dataaccess bit):
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory"></bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="persistenceUnitName" value="myPU"/>
<property name="jpaProperties">
<props>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<!-- Are there any other properties required? -->
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/CNTXESDB" />
<property name="lookupOnStartup" value="true" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
But this kind of transaction seems not to work with Glassfish, so I had to switch to JTA transactions.
The problem is -- to get Spring to manage transaction creation (through #Transactional) I need to define a TransactionManager bean but JtaTransactionManager included in spring-tx does not accept an entityManagerFactory bean, so it does not know where the entityManager is in order to open/close/flush Hibernate session.
So how can I configure Spring with Hibernate to use JTA transactions?
EDIT:
turns out you can use RESOURCE_LOCAL transactions with Glassfish, but somehow you cannot have a persistence.xml file. I renamed this file to my_persistence.xml and configured LocalContainerEntityManagerFactoryBean like this:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="persistenceUnitName" value="myPU"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/my_persistence.xml" />
<property name="jpaProperties">
<props>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>

I had a similar problem and finally I solved as you can see in this little demo:
https://github.com/miguelangelprogramacion/spring4_jpa_hibernate
With [1] as a reference, I prefer to use Spring's Transaction Support before JTA.
Also, I've used an annotation based approach.
[1] http://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/

Related

Javax Persistence Error : Unknown Entity com.samplewebentities.Customer

I'm trying to persist an entity using EntityManagerFactory defined in my bean. The function looks like this:
private BaseMasterEntity saveEntity(BaseMasterEntity entity){
EntityManagerFactory emf = (EntityManagerFactory)context.getBean("entityManagerFactory");
EntityManager sf = emf.createEntityManager();
sf.getTransaction().begin();
sf.persist(entity);
sf.getTransaction().commit();
sf.close();
return entity;
}
The problem here is when it persists it cannot find the entity. The entity has #Entity defined clearly with the javax.persistance annotation. This is how my context file looks btw:
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="*my jdbc setting*" />
<property name="username" value="hr" />
<property name="password" value="hr" />
</bean>
<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="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="packagesToScan"
value="classpath*:com.samplewebentities"></property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<tx:annotation-driven transaction-manager="transactionManager" />
If it helps, the classpath*:com.samplewebentites is a different component (The application is a combination of many different components/projects: Using SCA here).
No need for classpath
..
<property name="packagesToScan"
value="com.samplewebentities"></property>
..

How to setup xa datasource using Spring and weblogic

I am having an issue creating xa datasources in spring 4.0.
I have setup my datasources in weblogic using an xa driver.
I then added added jndi-lookups for the data sources in spring:
<jee:jndi-lookup id="dataSourceOne" jndi-name="/jdbc/XAONE" resource-ref="true" />
<jee:jndi-lookup id="dataSourceTwo" jndi-name="/jdbc/XATWO" resource-ref="true" />
I have then created the configuration for the entity managers:
<bean id="emfone" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceOne" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan" value="..." />
</bean>
<bean id="emftwo"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceTwo" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan" value="..." />
</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>
After this I have my transaction manager configured:
<tx:annotation-driven />
<tx:jta-transaction-manager />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emfone" />
<qualifier value="tmOne"/>
</bean>
<bean id="docTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emftwo" />
<qualifier value="tmTwo"/>
</bean>
I have a service class method annotated with #Transactional that calls a DAO. The DAO uses both entity managers for persisting data.
When the DAO tries to persist using the emftwo a no transaction in progress error is thrown. Does anybody know where I am going wrong?
Thanks,

Configure hibernate in spring application

I have successfully configured hibernate and I can run transactions but only from the psvm of the DAO class. I want to configure it with my spring app using the same configuration file i.e. hibernate.cfg.xml.
How can I do this? Most tutorials I've read simply neglect the hibernate configuration file.
You can add this code to you xml file to configure hibernate.
<!-- Hibernate Related Configuration. -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://192.168.1.9:5432/dbname"/>
<property name="username" value="postgres"/>
<property name="password" value="pwd"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
The hibernate.cfg.xml file is specified for the LocalEntityManagerFactoryBean, along with your DataSource
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/hibernate.cfg.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
Here you can find an example of a Spring XML configuration containing some Hibernate configuration

How to avoid too many connections on spring+hibernate?

I´ve my hibernate configuration inside my spring-context, but after a little time of use I´m getting the too many connections error. Here is my code:
Spring context:
<!-- Beans Declaration -->
<bean id="Usuarios" class="com.proximate.model.Usuarios"/>
<!-- Service Declaration -->
<bean id="UsuariosService" class="com.proximate.service.UsuariosService">
<property name="usuariosDAO" ref="UsuariosDAO" />
</bean>
<!-- DAO Declaration -->
<bean id="UsuariosDAO" class="com.proximate.dao.UsuariosDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb" />
<property name="user" value="user" />
<property name="password" value="password" />
<property name="maxPoolSize" value="50" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- Session Factory Declaration -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>com.proximate.model.Usuarios</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<context:annotation-config />
<!-- Transaction Manager is defined -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
and here is how I use my session factory inside my dao:
private SessionFactory sessionFactory;
private HibernateTemplate hibernateTemplate;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
Query query = hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery("SELECT ID FROM usuarios");
Integer cantidad = new Integer(((BigInteger) query.uniqueResult()).intValue());
Why is my code opening so many connections. I heard that using a HibernateUtil class to load a session after logging might be what I need, but how do you implement it when using spring??
Thanks in advance!!
I don't know much about hibernate itself, but i think closing the session might help.
That's how JPAs EntityManager works - you have to close it to close underlaying connection.
It looks like your hibernate query is global? I would guess the cause is probably because it is not contained in a method with a transactional annotation around it.

ClassNotFoundException: org.hibernate.hql.internal.ast.HqlToken even after adding classic.ClassicQueryTranslatorFactory [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
org.hibernate.HibernateException: could not instantiate QueryTranslatorFactory: org.hibernate.hql.classic.ClassicQueryTransactionFactory
I am using Hibernate 4, Spring 3 and JSF 2.0. While running jsf page I am getting
org.hibernate.QueryException: ClassNotFoundException:
org.hibernate.hql.internal.ast.HqlToken [select generatedAlias0 from
net.test.model.Request as generatedAlias0]
I already have the following under hibernate properties in applicationContext.xml
<prop key="hibernate.query.factory_class">org.hibernate.hql.internal.classic.
ClassicQueryTranslatorFactory
</prop>
Please note that I have added org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean and org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter, I suspect that after adding this I was again getting org.hibernate.QueryException: ClassNotFoundException
My question what is the equivalent of ClassicQueryTranslatorFactory for spring properties?
If no such properties how could I resolve this?
applicationContext.xml
<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-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Spring view scope customized -->
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="view">
<bean class="org.primefaces.spring.scope.ViewScope" />
</entry>
</map>
</property>
</bean>
<context:component-scan base-package="net.test" />
<!-- Data Source Declaration -->
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc" />
<property name="jdbcUrl"
value="jdbc:oracle:thin:#server:1521:orcl" />
<property name="user" value="scott" />
<property name="password" value="tiger" />
<property name="maxPoolSize" value="10" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<!-- JPA Entity Manager Factory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="packagesToScan" value="net.test.model" />
<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>
</bean>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
<!-- Session Factory Declaration -->
<bean id="SessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>net.test.model.Request</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory
</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations
<tx:annotation-driven transaction-manager="txManager" />-->
<!-- Transaction Manager is defined
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>-->
<!-- Transaction Config -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:annotation-driven transaction-manager="txManager"/>
<context:annotation-config/>
<bean id="hibernateStatisticsMBean" class="org.hibernate.jmx.StatisticsService">
<property name="statisticsEnabled" value="true" />
<property name="sessionFactory" value="#{entityManagerFactory.sessionFactory}" />
</bean>
<bean name="ehCacheManagerMBean"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true" />
</bean>
<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="server" ref="mbeanServer" />
<property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/>
<property name="beans">
<map>
<entry key="SpringBeans:name=hibernateStatisticsMBean" value-ref="hibernateStatisticsMBean" />
<entry key="SpringBeans:name=ehCacheManagerMBean" value-ref="ehCacheManagerMBean" />
</map>
</property>
</bean>
</beans>
edit modules/org/antlr/main/module.xml by adding the line <module name="org.hibernate" optional="true"/> inside the <dependencies> section. The issue must be resolved.
Thank you.
This issue has been resolved by doing the following
Use antlr 2.7.6 version which is compatible with Hibernate, add a reference in setDomainEnv.cmd
set CLASSPATH=\maven\repo\antlr\antlr\2.7.6\antlr-2.7.6.jar;%CLASSPATH%
More information here
Thanks

Categories