SpringDataJPA快速入门

SpringDataJPA快速入门

前言

之前在学习 SpringBoot 框架的时候,使用到了 SpringData JPA,但是当时只是简单的查询,没有用到稍微复杂的查询。

JPA 的 JPQL 语法规则对于简单的查询实属利器,大大加快了开发速度。不久前,在公司将用户推荐功能单独抽取出为一个独立项目,由于公司一直沿用的底层框架太老,只能使用 JDK1.6,JDK 1.9都出来了,实在不能忍😅,果断引入了 SpringData JPA。

然后最近公司其他同事接手了该项目,但是不太了解 SpringData JPA 的使用,于是有了此文,不会就可以直接让他看本篇博客了哈哈。

环境准备

这里不讲解 SpringData JPA 与框架的整合,只讲解 JPA 语法的使用

Entity 实体类

@Entity // 表示为一个实体类
@Table("employee") // 表名
public class Employee {

    @Id //主键标识注解
    @GeneratedValue // 主键生成方式
    private Integer id;

    private String name;

    private Integer age;
    
    //Getter/Setter省略
}

Repository 接口

// 继承 JpaRepository 接口,第一个参数为查询的实体类,第二个为实体类的主键数据类型
public interface EmployeeRepository extends JpaRepository<Employee, Integer>{

}

插入测试数据

@Test
public void testAdd() throws Exception {
    for (int i = 0; i < 100; i++) {
        Employee employee = new Employee();
        employee.setAge(i);
        employee.setName("test" + i);
        employeeRepository.save(employee);
    }
}

JPA 查询语法讲解

使用 JPQL 进行查询

// 新增/更新
employeeRepository.save(employee);

// where name = ?1
employeeRepository.findByName("test1")

// where name = ?1 and age = ?2
employeeRepository.findByNameAndAge("test1", 20);

// where age between ?1 and ?2 【包含头尾】
List<Employee> byAgeBetween = employeeRepository.findByAgeBetween(10, 16);

// where age < ?1
List<Employee> list = employeeRepository.findByAgeLessThan(10);

// where age > ?1
List<Employee> list = employeeRepository.findByAgeGreaterThan(90);

// where name is null  【不包含为空字符串的数据】
List<Employee> list = employeeRepository.findByNameIsNull();

// where name like "test9%" 以test9为开头的name
List<Employee> list = employeeRepository.findByNameLike("test9%");
或者
List<Employee> employees = employeeRepository.findByNameStartingWith("test")

// where name like "test_" 以test开头,且后面只模糊匹配一位
List<Employee> list2 = employeeRepository.findByNameLike("test_");

// where name like "%6" 模糊匹配以6结尾的
List<Employee> employees = employeeRepository.findByNameEndingWith(6)

// where name in (?1, ?2)
List<String> names = Arrays.asList("test1", "test2");
List<Employee> employees = employeeRepository.findByNameIn(names);

// where age <> ?1
List<Employee> employees = employeeRepository.findByAgeNot(99);

// where name = ?1 order by age desc 
List<Employee> findByNameOrderByAgeDesc(String name);

使用自定义 Sql 以及 原生 Sql 查询

/** EmployeeRepository.java 添加方法 */

// 根据姓名与年龄查找,[通过占位符获取参数值]
@Query("select o from Employee o where name = ?1 and age = ?2")
List<Employee> queryEmployeeByParams(String name, Integer age);

// 根据姓名与年龄查找,[通过命名参数获取参数值],必须使用 @Param 注解
@Query("select o from Employee o where name = :name and age = :age")
List<Employee> queryEmployeeByParams2(@Param("name") String name, @Param("age") Integer age);

// 原生SQL,与上面不同的是,上面使用的是对象名称以及对象属性名称,Native SQL使用数据库表名以及字段名
@Query(nativeQuery = true, value = "select * from employee where name = :name and age = :age")
List<Employee> queryEmployeeByParams3(@Param("name") String name, @Param("age") Integer age);

JPA 更新操作

/** 需要搭配使用 @Query 与 @Modifying 和 @Transactional 注解使用*/

@Modifying
@Query("update Employee o set o.age = ?2 where o.id = ?1")
Integer updateAge(Integer id, Integer age);

在 Service 层调用

@Autowired
private EmployeeRepository employeeRepository;

@Transactional // 必须开启事务
public void update(Integer id, Integer age) {
    employeeRepository.save(id, age);
}

分页查询

// EmployeeRepository 接口定义
Page<Employee> findByNameStartingWith(String name, Pageable pageable);

// 测试类 EmployeeRepositoryTest.java
// 普通分页查询
@Test
public void testFindByNameStartingWith() {
    // 注意 page 从 0 开始
    Pageable request = new PageRequest(0, 10);
    Page<Employee> result = employeeRepository.findByNameStartingWith("test", request);
    for (Employee employee : result.getContent()) {
        System.out.println(employee);
    }
}

// 带排序条件的分页查询
@Test
public void testFindByNameStartingWith() {
    Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
    Sort sort = new Sort(order);
    Pageable request = new PageRequest(0, 10, sort);
    Page<Employee> result = employeeRepository.findByNameStartingWith("test", request);
    for (Employee employee : result.getContent()) {
        System.out.println(employee);
    }
}

动态 SQL 查询

在 Java 开发中,动态 SQL 是必不可少的,JPA 也可以实现,Repository 多继承一个接口 JpaSpecificationExecutor 即可。

// 修改之前的 EmployeeRepository, 使其多继承 JpaSpecificationExecutor 接口
public interface EmployeeRepository extends JpaRepository<Employee, Integer>, JpaSpecificationExecutor<Employee>{

    // ......
}


Pageable request = new PageRequest(0, 10);
Specification<Employee> specification = new Specification<Employee>() {
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path<Integer> path = root.get("age");
                return cb.gt(path, 50);
            }
        };
Page<Employee> all = employeeRepository.findAll(specification, request);

后记

这里感谢一下慕课网,快速入门多亏了 imooc 上的课程。

参考课程:

  • https://www.imooc.com/learn/821
posted on 2019-09-24 15:17  腾逸  阅读(300)  评论(0编辑  收藏  举报