乐者为王

Do one thing, and do it well.

JPA + Spring 2入门

JPA(Java Persistence API)是EJB 3.0 新引入的一个把Java数据对象映射成关系数据库对象的数据持久化编程模型,它弥补了JDBC、ORM、EJB 2等在Java对象持久化方面的不足之处,并且非常易于使用。JPA可以被当作一个单独的 POJO(Plain Old Java Object)持续化使用,或者被集成到任意Java EE兼容的容器或其它的轻量级框架(例如Spring)等一起使用。

配置JPA

Spring提供了两种方法创建JPA的EntityManagerFactory对象。

方法1:

1
2
3
4
5
<beans>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="persistenceUnit" />
    </bean>
</beans>

FactoryBean创建的EntityManagerFactory适用于仅通过JPA进行数据访问的环境。由于使用了PersistenceProvider自动侦测机制,所以只能从默认路径classpath:META-INF/persistence.xml中读取配置信息。

方法2:

1
2
3
4
5
6
7
8
<beans>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="someDataSource" />
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
        </property>
    </bean>
</beans>

FactoryBean提供了对JPA EntityManagerFactory的完整控制,非常适合那种有简单定制需要的环境。你可以处理多个persistence.xml配置文件;覆盖persistence.xml文件的默认路径;可以传递Spring托管的JDBC DataSource给JPA PersistenceProvider,用来替代persistence.xml中的JDBC配置(这个Spring托管的DataSource通常被作为nonJtaDataSource传送给PersistenceProvider,并且覆盖persistence.xml中相同的nonJtaDataSource)。

数据访问

基于JPA的DAO可以通过三种方式进行数据访问JpaDaoSupport,JpaTemplate和plain JPA。其中JpaTemplate是plain JPA的封装,而JpaDaoSupport又是JpaTemplate的封装。无疑,使用不对Spring产生任何依赖的Plain JPA的API进行编程是最好选择。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ProductDaoImpl implements ProductDao {
    private EntityManager entityManager = null;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Collection loadProductsByCategory(String category) {
         Query query = em.createQuery("from Product as p where p.category = :category");
         query.setParameter("category", category);
         return query.getResultList();
    }
}

需要注意的是,必须激活PersistenceAnnotationBeanPostProcessor功能才能让Spring识别@PersistenceContext注解。

1
2
3
4
5
6
<beans>
    <!-- JPA annotations bean post processor -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="productDao" class="com.codemany.netlink.dao.impl.ProductDaoImpl" />
</beans>

异常转化

Spring提供了一个允许通过使用@Repository注解进行透明的异常转化的解决方案。

1
2
@Repository
public class ProductDaoImpl implements ProductDao {
1
2
3
<beans>
    <!-- Exception translation bean post processor -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

后置处理器将自动的寻找所有的异常转化器(PersistenceExceptionTranslator这个接口的实现类)并通知所有打上@Repository注解的bean,从而能够使得被找到的异常转化器能够在抛出异常时做相应的异常转化工作。

总的来说,DAO能够基于普通的Java持久层API和注解来实现,但同样也能享受到由Spring管理事务、IoC和透明的异常转化(转化成为Spring的异常体系)等好处。

Comments