However, I used Spring's JpaTemplate which got some attention from Tomek Nurkiewicz who pointed out that this is not really a recommended way of doing it.
The recommended way of handling JPA in your DAO classes is to use an EntityManager injected with JEE's @PersistenceContext annotation.
Let's see what the configuration looks like.
Your Spring beans file
- Remove the jpaTemplate bean declaration.
- Remove the jpaTemplate bean references.
- Add PersistenceAnnotationBeanPostProcessor.
Here's the whole file:
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Dogs" />
</bean>
<bean id="dogsDao" class="me.m1key.springtx.dao.DogsDaoImpl" />
<bean id="dogsBean" class="me.m1key.springtx.beans.DogsBean"
scope="singleton">
<property name="dogsDao" ref="dogsDao" />
</bean>
<tx:annotation-driven transaction-manager="myTransactionManager" />
<bean id="myTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
Your DAO class
- Remove extending JpaDaoSupport.
- Add @PersistenceContext injected EntityManager.
- Replace getJpaTemplate() with the EntityManager (that's not always a non-brainer).
- Make each DAO method @Transactional (you can set its readOnly attribute to true if the method only reads data).
package me.m1key.springtx.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
import me.m1key.springtx.entities.Dog;
public class DogsDaoImpl implements DogsDao {
@PersistenceContext
private EntityManager em;
@SuppressWarnings("unchecked")
@Transactional(readOnly = true)
public List<Dog> retrieveAllDogs() {
return em.createQuery("from Dog").getResultList();
}
@Transactional(readOnly = true)
public Long retrieveNumberOfDogs() {
System.out.println(em);
return (Long) em.createQuery(
"select count(d) from Dog d")
.getSingleResult();
}
@Transactional(readOnly = false)
public void persistDog(Dog dog) {
em.persist(dog);
}
}
Summary
We removed an additional thin layer of JpaTemplate.
Many sites (e.g. the official Hibernate site) will tell you you cannot use @PersistenceContext in Java SE applications - well we just did, thanks to Spring (thanks to PersistenceAnnotationBeanPostProcessor).
I got some of the information from the blog by Łukasz.
Download source code for this article

27 comments: