Spring Data JPA简介

2023/05/18

1. 概述

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

延伸阅读

使用Spring的JPA指南

使用Spring设置JPA-如何设置EntityManager工厂和使用原始JPA API。

阅读更多

Spring Data中的CrudRepository、JpaRepository和PagingAndSortingRepository

了解Spring Data提供的不同风格的Repository。

阅读更多

使用Spring和Java泛型简化DAO

通过使用单一的、通用的DAO简化数据访问层,这可以实现优雅的数据访问,没有不必要的混乱。

阅读更多

2. Spring Data Generated DAO-不再有DAO实现

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

Spring Data将这种简化更进一步,使得完全删除DAO实现成为可能。DAO的接口现在是我们需要显式定义的唯一组件。

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

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

3. 自定义访问方式和查询

如前所述,通过实现Repository接口之一,DAO已经定义和实现了一些基本的CRUD方法(和查询)

为了定义更具体的访问方法,Spring JPA支持相当多的选项:

  • 只需在接口中定义一个新方法
  • 使用@Query注解提供实际的JPQL查询
  • 在Spring Data中使用更高级的Specifications和Querydsl支持
  • 通过JPA命名查询定义自定义查询

第三种方法,Specifications和Querydsl支持,类似于JPA Criteria,但是使用了更灵活方便的API。这使得整个操作更具可读性和可重用性。当处理大量固定查询时,此API的优势将更加明显,因为我们可以通过较少数量的可重用块来更简洁地表达这些查询。

最后一种方法的缺点是它要么涉及XML,要么给域类增加查询负担。

3.1 自动自定义查询

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

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

public interface FooDAO extends JpaRepository<Foo, Long> {
    Foo findByName(String name);
}

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

如果解析器无法将属性与域对象字段匹配,我们将得到以下异常:

java.lang.IllegalArgumentException: No property nam found for type class cn.tuyucheng.taketoday.spring.data.persistence.model.Foo

3.2 手动自定义查询

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

@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)")
Foo retrieveByName(@Param("name") String name);

要对查询的创建进行更细粒度的控制(例如使用命名参数或修改现有查询),该参考资料是一个很好的起点。

4. 事务配置

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

更明确地说,这在类级别使用只读的@Transactional注解,然后为非只读方法覆盖该注解。其余的事务语义是默认的,但这些可以很容易地根据方法手动覆盖。

4.1 异常转换仍然存在

现在的问题是:由于Spring Data JPA不依赖于旧的ORM模板(JpaTemplate、HibernateTemplate),并且自Spring 5以来它们已被删除,我们是否仍要将JPA异常转换为Spring的DataAccessException层次结构?

答案当然是。通过在DAO上使用@Repository注解仍然可以启用异常转换。此注解使Spring bean后处理器能够向所有@Repository bean提供在容器中找到的所有PersistenceExceptionTranslator实例的通知,并像以前一样提供异常转换。

让我们通过集成测试来验证异常转换:

@Test
final void whenInvalidEntityIsCreated_thenDataException() {
	assertThrows(DataIntegrityViolationException.class, () -> service.create(new Foo()));
}

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

5. Spring Data JPA Repository配置

要激活Spring JPA Repository支持,我们可以使用@EnableJpaRepositories注解并指定包含DAO接口的包:

@EnableJpaRepositories(basePackages = "cn.tuyucheng.taketoday.spring.data.persistence.repository")
public class PersistenceConfig {
    // ...
}

我们可以对XML配置执行相同的操作:

<jpa:repositories base-package="cn.tuyucheng.taketoday.spring.data.persistence.repository" />

6. Java或XML配置

在上一篇文章中,我们已经非常详细地讨论了如何在Spring中配置JPA。Spring Data还利用了Spring对JPA @PersistenceContext注解的支持。它使用该注解将EntityManager注入到负责创建实际DAO实现JpaRepositoryFactoryBean的Spring工厂bean。

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

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

7. Maven依赖

除了JPA的Maven配置,就像在之前的文章中一样,我们将添加spring-data-jpa依赖项:

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

8. 使用Spring Boot

我们还可以使用spring-boot-starter-data-jpa依赖项,它会自动为我们配置数据源

我们需要确保我们要使用的数据库存在于类路径中。在我们的示例中,我们添加了H2内存数据库:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
   <version>2.7.2</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

因此,仅通过添加这些依赖项,我们的应用程序就能够启动并运行了,我们可以将其用于其他数据库操作。

标准Spring应用程序的显式配置现在作为Spring Boot自动配置的一部分包含在内

当然,我们可以通过添加自定义显式配置来修改自动配置。

Spring Boot提供了一种使用application.properties文件中的属性来执行此操作的简单方法。让我们看一个更改连接URL和凭据的示例:

spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

9. Spring Data JPA的有用工具

所有主要的Java IDE都支持Spring Data JPA。让我们看看Eclipse和IntelliJ IDEA有哪些有用的工具。

如果你使用Eclipse作为你的IDE,你可以安装Dali Java Persistence Tools插件。这为JPA实体提供了ER图、用于初始化模式的DDL生成以及基本的逆向工程功能。此外,你还可以使用Eclipse Spring Tool Suite(STS)。它有助于验证Spring Data JPA Repository中的查询方法名称。

如果你使用IntelliJ IDEA,则有两种选择。

IntelliJ IDEA Ultimate(旗舰版)支持ER图、用于测试JPQL语句的JPA控制台和有价值的检查。但是这些功能在社区版中不可用。

为了提高IntelliJ的生产力,你可以安装JPA Buddy插件。它提供了许多功能,包括生成JPA实体、Spring Data JPA Repository、DTO、初始化DDL脚本、Flyway版本化迁移、Liquibase变更日志等。此外,JPA Buddy还提供逆向工程的高级工具。

最后,JPA Buddy插件同样适用于社区版和旗舰版。

10. 总结

在本文中,我们介绍了使用Spring 5、JPA 2和Spring Data JPA(Spring Data伞形项目的一部分)使用XML和基于Java的配置来配置和实现持久层。

我们讨论了定义更高级的自定义查询、事务语义以及使用新的JPA名称空间进行配置的方法。最终结果是使用Spring对数据访问进行了全新且优雅的处理,几乎没有实际的实现工作。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章