1.Spring Data
Spring Data是Spring Framework的一个子项目,它提供了一种简化数据访问层的方式。Spring Data支持多种数据存储技术,包括关系型数据库、NoSQL数据库、搜索引擎等。
通过使用Spring Data,开发人员可以更轻松地进行数据访问,同时还能够利用Spring Framework的其他功能,如依赖注入、面向切面编程等。
Spring Data提供了一组通用的API和实现,可以帮助开发人员快速、简便地访问各种类型的数据存储。
2. Spring Data JPA
Spring Data JPA是Spring Data项目中的一个模块,它提供了对JPA(Java Persistence API)的支持。JPA是Java平台上的一种ORM(对象关系映射)规范,它定义了一组API和注解,用于简化Java对象与关系型数据库之间的映射操作。
Spring Data JPA通过提供一组简化的API和自动化的实现,使得开发人员可以更轻松地进行数据库访问和操作。它减少了编写重复、繁琐的数据访问代码的工作量,同时还提供了一些方便的特性,如查询方法的自动生成、分页和排序的支持等。
使用Spring Data JPA,开发人员只需定义好实体类和接口,通过继承一些预定义的接口,就可以实现常见的数据访问操作,而无需编写具体的SQL语句。这样可以大大简化开发过程,提高开发效率
2.1Spring Data JPA整合springboot
1.首先需要导入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.配置yml文件
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://localhost:3306/jpa?serverTimezone=Asia/Shanghai
username: root
password: root
jpa:
hibernate:
ddl-auto: update #自动创建表
show-sql: true #显示SQL语句
3. 创建实体类
package com.qf.jpa.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
@Entity //标识实体
//为注解标识的实体指定对应的数据表
@Table(name = "student")
@Data
public class Student implements Serializable {
@Id //ID列标识
@GeneratedValue(strategy = GenerationType.IDENTITY)//主键生成策略
@Column(name = "id", length = 20, nullable = false)//列定义
private Long id;
@Column(name = "name", length = 50, nullable = false)
private String name;
@Column(name = "sex", length = 1, nullable = false)
private int sex;
@Column(name = "phone", length = 11, nullable = false)
private String phone;
}
4. 创建DAO
package com.qf.jpa.dao;
import com.qf.jpa.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
public interface StudentRepository extends JpaRepository<Student, String> {
}
5. 测试
package com.qf.jpa;
import com.qf.jpa.dao.StudentRepository;
import com.qf.jpa.entity.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class JpaApplicationTests {
@Autowired
private StudentRepository studentRepository;
@Test
void jpaTest() {
Student stu = new Student();
stu.setName("张华");
stu.setSex(1);
stu.setPhone("1388888888");
studentRepository.save(stu);
System.out.println(stu.getId());
}
}
3.spring data jpa 核心接口
1.Repository接口
Repository
接口是Spring Data的一个核心接口,它是一个标记接口,用于表示一个数据访问仓库。在Spring Data中,每个数据源(如关系型数据库、NoSQL数据库等)都有对应的 Repository
接口
接口中的方法主要有:
1. 继承的方法:
- save(entity)
:保存实体对象。
- findById(id)
:根据ID查找实体对象。
- findAll()
:获取所有实体对象。
- delete(entity)
:删除实体对象。
2. 分页和排序方法(继承自 PagingAndSortingRepository
):
- findAll(Pageable pageable)
:分页查询所有实体对象。
- findAll(Sort sort)
:按照指定排序规则查询所有实体对象。
3. 动态查询方法(继承自 JpaSpecificationExecutor
):
- findAll(Specification<T> spec)
:根据动态查询条件查询所有实体对象。
4. 自定义查询方法: - 根据方法名自动生成查询语句,如 findByXXX()
、 countByXXX()
等。 - 使用 @Query
注解定义自定义的JPQL或SQL查询语句。
该接口主要提供了方法名称命名查询方式,同时也提供了基于@Query注解查询与更新
package com.qf.jpa.dao;
import com.qf.jpa.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface StudentRepository extends JpaRepository<Student, String> {
//方法名称必须要遵循驼峰式命名规则,findBy(关键字)+属性名称(首字母大写)+查询条件(首字母大写)
List<Student> findByNameLike(String name);
List<Student> findByNameLikeOrPhoneEquals(String name, String phone);
@Query("FROM Student WHERE name LIKE :name") //HQL=Hibernate Query Language
List<Student> getStudents(String name);
@Query(value="SELECT * FROM student WHERE name LIKE ?",nativeQuery=true)
List<Student> searchStudents(String name);
}
2. CrudRepository接口
CrudRepository
接口是Spring Data的一个核心接口之一,用于定义基本的CRUD(创建、读取、更新、删除)操作方法。它提供了一组通用的方法,用于简化数据访问层的开发。
CrudRepository
接口中定义了以下常用的方法:
- save(entity)
:保存实体对象。
- findById(id)
:根据ID查找实体对象。
- findAll()
:获取所有实体对象。
- delete(entity)
:删除实体对象。
此外, CrudRepository
还提供了一些其他的方法,
如: - count()
:获取实体对象的总数
。 - existsById(id)
:检查指定ID的实体对象是否存在。
- deleteById(id)
:根据ID删除实体对象。
通过继承 CrudRepository
接口,开发人员可以快速定义自己的数据访问接口,并且可以利用Spring Data提供的自动化实现来执行基本的CRUD操作,无需编写冗余的数据访问代码
@Test
public void testCrudRepositorySave() {
Student stu = new Student();
stu.setName("张华");
stu.setSex(1);
stu.setPhone("1388888888");
studentRepository.save(stu);
}
@Test
public void testCrudRepositoryUpdate() {
Student stu = new Student();
stu.setId(1);
stu.setName("张华");
stu.setSex(2);
stu.setPhone("13899999999");
this.studentRepository.save(users);
}
@Test
public void testCrudRepositoryFindOne() {
Student stu=this.studentRepository.findOne(1);
System.out.println(stu);
}
@Test
public void testCrudRepositoryFindAll() {
List<Student> list= (List<Student>) this.studentRepository.findAll();
for (Student stu:list){
System.out.println(stu);
}
}
@Test
public void testCrudRepositoryDeleteById() {
this.studentRepository.delete(4);
}
3.PagingAndSortingRepository接口
`PagingAndSortingRepository` 接口是Spring Data的一个核心接口之一,它继承自 `CrudRepository` 接口,提供了分页和排序的支持。
`PagingAndSortingRepository` 接口中定义了以下常用的方法:
- `findAll(Sort sort)` :按照指定排序规则查询所有实体对象。
- `findAll(Pageable pageable)` :分页查询所有实体对象。
在使用 `findAll(Pageable pageable)` 方法时,需要传入一个 `Pageable` 对象来指定分页参数,如页码、每页条数和排序规则等。 `Pageable` 对象可以通过 `PageRequest.of()` 方法来创建。
通过继承 `PagingAndSortingRepository` 接口,开发人员可以在数据访问接口中定义支持分页和排序的方法,Spring Data会自动处理分页和排序的逻辑,简化了数据访问层的开发工作。
@Test
public void testPagingAndSortingRepositorySort() {
//Order 定义了排序规则
Sort.Order order=new Sort.Order(Sort.Direction.DESC,"id");
//Sort对象封装了排序规则
Sort sort=new Sort(order);
List<Student> list= (List<Student>) this.studentRepository.findAll(sort);
for (Student stu:list){
System.out.println(stu);
}
}
@Test
public void testPagingAndSortingRepositoryPaging() {
//Pageable:封装了分页的参数,当前页,煤业显示的条数。注意:它的当前页是从0开始
//PageRequest(page,size):page表示当前页,size表示每页显示多少条
Pageable pageable=new PageRequest(1,2);
Page<Student> page=this.studentRepository.findAll(pageable);
System.out.println("数据的总条数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
List<Student> list=page.getContent();
for (Student stu:list){
System.out.println(stu);
}
}
@Test
public void testPagingAndSortingRepositorySortAndPaging() {
Sort sort=new Sort(new Sort.Order(Sort.Direction.DESC,"id"));
Pageable pageable=new PageRequest(0,2,sort);
Page<Student> page=this.studentRepository.findAll(pageable);
System.out.println("数据的总条数:"+page.getTotalElements());
System.out.println("总页数:"+page.getTotalPages());
List<Student> list=page.getContent();
for (Student stu:list){
System.out.println(stu);
}
}
4. JpaRepository 接口
`JpaRepository` 接口是Spring Data JPA中的一个核心接口,它继承自 `PagingAndSortingRepository` 接口,提供了一组基本的CRUD(创建、读取、更新、删除)操作方法,并且支持分页和排序。
除了继承自 `PagingAndSortingRepository` 的方法外, `JpaRepository` 接口还提供了一些其他常用的方法,如:
- `flush()` :将挂起的持久化操作立即刷新到数据库。
- `saveAndFlush(entity)` :保存实体对象,并立即刷新到数据库。
- `deleteInBatch(entities)` :批量删除实体对象。
此外, `JpaRepository` 还提供了一些查询方法的默认实现,如:
- `findAll()` :获取所有实体对象。
- `findById(id)` :根据ID查找实体对象。
- `existsById(id)` :检查指定ID的实体对象是否存在。
- `count()` :获取实体对象的总数。
通过继承 `JpaRepository` 接口,开发人员可以在数据访问接口中定义自己的方法,并利用Spring Data提供的自动化实现来执行常见的CRUD操作和查询操作,简化了数据访问层的开发工作。
5. JpaSpecificationExecutor 接口
`JpaSpecificationExecutor` 接口是Spring Data JPA中的一个核心接口,用于支持动态查询。它提供了一种在运行时动态构建查询条件的方式,可以根据不同的查询条件生成动态的查询语句。
`JpaSpecificationExecutor` 接口中定义了以下常用的方法:
- `findAll(Specification<T> spec)` :根据动态查询条件查询所有符合条件的实体对象。
- `findOne(Specification<T> spec)` :根据动态查询条件查询符合条件的单个实体对象。
在使用这些方法时,需要传入一个 `Specification<T>` 对象,用于描述查询条件。 `Specification<T>` 接口中定义了一些方法,如 `toPredicate()` ,用于构建查询条件。
通过继承 `JpaSpecificationExecutor` 接口,开发人员可以在数据访问接口中定义支持动态查询的方法,根据实际的查询需求,动态构建查询条件,从而实现灵活的查询功能。Spring Data JPA会根据传入的 `Specification<T>` 对象,自动生成相应的查询语句。
5.1单条件查询
public Page<User> test(){
Sort sort = new Sort(Sort.Direction.DESC,"id");
int page = 1;
int pageSize = 5;
Pageable pageable = PageRequest.of(page,pageSize,sort);
//通常使用 Specification 的匿名内部类
Specification<User> specification = new Specification<User>() {
/**
* @param root: 代表查询的实体类.
* @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
* 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
* @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象
* @return: *Predicate 类型, 代表一个查询条件.
*/
@Override
public Predicate toPredicate(Root<Student> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
Path id = root.get("id");
Predicate predicateId = cb.gt(id,5);
return predicateId ;
}
};
Page<Student> userPage = userRepository.findAll(specification, pageable);
return userPage;
}
5.2多条件查询
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<Student> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
Path id = root.get("id");
Predicate predicateId = cb.gt(id,5);
Path<Student> email = root.get("phone");
Predicate predicateEmail = cb.equal(email, "13899999999");
Predicate endPredicate = cb.and(predicateId, predicateEmail);
return endPredicate;
}
};
4.注意事项
使用Spring Data JPA时,以下是一些注意事项:
1. 实体类的注解:确保实体类上使用了 `@Entity` 注解,以标识它是一个持久化实体。
2. 主键的注解:在实体类的主键字段上使用适当的注解,如 `@Id` 和 `@GeneratedValue` ,以定义主键的生成策略。
3. 关联关系的注解:使用适当的注解(如 `@OneToOne` 、 `@OneToMany` 、 `@ManyToOne` 、 `@ManyToMany` 等)来定义实体类之间的关联关系。
4. 自定义查询方法:可以通过在数据访问接口中定义方法,并使用 `@Query` 注解来编写自定义的JPQL或SQL查询语句。
5. 命名查询:可以使用 `@NamedQuery` 注解在实体类中定义命名查询,然后通过方法名调用。
6. 事务管理:使用 `@Transactional` 注解来标识需要进行事务管理的方法或类。
7. 分页和排序:可以使用 `Pageable` 对象来进行分页和排序操作,通过传递 `Pageable` 对象作为方法参数,实现分页查询。
8. 数据库方言:根据使用的数据库,配置适当的数据库方言,以确保生成的SQL语句与数据库兼容。
9. 错误处理:在数据访问过程中,处理可能出现的异常,如 `DataAccessException` 等,以保证数据访问的稳定性。
10. 监控和日志:使用适当的监控和日志工具,如Spring Boot Actuator和日志框架,以便进行性能监控和故障排查。
总之,合理使用Spring Data JPA的注解和功能,遵循最佳实践,可以简化数据访问层的开发,并提高代码的可读性和可维护性。