Spring Data JPA 最佳实践【2/2】:存储库设计指南

Spring Data JPA(系列文章共 2 篇)
Spring Data JPA 最佳实践【1/2】:实体设计指南 Spring Data JPA 最佳实践【2/2】:存储库设计指南在本系列文章中,我将分享我对重构一个采用了大量不良实践的大型遗留代码库的看法。为了解决这些问题并开发出更好的 Spring Data JPA 存储库,我撰写了这份指南,旨在向我之前的同事们推广良好的开发实践。本指南已更新并完全重写,以利用 Spring Data JPA 的最新特性。有些例子可能看起来显而易见,但事实并非如此。这只是从你经验丰富的角度来看的。它们都是来自生产代码库的真实案例。
请记住,本系列文章讲解的是最新版本的 Spring Data JPA,因此可能会有一些我特别指出的细微差别。
1 设计 Spring Data JPA 存储库 Spring Data JPA 提供了几个带有预定义数据获取方法的存储库接口。我这里只提几个值得关注的:
Repository<T, ID> 接口是 Spring Data 接口的父接口,是一个用于发现的标记接口。它没有任何方法。使用时,你只需定义你所需的内容。CrudRepository 接口添加了基本的 CRUD 方法以加快开发速度,它的孪生接口 ListCrudRepository 功能相同,但返回 List 而不是 Iterable。PagingAndSortingRepository 仅添加了分页和排序功能,它也有一个返回 List 的孪生接口。猜猜它叫什么?等等,你说对了!JpaRepository 是我的最爱,它包含了所有返回 List 的先前接口。大多数时候,我只使用这个接口。你应该在何时使用 Repository、JpaRepository 或者介于两者之间的接口呢?我认为,如果你需要为其他开发者提供严格的 API,可以从 Repository 扩展并仅实现必要的操作,而不是授予访问全部 CRUD 操作的权限,这可能会损害你的业务逻辑。在你没有访问限制并且希望快速开发的情况下,请使用 JpaRepository。
关于 API 限制的例子:有时你可能需要处理存储在数据库中的逻辑。这涉及到大量的存储过程、逻辑中的细微差别等等。作为开发者,在处理表实体时应格外小心,因为这可能导致不可预测的行为。因此,在这种情况下,你只应设计 JPA 实体,并仅实现一个包含指定查询方法的空接口。通过这种方法,你是在向其他开发者强调,他们应该实现你所需的方法,而不是直接操作原始实体。
实际上,Spring Data JPA 存储库还有一个有趣的特点。你从 CrudRepository/JpaRepository 继承的方法默认是事务性的:读取操作使用 @Transactional(readOnly = true),写入操作使用常规的 @Transactional。
你通常不需要在接口上使用 Spring Framework 的 @Repository 注解(不要与 JPA 的接口混淆)——发现是自动的。对于可重用的基类接口,请使用 @NoRepositoryBean 注解。
扩展这些接口之一会告知 Spring Data JPA 它应该为你的接口生成一个实现。例如:
public interface CompanyRepository extends JpaRepository<Company, Long> {// 自定义方法将添加在这里}2 在存储库中使用查询使用 Spring Data JPA 存储库查询数据主要有两种方法。实际上不止两种,但我们先关注更流行的(依我看来)。
从方法名派生查询。Spring 解析方法名并生成相应的 JPQL。这加快了开发速度,并且对于简单条件来说很直观。使用 @Query 注解显式编写查询。这种方法更灵活,允许你使用 JPQL 或原生 SQL。在最新版本的 Spring Data 中,你可以使用 @NativeQuery 注解来代替传递 nativeQuery = true。对于数据修改查询(UPDATE/DELETE),需要添加 @Modifying,并确保存在事务边界——要么在存储库方法或类上使用 @Transactional 注解,要么从 @Transactional 服务中调用它。
使用两种方法的示例:
// 派生查询 List<Employee> findByDepartmentIdAndActiveTrue(Long departmentId);
// 显式 JPQL 查询 @Query("SELECT e FROM Employee e WHERE e.department.id = :deptId AND e.active = true")List<Employee> findActiveEmployees(@Param("deptId") Long departmentId);
// 原生 SQL 查询 @Modifying@Transactional@NativeQuery(value = "UPDATE employee SET active = false WHERE id = :id")void deactivateEmployee(@Param("id") Long id);在上面的例子中,前两个方法是选择查询。最后一个是更新(停用)操作,其目的与选择查询不同。
第一种方法缩短了开发查询所需的时间并且很直观。第二个例子在创建用于操作数据库的方法时提供了额外的能力,允许你使用 JPQL 和原生 SQL 编写查询。
如前所述,继承的数据修改方法默认标记为 @Transactional。对于自定义的修改查询,请使用 @Modifying 注解,并确保存在事务边界(在方法或类上,或在服务层)。
3 Spring Data JPA 投影对来自数据库的原始实体进行操作可能不切实际或不安全。在应用程序中检索完整实体并进行操作或许可以接受,但更好的做法是调整你的查询,使其仅返回必要的信息。
为了解决这个问题,你应该利用 Spring Data JPA 投影,它能够定义数据库中的数据将如何呈现。在上面描述的示例中,Spring Data JPA 投影仅返回调用者所需的选定属性。
Spring Data JPA 提供以下类型的投影:
通过接口定义的投影,也称为基于接口的投影到 DTO 对象的投影。请阅读关于 Spring Data JPA 的系列文章中关于开发 DTO 的指南。动态投影。基于接口的投影允许你创建只读投影,以便安全地呈现来自数据库的数据。这种方法通常在不需要操作创建的对象,而仅用于显示数据时使用。请注意,访问嵌套属性可能导致连接和额外的查询,因此投影并不总是比获取实体快。务必检查生成的 SQL 以确保最佳性能。
例如,一个基于接口的 Spring Data JPA 投影:
public interface EmployeeView {String getFirstName();String getLastName();BigDecimal getSalary();}
List<EmployeeView> findBySalaryGreaterThan(BigDecimal amount);基于 DTO 的投影允许将数据投影到 Java 类上,使你可以使用具体的 DTO 对象而不是接口。对于派生的查询方法,Spring 可以通过其构造函数将结果映射到 DTO,而对于 @Query JPQL,则需要使用构造函数表达式。基于类的投影需要一个单一的全参数构造函数;如果有多个构造函数,请使用 @PersistenceCreator 注解标记目标构造函数。
public class EmployeeDto {private final String firstName;private final String lastName;private final BigDecimal salary;public String getFirstName() { return firstName; }public String getLastName() { return lastName; }public BigDecimal getSalary() { return salary; }
}
@Query("SELECT new com.example.EmployeeDto(e.firstName, e.lastName, e.salary) FROM Employee e WHERE e.salary > :amount")List<EmployeeDto> findHighEarningEmployees(@Param("amount") BigDecimal amount);你可以将动态投影与存储库一起使用,以公开一个通用方法,允许调用者在运行时选择投影类型。Class 参数用于选择投影类型。如果你需要将 Class 传递到查询本身中,请使用不同的参数,以免它被用作投影选择器。
当将 DTO 类与动态投影一起使用时,请确保查询提供了构造函数参数(例如,通过 JPQL 构造函数表达式);否则,调用将在运行时失败。
<T> List<T> findBySalaryGreaterThan(BigDecimal amount, Class<T> type);
// 用法:
repo.findBySalaryGreaterThan(new BigDecimal("1000"), EmployeeView.class); // 接口投影
repo.findBySalaryGreaterThan(new BigDecimal("1000"), EmployeeDto.class); // DTO 类投影(需要查询支持)4 有效使用存储库方法如前所述,存储库 CRUD 方法默认在事务中运行(读取操作为 readOnly = true,写入操作为常规事务)。关于事务的另一点是避免在调用点手动开启事务。
当对多个实体执行操作时,优先使用批量方法,如 saveAll(),而不是在循环中调用 save()。将操作分组到单个查询中可以减少数据库的往返次数。
优先使用面向批量的写入,但请注意 saveAll() 本身并不会发出单个 SQL 语句。为了实际减少往返次数,需要启用 JDBC 批处理(例如,设置 spring.jpa.properties.hibernate.jdbc.batch_size=50,并且通常设置 hibernate.order_inserts=true/hibernate.order_updates=true)。如果需要插入批处理,请避免使用 GenerationType.IDENTITY,对于非常大的批次,请定期调用 flush()/clear()。
只要可能,将逻辑合并到单个查询中,而不是在 Java 中执行多个查询。在某些情况下,使用 SQL 将部分算法卸载到数据库更高效。
对于大型结果集,使用分页。Page<T> 返回内容加总数,并触发计数查询(对于自定义的 @Query,需要提供 countQuery),Slice<T> 返回内容以及是否有下一个分片(不进行计数查询),而带有 Pageable 参数的 List<T> 应用 limit/offset 但不提供元数据。
H5.mqnnegf.cn/AuT/05495.shtml
H5.mqnnegf.cn/AuT/71447.shtml
H5.mqnnegf.cn/AuT/60699.shtml
H5.mqnnegf.cn/AuT/50927.shtml
H5.mqnnegf.cn/AuT/46329.shtml
H5.mqnnegf.cn/AuT/70582.shtml
H5.mqnnegf.cn/AuT/46007.shtml
H5.mqnnegf.cn/AuT/14269.shtml
H5.mqnnegf.cn/AuT/03357.shtml
H5.mqnnegf.cn/AuT/97798.shtml
H5.mqnnegf.cn/AuT/26855.shtml
H5.mqnnegf.cn/AuT/36609.shtml
H5.mqnnegf.cn/AuT/87679.shtml
H5.mqnnegf.cn/AuT/24261.shtml
H5.mqnnegf.cn/AuT/36690.shtml
H5.mqnnegf.cn/AuT/53582.shtml
H5.mqnnegf.cn/AuT/06722.shtml
H5.mqnnegf.cn/AuT/57337.shtml
H5.mqnnegf.cn/AuT/70594.shtml
H5.mqnnegf.cn/AuT/53797.shtml
H5.mqnnegf.cn/AuT/02771.shtml
H5.mqnnegf.cn/AuT/21263.shtml
H5.mqnnegf.cn/AuT/42866.shtml
H5.mqnnegf.cn/AuT/75960.shtml
H5.mqnnegf.cn/AuT/27402.shtml
H5.mqnnegf.cn/AuT/22264.shtml
H5.mqnnegf.cn/AuT/16014.shtml
H5.mqnnegf.cn/AuT/64464.shtml
H5.mqnnegf.cn/AuT/64341.shtml
H5.mqnnegf.cn/AuT/63605.shtml
H5.mqnnegf.cn/AuT/85100.shtml
H5.mqnnegf.cn/AuT/97968.shtml
H5.mqnnegf.cn/AuT/80645.shtml
H5.mqnnegf.cn/AuT/06072.shtml
H5.mqnnegf.cn/AuT/91734.shtml
H5.mqnnegf.cn/AuT/33493.shtml
H5.mqnnegf.cn/AuT/24801.shtml
H5.mqnnegf.cn/AuT/43898.shtml
H5.mqnnegf.cn/AuT/75905.shtml
H5.mqnnegf.cn/AuT/62002.shtml
H5.mqnnegf.cn/AuT/08916.shtml
H5.mqnnegf.cn/AuT/39164.shtml
H5.mqnnegf.cn/AuT/67559.shtml
H5.mqnnegf.cn/AuT/36961.shtml
H5.mqnnegf.cn/AuT/86901.shtml
H5.mqnnegf.cn/AuT/26862.shtml
H5.mqnnegf.cn/AuT/45534.shtml
H5.mqnnegf.cn/AuT/84140.shtml
H5.mqnnegf.cn/AuT/89633.shtml
H5.mqnnegf.cn/AuT/06460.shtml
H5.mqnnegf.cn/AuT/83020.shtml
H5.mqnnegf.cn/AuT/02482.shtml
H5.mqnnegf.cn/AuT/17580.shtml
H5.mqnnegf.cn/AuT/44998.shtml
H5.mqnnegf.cn/AuT/13887.shtml
H5.mqnnegf.cn/AuT/66745.shtml
H5.mqnnegf.cn/AuT/99261.shtml
H5.mqnnegf.cn/AuT/26971.shtml
H5.mqnnegf.cn/AuT/30855.shtml
H5.mqnnegf.cn/AuT/18323.shtml
H5.mqnnegf.cn/AuT/72796.shtml
H5.mqnnegf.cn/AuT/32479.shtml
H5.mqnnegf.cn/AuT/64536.shtml
H5.mqnnegf.cn/AuT/08199.shtml
H5.mqnnegf.cn/AuT/85829.shtml
H5.mqnnegf.cn/AuT/82044.shtml
H5.mqnnegf.cn/AuT/76636.shtml
H5.mqnnegf.cn/AuT/84728.shtml
H5.mqnnegf.cn/AuT/15619.shtml
H5.mqnnegf.cn/AuT/18394.shtml
H5.mqnnegf.cn/AuT/71733.shtml
H5.mqnnegf.cn/AuT/11667.shtml
H5.mqnnegf.cn/AuT/39194.shtml
H5.mqnnegf.cn/AuT/62022.shtml
H5.mqnnegf.cn/AuT/23012.shtml
H5.mqnnegf.cn/AuT/26758.shtml
H5.mqnnegf.cn/AuT/18992.shtml
H5.mqnnegf.cn/AuT/15621.shtml
H5.mqnnegf.cn/AuT/35516.shtml
H5.mqnnegf.cn/AuT/32150.shtml
H5.mqnnegf.cn/AuT/90020.shtml
H5.mqnnegf.cn/AuT/45771.shtml
H5.mqnnegf.cn/AuT/19408.shtml
H5.mqnnegf.cn/AuT/58765.shtml
H5.mqnnegf.cn/AuT/78959.shtml
H5.mqnnegf.cn/AuT/37175.shtml
H5.mqnnegf.cn/AuT/61224.shtml
H5.mqnnegf.cn/AuT/28728.shtml
H5.mqnnegf.cn/AuT/40164.shtml
H5.mqnnegf.cn/AuT/34445.shtml
H5.mqnnegf.cn/AuT/54061.shtml
H5.mqnnegf.cn/AuT/32801.shtml
H5.mqnnegf.cn/AuT/65120.shtml
H5.mqnnegf.cn/AuT/67291.shtml
H5.mqnnegf.cn/AuT/42905.shtml
H5.mqnnegf.cn/AuT/02030.shtml
H5.mqnnegf.cn/AuT/16559.shtml
H5.mqnnegf.cn/AuT/46673.shtml
H5.mqnnegf.cn/AuT/47545.shtml
H5.mqnnegf.cn/AuT/64623.shtml
H5.mqnnegf.cn/AuT/27042.shtml
H5.mqnnegf.cn/AuT/33746.shtml
H5.mqnnegf.cn/AuT/87415.shtml
H5.mqnnegf.cn/AuT/54170.shtml
H5.mqnnegf.cn/AuT/82157.shtml
H5.mqnnegf.cn/AuT/77700.shtml
H5.mqnnegf.cn/AuT/19624.shtml
H5.mqnnegf.cn/AuT/59434.shtml
H5.mqnnegf.cn/AuT/84318.shtml
H5.mqnnegf.cn/AuT/68416.shtml
H5.mqnnegf.cn/AuT/21995.shtml
H5.mqnnegf.cn/AuT/57599.shtml
H5.mqnnegf.cn/AuT/47503.shtml
H5.mqnnegf.cn/AuT/28861.shtml
H5.mqnnegf.cn/AuT/30619.shtml
H5.mqnnegf.cn/AuT/42272.shtml
H5.mqnnegf.cn/AuT/31199.shtml
H5.mqnnegf.cn/AuT/93463.shtml
H5.mqnnegf.cn/AuT/12483.shtml
H5.mqnnegf.cn/AuT/09780.shtml
H5.mqnnegf.cn/AuT/76194.shtml
H5.mqnnegf.cn/AuT/21460.shtml
H5.mqnnegf.cn/AuT/07279.shtml
H5.mqnnegf.cn/AuT/27341.shtml
H5.mqnnegf.cn/AuT/56597.shtml
H5.mqnnegf.cn/AuT/86682.shtml
H5.mqnnegf.cn/AuT/00047.shtml
H5.mqnnegf.cn/AuT/94225.shtml
H5.mqnnegf.cn/AuT/54842.shtml
H5.mqnnegf.cn/AuT/17390.shtml
H5.mqnnegf.cn/AuT/32951.shtml
H5.mqnnegf.cn/AuT/10388.shtml
H5.mqnnegf.cn/AuT/40424.shtml
H5.mqnnegf.cn/AuT/35476.shtml
H5.mqnnegf.cn/AuT/65770.shtml
H5.mqnnegf.cn/AuT/46524.shtml
H5.mqnnegf.cn/AuT/29800.shtml
H5.mqnnegf.cn/AuT/60606.shtml
H5.mqnnegf.cn/AuT/51348.shtml
H5.mqnnegf.cn/AuT/48926.shtml
H5.mqnnegf.cn/AuT/09494.shtml
H5.mqnnegf.cn/AuT/62415.shtml
H5.mqnnegf.cn/AuT/12627.shtml
H5.mqnnegf.cn/AuT/76729.shtml
H5.mqnnegf.cn/AuT/02054.shtml
H5.mqnnegf.cn/AuT/77358.shtml
H5.mqnnegf.cn/AuT/72807.shtml
H5.mqnnegf.cn/AuT/88634.shtml
H5.mqnnegf.cn/AuT/98634.shtml
H5.mqnnegf.cn/AuT/04543.shtml
H5.mqnnegf.cn/AuT/64793.shtml
H5.mqnnegf.cn/AuT/06230.shtml
H5.mqnnegf.cn/AuT/74422.shtml
H5.mqnnegf.cn/AuT/52051.shtml
H5.mqnnegf.cn/AuT/83083.shtml
H5.mqnnegf.cn/AuT/76294.shtml
H5.mqnnegf.cn/AuT/97961.shtml
H5.mqnnegf.cn/AuT/51727.shtml
H5.mqnnegf.cn/AuT/80031.shtml
H5.mqnnegf.cn/AuT/06440.shtml
H5.mqnnegf.cn/AuT/19317.shtml
H5.mqnnegf.cn/AuT/38510.shtml
H5.mqnnegf.cn/AuT/65414.shtml
H5.mqnnegf.cn/AuT/25572.shtml
H5.mqnnegf.cn/AuT/51746.shtml
H5.mqnnegf.cn/AuT/04225.shtml
H5.mqnnegf.cn/AuT/96700.shtml
H5.mqnnegf.cn/AuT/92692.shtml
H5.mqnnegf.cn/AuT/01528.shtml
H5.mqnnegf.cn/AuT/55364.shtml
H5.mqnnegf.cn/AuT/98921.shtml
H5.mqnnegf.cn/AuT/80795.shtml
H5.mqnnegf.cn/AuT/48891.shtml
H5.mqnnegf.cn/AuT/41385.shtml
H5.mqnnegf.cn/AuT/56747.shtml
H5.mqnnegf.cn/AuT/76919.shtml
H5.mqnnegf.cn/AuT/80073.shtml
H5.mqnnegf.cn/AuT/47396.shtml
H5.mqnnegf.cn/AuT/17092.shtml
H5.mqnnegf.cn/AuT/69543.shtml
H5.mqnnegf.cn/AuT/46383.shtml
H5.mqnnegf.cn/AuT/70570.shtml
H5.mqnnegf.cn/AuT/24028.shtml
H5.mqnnegf.cn/AuT/71704.shtml
H5.mqnnegf.cn/AuT/20725.shtml
H5.mqnnegf.cn/AuT/59441.shtml
H5.mqnnegf.cn/AuT/79536.shtml
H5.mqnnegf.cn/AuT/50640.shtml
H5.mqnnegf.cn/AuT/21120.shtml
H5.mqnnegf.cn/AuT/73425.shtml
H5.mqnnegf.cn/AuT/18425.shtml
H5.mqnnegf.cn/AuT/23146.shtml
H5.mqnnegf.cn/AuT/35002.shtml
H5.mqnnegf.cn/AuT/72344.shtml
H5.mqnnegf.cn/AuT/84245.shtml
H5.mqnnegf.cn/AuT/16546.shtml
H5.mqnnegf.cn/AuT/13531.shtml
H5.mqnnegf.cn/AuT/53765.shtml
H5.mqnnegf.cn/AuT/70130.shtml
H5.mqnnegf.cn/AuT/02548.shtml
https://H5.mqnnegf.cn/AuT/05495.shtml
https://H5.mqnnegf.cn/AuT/71447.shtml
https://H5.mqnnegf.cn/AuT/60699.shtml
https://H5.mqnnegf.cn/AuT/50927.shtml
https://H5.mqnnegf.cn/AuT/46329.shtml
https://H5.mqnnegf.cn/AuT/70582.shtml
https://H5.mqnnegf.cn/AuT/46007.shtml
https://H5.mqnnegf.cn/AuT/14269.shtml
https://H5.mqnnegf.cn/AuT/03357.shtml
https://H5.mqnnegf.cn/AuT/97798.shtml
https://H5.mqnnegf.cn/AuT/26855.shtml
https://H5.mqnnegf.cn/AuT/36609.shtml
https://H5.mqnnegf.cn/AuT/87679.shtml
https://H5.mqnnegf.cn/AuT/24261.shtml
https://H5.mqnnegf.cn/AuT/36690.shtml
https://H5.mqnnegf.cn/AuT/53582.shtml
https://H5.mqnnegf.cn/AuT/06722.shtml
https://H5.mqnnegf.cn/AuT/57337.shtml
https://H5.mqnnegf.cn/AuT/70594.shtml
https://H5.mqnnegf.cn/AuT/53797.shtml
https://H5.mqnnegf.cn/AuT/02771.shtml
https://H5.mqnnegf.cn/AuT/21263.shtml
https://H5.mqnnegf.cn/AuT/42866.shtml
https://H5.mqnnegf.cn/AuT/75960.shtml
https://H5.mqnnegf.cn/AuT/27402.shtml
https://H5.mqnnegf.cn/AuT/22264.shtml
https://H5.mqnnegf.cn/AuT/16014.shtml
https://H5.mqnnegf.cn/AuT/64464.shtml
https://H5.mqnnegf.cn/AuT/64341.shtml
https://H5.mqnnegf.cn/AuT/63605.shtml
https://H5.mqnnegf.cn/AuT/85100.shtml
https://H5.mqnnegf.cn/AuT/97968.shtml
https://H5.mqnnegf.cn/AuT/80645.shtml
https://H5.mqnnegf.cn/AuT/06072.shtml
https://H5.mqnnegf.cn/AuT/91734.shtml
https://H5.mqnnegf.cn/AuT/33493.shtml
https://H5.mqnnegf.cn/AuT/24801.shtml
https://H5.mqnnegf.cn/AuT/43898.shtml
https://H5.mqnnegf.cn/AuT/75905.shtml
https://H5.mqnnegf.cn/AuT/62002.shtml
https://H5.mqnnegf.cn/AuT/08916.shtml
https://H5.mqnnegf.cn/AuT/39164.shtml
https://H5.mqnnegf.cn/AuT/67559.shtml
https://H5.mqnnegf.cn/AuT/36961.shtml
https://H5.mqnnegf.cn/AuT/86901.shtml
https://H5.mqnnegf.cn/AuT/26862.shtml
https://H5.mqnnegf.cn/AuT/45534.shtml
https://H5.mqnnegf.cn/AuT/84140.shtml
https://H5.mqnnegf.cn/AuT/89633.shtml
https://H5.mqnnegf.cn/AuT/06460.shtml
https://H5.mqnnegf.cn/AuT/83020.shtml
https://H5.mqnnegf.cn/AuT/02482.shtml
https://H5.mqnnegf.cn/AuT/17580.shtml
https://H5.mqnnegf.cn/AuT/44998.shtml
https://H5.mqnnegf.cn/AuT/13887.shtml
https://H5.mqnnegf.cn/AuT/66745.shtml
https://H5.mqnnegf.cn/AuT/99261.shtml
https://H5.mqnnegf.cn/AuT/26971.shtml
https://H5.mqnnegf.cn/AuT/30855.shtml
https://H5.mqnnegf.cn/AuT/18323.shtml
https://H5.mqnnegf.cn/AuT/72796.shtml
https://H5.mqnnegf.cn/AuT/32479.shtml
https://H5.mqnnegf.cn/AuT/64536.shtml
https://H5.mqnnegf.cn/AuT/08199.shtml
https://H5.mqnnegf.cn/AuT/85829.shtml
https://H5.mqnnegf.cn/AuT/82044.shtml
https://H5.mqnnegf.cn/AuT/76636.shtml
https://H5.mqnnegf.cn/AuT/84728.shtml
https://H5.mqnnegf.cn/AuT/15619.shtml
https://H5.mqnnegf.cn/AuT/18394.shtml
https://H5.mqnnegf.cn/AuT/71733.shtml
https://H5.mqnnegf.cn/AuT/11667.shtml
https://H5.mqnnegf.cn/AuT/39194.shtml
https://H5.mqnnegf.cn/AuT/62022.shtml
https://H5.mqnnegf.cn/AuT/23012.shtml
https://H5.mqnnegf.cn/AuT/26758.shtml
https://H5.mqnnegf.cn/AuT/18992.shtml
https://H5.mqnnegf.cn/AuT/15621.shtml
https://H5.mqnnegf.cn/AuT/35516.shtml
https://H5.mqnnegf.cn/AuT/32150.shtml
https://H5.mqnnegf.cn/AuT/90020.shtml
https://H5.mqnnegf.cn/AuT/45771.shtml
https://H5.mqnnegf.cn/AuT/19408.shtml
https://H5.mqnnegf.cn/AuT/58765.shtml
https://H5.mqnnegf.cn/AuT/78959.shtml
https://H5.mqnnegf.cn/AuT/37175.shtml
https://H5.mqnnegf.cn/AuT/61224.shtml
https://H5.mqnnegf.cn/AuT/28728.shtml
https://H5.mqnnegf.cn/AuT/40164.shtml
https://H5.mqnnegf.cn/AuT/34445.shtml
https://H5.mqnnegf.cn/AuT/54061.shtml
https://H5.mqnnegf.cn/AuT/32801.shtml
https://H5.mqnnegf.cn/AuT/65120.shtml
https://H5.mqnnegf.cn/AuT/67291.shtml
https://H5.mqnnegf.cn/AuT/42905.shtml
https://H5.mqnnegf.cn/AuT/02030.shtml
https://H5.mqnnegf.cn/AuT/16559.shtml
https://H5.mqnnegf.cn/AuT/46673.shtml
https://H5.mqnnegf.cn/AuT/47545.shtml
https://H5.mqnnegf.cn/AuT/64623.shtml
https://H5.mqnnegf.cn/AuT/27042.shtml
https://H5.mqnnegf.cn/AuT/33746.shtml
https://H5.mqnnegf.cn/AuT/87415.shtml
https://H5.mqnnegf.cn/AuT/54170.shtml
https://H5.mqnnegf.cn/AuT/82157.shtml
https://H5.mqnnegf.cn/AuT/77700.shtml
https://H5.mqnnegf.cn/AuT/19624.shtml
https://H5.mqnnegf.cn/AuT/59434.shtml
https://H5.mqnnegf.cn/AuT/84318.shtml
https://H5.mqnnegf.cn/AuT/68416.shtml
https://H5.mqnnegf.cn/AuT/21995.shtml
https://H5.mqnnegf.cn/AuT/57599.shtml
https://H5.mqnnegf.cn/AuT/47503.shtml
https://H5.mqnnegf.cn/AuT/28861.shtml
https://H5.mqnnegf.cn/AuT/30619.shtml
https://H5.mqnnegf.cn/AuT/42272.shtml
https://H5.mqnnegf.cn/AuT/31199.shtml
https://H5.mqnnegf.cn/AuT/93463.shtml
https://H5.mqnnegf.cn/AuT/12483.shtml
https://H5.mqnnegf.cn/AuT/09780.shtml
https://H5.mqnnegf.cn/AuT/76194.shtml
https://H5.mqnnegf.cn/AuT/21460.shtml
https://H5.mqnnegf.cn/AuT/07279.shtml
https://H5.mqnnegf.cn/AuT/27341.shtml
https://H5.mqnnegf.cn/AuT/56597.shtml
https://H5.mqnnegf.cn/AuT/86682.shtml
https://H5.mqnnegf.cn/AuT/00047.shtml
https://H5.mqnnegf.cn/AuT/94225.shtml
https://H5.mqnnegf.cn/AuT/54842.shtml
https://H5.mqnnegf.cn/AuT/17390.shtml
https://H5.mqnnegf.cn/AuT/32951.shtml
https://H5.mqnnegf.cn/AuT/10388.shtml
https://H5.mqnnegf.cn/AuT/40424.shtml
https://H5.mqnnegf.cn/AuT/35476.shtml
https://H5.mqnnegf.cn/AuT/65770.shtml
https://H5.mqnnegf.cn/AuT/46524.shtml
https://H5.mqnnegf.cn/AuT/29800.shtml
https://H5.mqnnegf.cn/AuT/60606.shtml
https://H5.mqnnegf.cn/AuT/51348.shtml
https://H5.mqnnegf.cn/AuT/48926.shtml
https://H5.mqnnegf.cn/AuT/09494.shtml
https://H5.mqnnegf.cn/AuT/62415.shtml
https://H5.mqnnegf.cn/AuT/12627.shtml
https://H5.mqnnegf.cn/AuT/76729.shtml
https://H5.mqnnegf.cn/AuT/02054.shtml
https://H5.mqnnegf.cn/AuT/77358.shtml
https://H5.mqnnegf.cn/AuT/72807.shtml
https://H5.mqnnegf.cn/AuT/88634.shtml
https://H5.mqnnegf.cn/AuT/98634.shtml
https://H5.mqnnegf.cn/AuT/04543.shtml
https://H5.mqnnegf.cn/AuT/64793.shtml
https://H5.mqnnegf.cn/AuT/06230.shtml
https://H5.mqnnegf.cn/AuT/74422.shtml
https://H5.mqnnegf.cn/AuT/52051.shtml
https://H5.mqnnegf.cn/AuT/83083.shtml
https://H5.mqnnegf.cn/AuT/76294.shtml
https://H5.mqnnegf.cn/AuT/97961.shtml
https://H5.mqnnegf.cn/AuT/51727.shtml
https://H5.mqnnegf.cn/AuT/80031.shtml
https://H5.mqnnegf.cn/AuT/06440.shtml
https://H5.mqnnegf.cn/AuT/19317.shtml
https://H5.mqnnegf.cn/AuT/38510.shtml
https://H5.mqnnegf.cn/AuT/65414.shtml
https://H5.mqnnegf.cn/AuT/25572.shtml
https://H5.mqnnegf.cn/AuT/51746.shtml
https://H5.mqnnegf.cn/AuT/04225.shtml
https://H5.mqnnegf.cn/AuT/96700.shtml
https://H5.mqnnegf.cn/AuT/92692.shtml
https://H5.mqnnegf.cn/AuT/01528.shtml
https://H5.mqnnegf.cn/AuT/55364.shtml
https://H5.mqnnegf.cn/AuT/98921.shtml
https://H5.mqnnegf.cn/AuT/80795.shtml
https://H5.mqnnegf.cn/AuT/48891.shtml
https://H5.mqnnegf.cn/AuT/41385.shtml
https://H5.mqnnegf.cn/AuT/56747.shtml
https://H5.mqnnegf.cn/AuT/76919.shtml
https://H5.mqnnegf.cn/AuT/80073.shtml
https://H5.mqnnegf.cn/AuT/47396.shtml
https://H5.mqnnegf.cn/AuT/17092.shtml
https://H5.mqnnegf.cn/AuT/69543.shtml
https://H5.mqnnegf.cn/AuT/46383.shtml
https://H5.mqnnegf.cn/AuT/70570.shtml
https://H5.mqnnegf.cn/AuT/24028.shtml
https://H5.mqnnegf.cn/AuT/71704.shtml
https://H5.mqnnegf.cn/AuT/20725.shtml
https://H5.mqnnegf.cn/AuT/59441.shtml
https://H5.mqnnegf.cn/AuT/79536.shtml
https://H5.mqnnegf.cn/AuT/50640.shtml
https://H5.mqnnegf.cn/AuT/21120.shtml
https://H5.mqnnegf.cn/AuT/73425.shtml
https://H5.mqnnegf.cn/AuT/18425.shtml
https://H5.mqnnegf.cn/AuT/23146.shtml
https://H5.mqnnegf.cn/AuT/35002.shtml
https://H5.mqnnegf.cn/AuT/72344.shtml
https://H5.mqnnegf.cn/AuT/84245.shtml
https://H5.mqnnegf.cn/AuT/16546.shtml
https://H5.mqnnegf.cn/AuT/13531.shtml
https://H5.mqnnegf.cn/AuT/53765.shtml
https://H5.mqnnegf.cn/AuT/70130.shtml
https://H5.mqnnegf.cn/AuT/02548.shtml
// 1) 带有 Page 和排序的派生查询 interface UserRepository extends JpaRepository<User, Long> {Page<User> findByActive(boolean active, Pageable pageable);}
// 用法:Pageable pageable = PageRequest.of(0, 20, Sort.by("createdAt").descending());Page<User> page = userRepository.findByActive(true, pageable);List<User> users = page.getContent();long total = page.getTotalElements();boolean last = page.isLast();
// 2) 使用 Slice 进行无限滚动(无计数查询)interface UserRepository extends JpaRepository<User, Long> {Slice<User> findByActive(boolean active, Pageable pageable);}5 存储库中的存储过程在开发面向数据库的应用程序时,你可以使用 Spring Data JPA 调用数据库中定义的存储过程。有多种方法可以实现。
第一种方法是使用 @NamedStoredProcedureQuery:
在实体上使用 @NamedStoredProcedureQuery 声明它,指定:
name – JPA 使用的标识符,procedureName – 数据库中存储过程的实际名称,parameters – @StoredProcedureParameter 对象数组,定义每个参数的模式(IN/OUT)、名称和 Java 类型。在存储库中添加一个方法,并使用 @Procedure 注解,引用声明的名称。对于多个输出参数,当调用由 @NamedStoredProcedureQuery 支持时,Spring Data JPA 可以返回一个 Map<String,Object>。对于单个输出,可以直接返回该值。@Procedure 上还有一个 outputParameterName 属性用于定位特定的输出参数。







评论