Spring Data JPA 详解

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的注解和功能,遵循最佳实践,可以简化数据访问层的开发,并提高代码的可读性和可维护性。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值