Spring Data JPA简介


1.概述

本文将重点介绍将Spring Data JPA引入Spring 4项目并完全配置持久层。有关使用基于Java的配置和项目的基本Maven pom设置Spring上下文的分步介绍,请参阅此文章。

2. Spring Data生成了DAO - 没有更多的DAO实现

正如前一篇文章中所讨论的,DAO层通常包含许多可以并且应该简化的样板代码。这种简化的优点很多:需要定义和维护的工件数量减少,数据访问模式的一致性和配置的一致性。

Spring Data将此简化向前推进了一步,并且可以完全删除DAO实现 - DAO的接口现在是唯一需要明确定义的工件。

为了开始利用JPA的Spring Data编程模型,DAO接口需要扩展JPA特定的Repository接口--JpaRepository。这将使Spring Data能够找到此接口并自动为其创建实现。

通过扩展接口,我们获得了标准DAO中开箱即用的标准数据访问最相关的CRUD方法。

3.Custom Access Method and Queries

如上所述,通过实现其中一个Repository接口,DAO已经定义并实现了一些基本的CRUD方法(和查询)。

要定义更具体的访问方法,Spring JPA支持很多选项 - 您可以:

只需在界面中定义一个新方法 使用@Query注释提供实际的JPQ查询 在Spring Data中使用更高级的Specification和Querydsl支持 通过JPA命名查询定义自定义查询 在第三个选项 -规格和Querydsl支持-类似于JPA标准,而是采用了更灵活,方便的API -使得整个操作更具有可读性和可重用性。在处理大量固定查询时,此API的优势将变得更加明显,这些查询可能通过较少数量的可重复使用的块以更加简洁的方式表达,这些块可以以不同的组合形式发生。

最后一个选项的缺点是它涉及XML或者使用查询加载域类。

3.1。Automatic Custom Queries

当Spring Data创建新的Repository实现时,它会分析接口定义的所有方法,并尝试从方法名称自动生成查询。虽然这有一些限制,但它是一种非常强大而优雅的方法,可以轻松定义新的自定义访问方法。

让我们看一个例子:如果被管实体有一个名称字段(以及Java Bean标准的getName和setName方法),我们将在DAO接口中定义findByName方法 ; 这将自动生成正确的查询:

public interface IFooDAO extends JpaRepository< Foo, Long >{

   Foo findByName( String name );

}

这是一个相对简单的例子; 查询创建机制支持更大的关键字集。

如果解析器无法将该属性与域对象字段匹配,则抛出以下异常:

java.lang.IllegalArgumentException: No property nam found for type class org.rest.model.Foo

3.2。Manual Custom Queries

现在让我们看一下我们将通过@Query注释定义的自定义查询:

@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)")
Foo retrieveByName(@Param("name") String name);
为了对查询的创建进行更细粒度的控制,例如使用命名参数或修改现有查询,引用是一个很好的起点。

4.Transaction Configuration

Spring Data托管DAO的实际实现确实是隐藏的,因为我们不直接使用它。但是 - 它是一个简单的实现 - SimpleJpaRepository - 它使用注释定义事务语义。

更明确地 - 在类级别使用只读@Transactional注释,然后为非读取方法重写该注释。其余的事务语义是默认的,但是每个方法都可以轻松地重写这些语义。

4.1.Exception Translation is Alive and Well

问题是 - 因为我们没有使用默认的Spring ORM模板(JpaTemplate,HibernateTemplate) - 我们是否通过使用Spring Data JPA丢失了异常翻译?- 我们不会将我们的JPA异常转换为Spring的DataAccessException层次结构吗?

当然不是 - 通过在DAO上使用@Repository注释仍然可以启用异常转换。此批注使Spring bean后处理器能够使用在Container中找到的所有PersistenceExceptionTranslator实例来建议所有@Repository bean,并像以前一样提供异常转换。

通过集成测试可以轻松验证异常转换确实处于活动状态的事实:

@Test(expected = DataIntegrityViolationException.class)
public void givenFooHasNoName_whenInvalidEntityIsCreated_thenDataException() {
    service.create(new Foo());
}

请记住,异常转换是通过代理完成的 - 为了使Spring能够在DAO类周围创建代理,这些代理不能被声明为final。

5. Spring数据配置

要使用XML配置激活Spring JPA存储库支持 - 我们将使用jpa命名空间并指定DAO接口所在的包:

<?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:jpa="http://www.springframework.org/schema/data/jpa"
   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.xsd">

<jpa:repositories base-package="org.rest.dao.spring" />

</beans>

从 Spring Data 1.4开始,我们可以对仅使用Java的配置执行相同的操作:

@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
public class PersistenceConfig { ... }

6. Spring Java或XML配置

我们已经在前一篇文章中详细讨论了如何在Spring中配置JPA。Spring Data还利用了对JPA @PersistenceContext注释的Spring支持,它用于将EntityManager连接到负责创建实际DAO实现的Spring工厂bean - JpaRepositoryFactoryBean。

除了已经讨论过的配置之外,我们还需要包含Spring Data XML Config - 如果我们使用XML:

@Configuration
@EnableTransactionManagement
@ImportResource( "classpath*:*springDataConfig.xml" )
public class PersistenceJPAConfig{
   ...
}

7. The Maven Dependency

除了前一篇文章中定义的JPA Maven配置之外,还添加了spring-data-jpa依赖项:

<dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-jpa</artifactId>
   <version>1.6.0.RELEASE</version>
</dependency>