使用Spring Data JPA 本机查询

Spring Data JPA支持从数据库中检索数据的各种方法。有些非常易于使用,例如派生查询。其他方法提供了极大的灵活性,使您能够以各种方式读取和转换数据,例如自定义查询。本机查询是第二类的极端。它们是读取数据最灵活、最强大的选项。

正如我在上一篇关于JPA 中本机查询的文章中所解释的那样,它们使您可以访问数据库支持的所有功能。这使得它们非常适合需要复杂查询来提取所需信息的所有用例。当然,如果您将本机查询与 Spring Data JPA 一起使用,情况也是如此,因为您在内部使用相同的机制。Spring Data JPA 只是使本机查询的定义和执行变得更容易一些。

内容[隐藏]

定义本机查询

使用纯 JPA 或休眠时,定义和执行本机查询需要多个步骤。Spring Data 的@Query注释删除了所有样板代码。我们已经在上一篇文章中使用了该注释来定义自定义 JPQL 查询

定义本机查询时,使用 @Query 注释存储库方法,将其nativeQuery属性设置为true,并提供 SQL 语句作为。如以下代码片段所示,您可以像在自定义 JPQL 查询中一样使用绑定参数。

1

2

3

4

5

6

7

8

@Repository

public interface AuthorRepository extends CrudRepository<Author, Long>, PagingAndSortingRepository<Author, Long> {

    @Query(value="select * from author a where a.first_name= :firstName", nativeQuery=true)

    List<Author> getAuthorsByFirstName(String firstName);

}

完成此操作后,只需将存储库注入到其中一个服务中,并使用要搜索的firstName调用getAuthorsByFirstName方法。

1

List<Author> authors = authorRepository.getAuthorsByFirstName("Janssen");

然后,Spring Data 的存储库实现提供所需的代码来实例化对注释中提供的语句的查询@Query。然后,它将提供的值设置为该查询的绑定参数并执行它。

将操作写入为本机查询

正如我在 Hibernate 性能调优在线培训中详细解释的那样,批量操作通常是更改或删除大量数据库记录的更好选择。您可以使用 JPQL、条件本机查询来实现这些操作。

您可以使用@Query注释来定义此类 JPQL 或本机 SQL 语句。由于写入操作的执行方式与读取操作不同,因此还需要使用@Modifying注释来批注存储库方法。这是与前面讨论的本机 SQL SELECT 语句的唯一区别。

1

2

3

4

5

6

7

8

9

10

11

12

13

@Repository

public interface AuthorRepository extends CrudRepository<Author, Long>, PagingAndSortingRepository<Author, Long> {

    @Modifying

    @Query(value="delete from author a where a.last_name= :lastName", nativeQuery = true)

    void deleteAuthorByLastName(@Param("lastName") String lastName);

     

    @Modifying

    @Query(value="update author set last_name= :lastName where first_name = :firstName", nativeQuery=true)

    void updateAuthorByFirstName(String firstName, String lastName);

     

    ...

}

使用 Spring 数据 JPA 进行本机查询的限制

使用本机查询时,需要注意 2 个限制:

  1. Spring Data JPA 和持久性提供程序不会将查询调整为数据库的特定 SQL 方言。因此,您需要确保应用程序支持的所有 RDBMS 都可以处理提供的语句。
  2. 本机查询结果的分页需要一个额外的步骤。
  3. Spring Data JPA 不支持本机 SQL 语句的动态排序。

让我们仔细看看第 2 个和第 3 个限制。

添加计数查询以启用分页

使用自定义 JPQL 查询时,可以将可分页类型的参数添加到存储库方法。这将为查询结果启用分页。然后,Spring Data JPA 添加所有必需的样板代码,一次检索一页的查询结果。

对本机查询执行相同操作需要额外的步骤。您需要提供一个计数查询,该查询返回非分页结果中包含的记录总数。一种方法是提供查询字符串作为@Query注释的countQuery属性的值。

1

2

3

4

5

6

7

8

9

10

@Repository

public interface AuthorRepository extends CrudRepository<Author, Long>, PagingAndSortingRepository<Author, Long> {

     

    @Query(value="select * from author a where a.last_name= ?1",

            countQuery = "select count(id) from author a where a.last_name= ?1",

            nativeQuery = true)

    Page<Author> getAuthorsByLastName(String lastname, Pageable page);

     

    ...

}

如果存储库方法引用命名本机查询,则需要将计数查询作为第二个命名查询提供,并在其名称中添加后缀 sendix.count

1

2

3

4

5

6

7

@NamedNativeQuery(name = "Author.getAuthorsByLastName",

                    query = "select * from author a where a.last_name= ?1",

                    resultClass = Author.class)

@NamedNativeQuery(name = "Author.getAuthorsByLastName.count",

                    query = "select count(id) from author a where a.last_name= ?1")

@Entity

public class Author { ... }

无动态排序

使用 JPQL 查询时,可以将类型为 Sort的参数添加到存储库方法中。这使您能够在运行时定义排序条件。然后,Spring Data JPA 根据提供的参数值生成所需的 ORDER BY 子句。

不幸的是,Spring Data JPA 不支持本机查询的此功能。这样做需要 Spring Data 分析提供的语句,并以特定于数据库的方言生成 ORDER BY 子句。这将是一个非常复杂的操作,目前不受Spring Data JPA的支持。

当然,您可以将自己的 ORDER BY 子句添加到查询中。但这限制了每个查询只能进行一个特定的排序。如果需要支持多个存储库,使用复合存储库通常是更好的方法。然后,您可以使用 JPA 的条件 API 实现自己的查询方法,并根据提供的输入参数指定 ORDER BY 子句。

结论

本机查询是实现读取操作的最强大、最灵活的方法。它们使您能够使用数据库支持的所有功能,并且 Spring Data JPA 处理几乎所有必需的样板代码。

但是使用它们比派生查询需要付出更多的努力,并且与自定义 JPQL 查询相比,它们提供了一些限制。最值得注意的是:

  1. 若要对查询结果使用分页,需要提供计数查询。您可以通过设置 @Query注释的countQuery属性来执行此操作。
  2. Spring Data JPA 不支持本机查询的动态排序。如果要按特定顺序检索查询结果,则需要在查询中包含 ORDER BY 子句。
  3. Spring Data JPA 和持久性提供程序不会将本机查询语句调整为数据库的 SQL 方言。因此,您需要确保所有受支持的 DBMS 都支持您的 SQL 语句。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值