【Spring Boot】Java 持久层 API(二):认识 JPA 的接口

用 ORM 操作 SQL 数据库》系列,共包含以下文章:

😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!

JPA 提供了操作数据库的接口。在开发过程中继承和使用这些接口,可简化现有的持久化开发工作。可以使 Spring 找到自定义接口,并生成代理类,后续可以把自定义接口注入 Spring 容器中进行管理。在自定义接口过程中,可以不写相关的SQL操作,由代理类自动生成。

在这里插入图片描述
此前,在《分层开发 Web 应用程序》这篇博文中,已经讲述了 Repository 的概念,在此和大家一起回顾一下。

在 Spring 中有 Repository 的概念,Repository 原意指的是 仓库,即 数据仓库 的意思。Repository 居于 业务层数据层 之间,将两者隔离开来,在它的内部封装了数据查询和存储的逻辑。这样设计的好处有两个:

  • 降低层级之间的耦合:更换、升级 ORM 引擎(Hibernate)并不会影响业务逻辑。
  • 提高测试效率:如果在测试时能用 Mock 数据对象代替实际的数据库操作,运行速度会快很多。

DAO 是传统 MVC 中 Model 的关键角色,全称是 Data Access Object。DAO 直接负责数据库的存取工作,乍一看两者非常类似,但从架构设计上讲两者有着本质的区别。

Repository 蕴含着真正的 OO 概念,即一个数据仓库角色,负责所有对象的持久化管理。DAO 则没有摆脱数据的影子,仍然停留在数据操作的层面上。Repository 是相对对象而言,DAO 则是相对数据库而言,虽然可能是同一个东西 ,但侧重点完全不同。

在 Spring 和 Spring Data JPA 中,有三种 Repository 接口方便开发者直接操作数据仓库。它们之间的关系如下:
在这里插入图片描述

1.JPA 接口 JpaRepository

JpaRepository 继承自 PagingAndSortingRepository。该接口提供了 JPA 的相关实用功能, 以及通过 Example 进行查询的功能。Example 对象是 JPA 提供用来构造查询条件的对象。该接口的关键代码如下:

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {}

在上述代码中,T 表示 实体对象,ID 表示 主键。ID 必须实现序列化。

JpaRepository 提供的方法如下表所示。

方法
描述
List<T> findAll();查找所有实体
List<T> findAll(Sort var1);排序、查找所有实体
List<T> findAllById(Iterable<ID> var1);返回制定一组 ID 的实体
<S extends T> List<S> saveAll(Iterable<S> var1);保存集合
void flush();执行缓存与数据库同步
<S extends T> S saveAndFlush(S var1);强制执行持久化
void deleteInBatch(Iterable<T> var1);删除一个实体集合
void deleteAllInBatch();删除所有实体
T getOne(ID var1);返回 ID 对应的实体。如果不存在,则返回空值
<S extends T> List<S> findAll(Example<S> var1);查询满足 Example 的所有对象
<S extends T> List<S> findAll(Example<S> var1, Sort var2);查询满足 Example 的所有对象,并且进行排序返回

2.分页排序接口 PagingAndSortingRepository

PagingAndSortingRepository 继承自 CrudRepository 提供的分页和排序方法。其关键代码如下:

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { 
	Iterable<T> findAll(Sort var1);
	Page<T> findAll(Pageable var1);
}

其方法有如下两种

  • Iterable<T> findAII(Sort sort):排序功能。它按照 sort 制定的排序返回数据。
  • Page<T> findAll(Pageable pageable):分页查询(含排序功能)。

3.数据操作接口 CrudRepository

CrudRepository 接口继承自 Repository 接口,并新增了增加、删除、修改和查询方法。 CrudRepository 提供的方法见下表:

方法
说明
<S extends T> S save(S entity)保存实体。当实体中包含主键时,JPA 会进行更新操作
<S extends T> Iterable<S> saveAll(Iterable<S> entities)保存所有实体。实体必须不为空
Optional<T> findById(ID id)根据主键 id 检索实体
boolean existsById(ID id)根据主键 id 检索实体,返回是否存在。值为布尔类型
Iterable<T> findAll()返回所有实体
Iterable<T> findAllById(Iterable<ID> ids)根据给定的一组 id 值返回一组实体
long count()返回实体的数量
void deleteById(ID id)根据 id 删除数据
void delete(T entity)删除给定的实体
void deleteAll(Iterable<? extends T> entities)删除实体
void deleteAll()删除所有实体

4.分页接口 Pageable 和 Page

Pageable 接口用于构造翻页查询,返回 Page 对象。Page 从 0 0 0 开始分页。

例如,可以通过以下代码来构建文章的翻页查询参数。

@RequestMapping("/article")
public ModelAndView articleList(@RequestParam(value = "start", defaultvalue = "0") Integer start, 
								@RequestParam(value = "limit", defaultvalue = "10") Integer limit) {
  start = start < 0 ? 0 : start;  
  Sort sort = new Sort(Sort.Direction.DESC, "id");
  Pageable pageable = PageRequest.of(start, limit, sort);
  Page<Article> page = articleRepository.findAll(pageable);
  ModelAndView mav = new ModelAndView("admin/article/list");
  mav.addObject("page", page);
  return mav;
}

然后,再调用它的参数获取总页数、上一页、下一页和末页,见以下代码。

<div>
	<a th:href="@(/article(start=0)}">[首页]</a>
	<a th:if="$(not page.isFirst())" th:href="@{/article(start=${page.number-1})}">[上页]</a>
	<a th:if="$(not page.isLast())" th:href="@(/article(start=$(page.number+1})}">[下页]</a>
	<a th:href="@{/article(start=$(page.totalPages-1}))">[末页]</a>
</div>

5.排序类 Sort

Sort 类专门用来处理排序。最简单的排序就是先传入一个属性列,然后根据属性列的值进行排序。默认情况下是升序排列。它还可以根据提供的多个字段属性值进行排序。

例如以下代码是通过 Sort.Order 对象的 List 集合来创建 Sort 对象的:

List<Sort.Order> orders = new ArrayList<>();
orders.add(new Sort.Order(Sort.Direction.DESC, "id"));
orders.add(new Sort.Order(Sort.Direction.ASC, "view"))Pageable pageable = PageRequest.of(start, limit, sort);
Pageable pageable = PageRequest.of(start, limit, Sort.by(orders));

Sort 排序的方法还有下面几种:

  • 直接创建 Sort 对象,适合对单一属性做排序。
  • 通过 Sort.Order 对象创建 Sort 对象,适合对单一属性做排序。
  • 通过属性的 List 集合创建 Sort 对象,适合对多个属性采取同一种排序方式的排序。
  • 通过 Sort.Order 对象的 List 集合创建 Sort 对象,适合所有情况,比较容易设置排序方式。
  • 忽略大小写排序。
  • 使用 JpaSort.unsafe 进行排序。
  • 使用聚合函数进行排序。
Spring Boot 提供了对 JPAJava Persistence API)的自动配置和支持,使得在 Spring Boot 应用中使用 JPA 更加简单。下面是整合 JPA 的步骤: 1. 添加依赖:在 pom.xml 文件中添加 Spring BootJPA 的依赖,如下所示: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ``` 2. 配置数据源:在 application.properties 或 application.yml 文件中配置数据源信息,如下所示: ```yaml spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=password123 spring.datasource.driver-class-name=com.mysql.jdbc.Driver ``` 3. 定义实体类:定义与数据库表对应的实体类,使用 JPA 注解来映射表和字段,如下所示: ```java @Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Integer age; // 省略 getter/setter 方法 } ``` 4. 定义 Repository:定义继承自 JpaRepositoryRepository 接口,如下所示: ```java @Repository public interface UserRepository extends JpaRepository<User, Long> { List<User> findByName(String name); } ``` 5. 使用 Repository:在服务层或控制器中使用 UserRepository,如下所示: ```java @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> findUsersByName(String name) { return userRepository.findByName(name); } } ``` 通过以上步骤,即可完成 Spring BootJPA 的整合,可以通过 UserRepository 来访问数据库,并执行 CRUD 操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G皮T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值