EntityManager configuration in each DAO - java

I understand that this is a very long question, but i wanted to ask everything because i'm
stuck with these things for more than 2 weeks and i'm in a situation to solve this within
this week. Please guide me in this matter.
I'm Using EclipseLink jpa version 2, Spring 3, jdk6, MySQL5 and tomcat7.
I have configured the following in each of my DAO classes.
#PersistenceContext
private EntityManager em;
I have the following in my Spring xml:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="url" value="jdbc:mysql://localhost:3306/xxxxx"/>
<property name="username" value="xxxx"/>
<property name="password" value="xxxx"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" >
<property name="showSql" value="true"/>
<property name="generateDdl" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
From Persistence.xml:
<persistence-unit name="xxxxx" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<-- class mappings -->
</persistence-unit>
I've got few confusion about what i have done:
Is the EntityManager injected by Spring? (I understand that #PersistenceContext is a
J2EE annotation, so wondering whether it is injected without Spring's contribution).
As i have already mentioned, i have injected EntityManager in all the DAO classes. Is
this a good practice? or should i make it Singleton by having a separate class like
PersistenceManager, which has EntityManager attribute wired, and have
getEntityManager() method?
As you can see above, i have configured Spring transactions. But when i do CRUD
operations continuously for 2-3 times, application gets stuck and fails with EclipseLink
exception saying unable to get lock, timeout etc. Am i doing anything wrong here or
missing any transaction configurations??
With the above configurations, i can only use #Transactional annotation with default
values which are PROPAGATION_REQUIRED,ISOLATION_DEFAULT. If i change these for any other
values, such as #Transactional(PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE) etc,
application throws exception as Custom isolation levels are not supported. Again, am
i missing any configurations?
Thanks.

Yes, spring recognizes the #PersistenceContext annotation and injects the entity manager
Spring takes care of that - it injects the same EntityManager instance in all DAOs. In fact, it injects a proxy so that each request uses a different entity manager.
Normally everything should run fine. You need <tx:annotation-driven /> in order to use #Transactional
JPA only supports the default isolation level. You can work this around by customizing the spring jpa dialect, but there's nothing built-in. The way to go is extend XJpaDialect (in your case X=EclipseLink), override the beingTransaction, obtain the Connection (in an eclipse-link specific way), set the desired isolation level (accessible through the transaction definition), and configure this as a property of your LocalContainerEntityManagerFactoryBean:
<property name="jpaDialect">
<bean class="com.foo.util.persistence.EclipseLinkExtendedJpaDialect" />
</property>

Related

How to setup multiple data sources with Spring and JPA

In our application, we want to set multiple data source with Spring and JPA. Hence we have created 2 entityManagerFactory, 2 data source and 2 transaction- manager.
web.xml
<param-value>
/WEB-INF/a_spring.xml
/WEB-INF/b_spring.xml
</param-value>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="db1" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.RcA</class>
</persistence-unit>
<persistence-unit name="db2" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.Rcb</class>
</persistence-unit>
</persistence>
a_spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" />
<aop:config>
<aop:pointcut id="rOperation" expression="execution(* com.rh.services.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="rOperation"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/db1" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="db1" />
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
</bean>
</property>
</bean>
I also declare another entityManagetFactory,Transaction Manager and dataSource to b_spring.xml.
Error
Initialization of bean failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [javax.persistence.EntityManagerFactory] is
defined: expected single bean but found 2 Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [javax.persistence.EntityManagerFactory] is
defined: expected single bean but found 2 at
org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:303)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:451)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:428)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:582)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolve(PersistenceAnnotationBeanPostProcessor.java:553)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.inject(PersistenceAnnotationBeanPostProcessor.java:489)
In case of multiple data source configuration, we need to define which one will be considered as a primary data source. we can specify that using #Primary annotation in java config or primary=true in XML bean config.
As there is two entity manager being created in XML, we need to use #Qualifier to specify which bean should be injected where. In your case, something like this.
#PersistenceContext(unitName = "db1")
public void setEntityManager(#Qualifier("entityManagerFactory") EntityManager entityMgr) {
this.em = entityMgr;
}
for XML configuration, we can do something like this
<bean id="BaseService" class="x.y.z.BaseService">
<property name="em" ref="entityManagerFactory"/>
<property name="em1" ref="entityManagerFactory1"/>
</bean>
<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>
Did you try providing the package details which contains your EntityManagerFactory bean?
You can provide the package details as a property in you bean definition -
<property name="packagesToScan" value="com.XX.XX.XX.XX" />
new property to be added in this block -
<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="db2" />
<property name="dataSource" ref="dataSource1"/>
<-- add here for both beans -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
</bean>
</property>
</bean>
Also, you are missing the persistenceXmlLocation property -
<property name="persistenceXmlLocation" value="***/persistence.xml" />
The error message you've posted indicates that you're autowiring by type for an object of type EntityManagerFactory. None of the code you've shown so far contains such an injection, which implies that it's probably in some code you haven't yet posted.
If you were to post the full stack trace of the error, you'd be able to walk up the stack to see which bean contains the un-satisfiable reference to an EntityManagerFactory object, which in turn would let you change how you're referencing it to allow a reference to the specific bean you want.
Update
Based on the further information you provided (thank you) and some Googling, it seems as though other users have similarly found that specifying a unitName isn't enough to get the correct EntityManager injected. Several posts online back up #lucid's recommendation to use the #Qualifier annotation to get Spring to select the correct bean, but unfortunately that annotation was introduced in 2.5 so it's only available to you if you upgrade. (Which, given the age of the Spring framework that you're using, is probably a good idea, but that's a separate conversation.)
However, several users have indicated that an alternate approach is available in 2.0.5, using a single PersistenceUnitManager that references multiple data sources rather than multiple persistence units that each reference a single data source. From the official Spring docs: https://docs.spring.io/spring/docs/2.0.x/reference/orm.html#orm-jpa-multiple-pu.
Overall I'd suggest you consider upgrading to a version of Spring that's not more than a decade old, which would let you specify an #Qualifier annotation per #lucid's answer. But if that's not possible for some reason, the PersistenceUnitManager approach should give you a way to make it work within Spring 2.0.5.
There are a couple of things that don't look good to me. The name of the setters won't match the property names, I think that is important, the second thing is about the inheritance, some annotations sometimes only works in concrete classes not in base classes. I would try to change the base service as follow.
public class BaseService {
#PersistenceContext(unitName = "db2")
private EntityManager em;
#PersistenceContext(unitName = "db1")
private EntityManager em1;
public EntityManager getEm() {
return em;
}
protected EntityManager getEm2() {
return em1;
}
public void setEm(EntityManager entityMgr) {
this.em = entityMgr;
}
public void setEm1(EntityManager entityMgr) {
this.em = entityMgr;
}
}
If that does not work I probably try to remove the base class and see if I put the annotation under the concrete class I can make that works, I would do that moving just the annotations to the RcAbcMaintenanceServiceImpl class and remove the extend statement that inherits from the BaseService
Also, I noticed that the PersistenceContext annotation has another param https://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html, so you could try to use the name as well to match the id on the bean definition.

Spring #Transactional on one service method spanning over two Hibernate transaction managers

I was wondering if it is possible to use two transaction manager in one service methods.
Because due to the limitation of client's mysql db configuration, we have got 2 different datasources within one database, i.e., one user/pwd/url per schema. Thats why i have to configured two transaction managers. Now I got problem when it comes to the service implementation. See the following code:
public class DemoService{
...
#Transactional(value = "t1")
public doOne(){
doTwo();
}
#Transactional(value = "t2")
public doTwo(){
}
...
}
if I using this code pattern, i always got the exception
org.hibernate.HibernateException: No Session found for current thread
If i run the two methods seperately, it workd fine.
Did i miss something? Or there is other work around here?
Any advice would be appreciated.
btw: some of my configuration
<bean id="sessionFactorySso" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="mappingLocations">
<list>
<value>classpath*:sso.vo/*.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="generateDdl">true</prop>
<prop key="hibernate.dialect">${dialect} </prop>
</props>
</property>
<property name="dataSource" ref="dataSourceSso"/>
</bean>
<bean id="dataSourceSso" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${driver}"/>
<property name="jdbcUrl" value="${sso.url}"/>
<property name="user" value="${sso.username}"/>
<property name="password" value="${sso.password}"/>
<!-- these are C3P0 properties -->
<property name="acquireIncrement" value="2" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="2" />
<property name="automaticTestTable" value="test_c3p0" />
<property name="idleConnectionTestPeriod" value="300" />
<property name="testConnectionOnCheckin" value="true" />
<property name="testConnectionOnCheckout" value="true" />
<property name="autoCommitOnClose" value="true" />
<property name="checkoutTimeout" value="1000" />
<property name="breakAfterAcquireFailure" value="false" />
<property name="maxIdleTime" value="0" />
</bean>
<bean id="transactionManagerSso" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactorySso"/>
<qualifier value="sso" />
</bean>
<tx:annotation-driven transaction-manager="transactionManagerSso" />
Because you want to enlist two data sources in one transaction you need XA(Global) Transaction.
Therefore you need to:
Set the Spring JTA transaction manager
You Hibernate properties should use the JTA platform settings
Your data source connections should be XA complaint
You need an application server JTA transaction manager or a stand-alone tarnsaction manager (Bitronix, Atomikos, JOTM)
You will need two session factory configurations, one for each individual data source.
And you won't have two transaction managers: t1 and t2, but instead you will enlist two transactional XA data sources that will be automatically enlisted in the same global transaction, meaning you will have two XA connections being enlisted in the same global transaction. The XA transaction will use the 2PC protocol to commit both resources upon commit time.
Checkout this Bitronix Hibernate example.
You have a few options:
Inject the bean into itself and use the reference to call doTwo(). This really goes against the whole idea of IoC and AOP so I don't recommend it.
Switch to compile time weaving. Rather than using proxies, Spring (actually the AspectJ compiler) will add the bytecode to start/stop transactions to your class at compile time. There are pros and cons to this approach. See this page for more details.
Use load time weaving. Same as #2 except that your classes are modified as they are loaded rather than at compile time. IMO, Java classloading is complicated enough. I'm sure this works great for some folks but I personally would avoid this.
As Vlad pointed out, you can use JTA and XA.
Start a new transaction against transaction manager 2 within doOne() before calling doTwo(). RTFM on programmatic transaction management.
Check out ChainedTransactionManager. It essentially aggregates multiple transaction managers and does a "best effort" with commit/rollback. This is NOT a true two-phase commit like Vlad's solution.
All of these except for Vlad's solution (#4) have the potential to leave the databases in an inconsistent state. You need to use JTA/XA/two-phase commit to ensure consistency in the event that one of the TX managers throws an exception at commit time.

Is PersistenceAnnotationBeanPostProcessor of any use at all?

According to its JavaDoc, PersistenceAnnotationBeanPostProcessor seems to be responsible for injecting the EntityManager with the annotation #PersistenceContext. It appears to imply without this bean declared in the Spring application context xml, the #PersistenceContext annotation won't work.
However, based on my experiments, this is not the truth.
Persistence.xml
<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="default" transaction-type="RESOURCE_LOCAL" />
</persistence>
Spring application context XML
<context:component-scan base-package="com.test.dao" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="default"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"/>
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb"/>
<property name="username" value="APP"/>
<property name="password" value="APP"/>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!--
<bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
-->
UserDaoImpl
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#PersistenceContext
protected EntityManager entityManager;
#Transactional
public void save(User user) {
entityManager.persist(user);
}
}
Whether I comment or uncomment the persistenceAnnotation bean, the result is the same. It doesn't hurt to leave the bean around, but what's the use of this bean?
I am using Spring 3.0.5.
Could someone provide a scenario where taking out this bean will result in failure?
Also I am not fond of creating an empty persistence unit just to fool Spring. Luckily this problem has been addressed in Spring 3.1.0.
The PersistenceAnnotationBeanPostProcessor transparently activated by the <context:component-scan /> element. To be precise it's the <context:annotation-config /> element that activates the bean but this element in turn gets transparently activated by <context:component-scan />.
As Oliver Gierke mentioned, org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor is automatically loaded into App Context by Spring when using annotation based configuration. One of its duties is to search the proper entity EntityManagerFactory that would provide the EntityManager for you #PersistenceContext annotated properties.
If you have multiple EntityManagerFactory beans in you spring config/context and you have #PersistenceContext annotations without a unitName attribute (lets say you are using a framework that comes with such a bean, and you can't touch framework code), you may run into this exception: org.springframework.beans.factory.NoUniqueBeanDefinitionException.
I found this workaround in case you tun into this:
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" >
<property name="defaultPersistenceUnitName" value="entityManagerFactory"/>
</bean>
This would override the default PersistenceAnnotationBeanPostProcessor loaded by Spring with a new one with defaultPersistenceUnitName.

Inject entity manager from XML in Spring

I need to do very similar thing to what is described in Injecting Entitymanager via XML and not annnotations, but I need to inject from XML the real, container-created, entity manager, so that it behaves exactly as if there is a real #PersistenceContext annotation. I've found a LocalEntityManagerFactoryBean (notice missing "Container" word), but I'm affraid that it creates a new entity manager factory and therefore entity manager won't be compatible with that injected via real #PersistenceContext annotation.
I will describe the reason, because it is weird and maybe the solution to my problem is to choose completely different approach. I'm using PropertyPlaceholderConfigurer in my spring configuration and in this configurer I'm referencing other beans. I'm experiencing a bug that autowiring doesn't work in those referenced beans. I don't know why and how PropertyPlaceholderConfigurer turns off autowiring in those referenced beans but the fact is, that if I replace autowiring by xml configuration for those beans, everything works. But I'm unable to replace autowiring of EntityManager, since it's not standard spring bean, but jndi-loaded something I don't fully understand.
One way or the other, is there some solution?
in spring-bean.xml ,
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="USER_TEST"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="eclipselink.weaving">false</prop>
</props>
</property>
<bean id="PersonDao" class="com.xxx.java.person.persistence.PersonDAO">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="earlyInitializedApplicationSettingsService" class="...services.impl.ApplicationSettingsServiceImpl" autowire-candidate="false">
<property name="applicationSettingsDao">
<bean class="....impl.ApplicationSettingsDaoImpl">
<property name="entityManager">
<bean class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/persistence/somePersistenceUnit"/>
</bean>
</property>
</bean>
</property>
</bean>
</property>
</bean>
Notice mainly the fact, that I'm not using standard jee:jndi-lookup, because it didn't work (in the conditions created by PropertyPlaceholderConfigurer) and that was the source of my confusion. When I used direct JndiObjectFactoryBean, it worked.

Does HibernateTemplate work with Envers? If so, how?

I am trying to use Envers on a project that also uses Hibernate and Spring - and I appreciate a lot the code reduction offered by HibernateTemplate.
I configured Envers under JPA, and after a few tweaks I was able to have the schema generated by the EnversHibernateToolTask Ant task (including the auditing tables). However, when I write code such as:
hibernateTemplate.saveOrUpdate(f);
the data is persisted, but nothing goes to the auditing tables. Conversely, if I write:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(f);
em.getTransaction().commit();
then data goest to the audit tables (but I'd rather use the former syntax - I know using JPA's EntityManager decouples that code from Hibernate, but it simple does not pay off the hassle - changing ORM engine is not in my wildest dreams for this project.)
It may help to check my applicationContext.xml configuration:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="projetox" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.w2it.projetox.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
...
</bean>
and here is my persistence.xml setup:
<persistence-unit name="projetox" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<!-- Hibernate Envers -->
<property name="hibernate.ejb.event.post-insert"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-update"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-delete"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-update"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.pre-collection-remove"
value="org.hibernate.envers.event.AuditEventListener" />
<property name="hibernate.ejb.event.post-collection-recreate"
value="org.hibernate.envers.event.AuditEventListener" />
</properties>
</persistence-unit>
Does anyone have a hint on what is going on here? Thank you!
HibernateTemplate has its JPA counterpart, JpaTemplate which provides a fairly similar functionality.
The reason Envers doesn't work with HibernateTemplate is because it relies on JPA events (you can see the listeners declared in your persistence.xml above) triggered when EntityManager is used. It's possible in theory to write code to trigger those events from Hibernate session when HibernateTemplate is used, but it's rather involved.
All u needed to do was put #Transactional in your Dao or services which call the dao.save()/ update methods.
Even if you register your eventlistener these events are not fired unless you use transcational of the Spring FW. Spring has to know and tell hibernate that these events are fired.

Categories