写点什么

Spring Data JPA 极速入门

作者:翊君
  • 2022 年 6 月 08 日
  • 本文字数:2787 字

    阅读完需:约 9 分钟

Spring Data JPA 极速入门

0.阅读完本文你将会学会

  • 如何在 Spring 项目中引入 Spring Data JPA

1. 概述

这篇文章将重点介绍如何在 Spring 项目中引入 Spring Data JPA,并全面配置持久化层。

2.Spring Data 生成的 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 中更高级的 Specification 和 Querydsl 支持。

  • 通过 JPA 命名查询定义自定义查询


第三个选项,Specification 和 Querydsl 支持,类似于 JPA 标准,但使用更灵活和方便的 API。这使得整个操作的可读性和可重用性大大增强。在处理大量的固定查询时,这种 API 的优势将变得更加明显,因为我们有可能通过数量较少的可重用代码块来更简洁地表达这些查询。


最后一种方案的缺点是,它要么涉及到 XML,要么让实体类承担查询的负担。

3.1 自动的自定义查询

当 Spring Data 创建一个新的 Repository 实现时,它分析了所有由接口定义的方法,并试图从方法名称中自动生成查询。虽然这有一些局限性,但这是一种非常强大和优雅的方式,只需少量工作就可以定义新的自定义访问方法。


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


public interface IFooDAO extends JpaRepository<Foo, Long> {
Foo findByName(String name);
}
复制代码


这是一个相对简单的例子。查询创建机制支持更多的关键词:


如果解析器不能将该属性与域对象字段相匹配,我们会看到以下异常。


java.lang.IllegalArgumentException: No property nam found for type class com.jayxu.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 异常转译仍然是 ok 的

在 Java 中,我们通常使用 try-catch 语句捕获异常,进行异常处理。但有些时候,我们使用 try-catch 捕获一个异常,但却不进行异常处理,反而是抛出另一个异常,这就称为异常转译。现在的问题是:由于 Spring Data JPA 不依赖于旧的 ORM 模板(JpaTemplate、HibernateTemplate),而且它们从 Spring 5 开始就被删除了,我们是否还能让我们的 JPA 异常被翻译成 Spring 的 DataAccessException 层次结构?


答案是,我们当然要这样做。通过在 DAO 上使用 @Repository 注解,仍然可以实现异常转译。这个注解使 Spring Bean 后理器能够用容器中发现的所有 PersistenceExceptionTranslator 实例告知所有 @Repository Bean,并像以前一样提供异常转译。


让我们用一个集成测试来验证异常转译。


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


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

5.Spring Data JPA Repository 配置

为了激活 Spring JPA repository 的支持,我们可以使用 @EnableJpaRepositories 注解并指定包含 DAO 接口的包。


@EnableJpaRepositories(basePackages = "com.jayxu.spring.data.persistence.repository") public class PersistenceConfig {     ...}
复制代码


我们可以用 XML 配置做同样的事情。


<jpa:repositories base-package="com.jayxu.spring.data.persistence.repository" />
复制代码

6.Java 或 XML 配置

我们将会在新的的文章中详细讨论如何在 Spring 中配置 JPA。Spring Data 还利用了 Spring 对 JPA @PersistenceContext 注解的支持。它利用这一点将 EntityManager 连接到负责创建实际 DAO 实现的 Spring 工厂 Bean(JpaRepositoryFactoryBean)。


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


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

7.Maven 的依赖性

除了 Maven 对 JPA 的配置外,我们还需要添加 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 依赖,它将自动为我们配置数据源。我们需要确保我们要使用的数据库存在于 classpath 中。在我们的例子中,我们已经添加了 H2 内存数据库。


<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-data-jpa</artifactId>   <version>2.6.1</version></dependency><dependency>    <groupId>com.h2database</groupId>    <artifactId>h2</artifactId>    <version>1.4.200</version></dependency>
复制代码


仅仅通过做这些依赖,我们的应用程序就开始运行了,我们可以用它来进行其他的数据库操作。标准 Spring 应用程序的配置现在包含在 Spring Boot 的自动配置中。当然,我们可以通过添加我们定制的显式配置来修改自动配置。Spring Boot 提供了一种简单的方法,可以使用 application.properties 文件中的属性来做到这一点。


spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1spring.datasource.username=saspring.datasource.password=sa
复制代码


在这个例子中,我们改变了连接的 URL 和用户名密码。

9.结语

在这篇文章中,我们使用 XML 和基于 Java 的配置,介绍了 Spring Data JPA 的持久层的配置和实现。我们讨论了如何定义更高级的自定义查询,以及事务和新 jpa 命名空间的配置。现在 Spring 可以以一种崭新的、优雅的方式进行数据访问,快试试吧。


如果你觉得还不错的话,快给我三连支持一下吧,咱们下期不见不散呐。

发布于: 刚刚阅读数: 3
用户头像

翊君

关注

周而不比 和而不同 2019.02.11 加入

喜欢阅读、摄影、写文的一枚小码农

评论

发布
暂无评论
Spring Data JPA 极速入门_spring data_翊君_InfoQ写作社区