JPA 基础(2)—— 分页操作
JPA 基础(1)—— 数据库持久化代码实战
JPA 基础(2)—— 分页操作
JPA 基础(3)—— Auditing
JPA 基础(4)—— 关联表映射
仓库PagingAndSortingRepository包装了分页和排序。
简单分页查询
直接根据班级号进行分页查询。
Page<StudentEntity> findAllByClassNo(String classNo, Pageable pageable);
自定义规范
Page<StudentEntity> findAll(Specification<StudentEntity> spec, Pageable pageable);
查询语句@Query
当进行一些复杂查询时,可以用@Query显示地声明查询语句。
@Query("select s from StudentEntity s where s.grade >= ?1 and s.classNo <> ?2 and s.no like ?3") List<StudentEntity> findAllByGrade(Integer grade, String classNo, String no);
@Query语句还有另一种写法
@Query(value = "select s from student s where s.grade >= ?1 and s.class_no <> ?2 and s.no like ?3", nativeQuery = true)
因为指定了nativeQuery = true,即使用原生的sql语句查询。使用java对象'Book'作为表名来查自然是不对的。只需将Book替换为表名book。
更新/删除
当声明更新和删除接口时,需要增加2个注解@Transactional,因为默认事务是只读的,所以update或delete操作需要覆盖事务配置。
@Transactional void deleteAllByClassNo(String classNo);
代码实战
学生实体
@Data
@Entity
@Table(name = "student")
public class StudentEntity {
@Id
private String no;
@Column(name = "class_no")
private String classNo;
private Integer grade;
}
仓库方法
package com.jpa.test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface StudentRepository extends JpaRepository<StudentEntity, String> {
StudentEntity findByNo(String no);
Page<StudentEntity> findAllByClassNo(String classNo, Pageable pageable);
// @Modifying // JPQL并不支持INSERT语句,但可以使用UPDATE和DELETE语句,要想使用UPDATE或DELETE语句则需要在@Query注解上@Modifying注解,以通知该JPQL为更新或删除操作。
// @Query(value = "select s from student s where s.grade >= ?1 and s.class_no <> ?2 and s.no like ?3", nativeQuery = true)
@Query(value = "select s from StudentEntity s where s.grade >= ?1 and s.classNo <> ?2 and s.no like ?3")
List<StudentEntity> getGoodStudent(Integer grade, String classNo, String no);
Page<StudentEntity> findAll(Specification<StudentEntity> spec, Pageable pageable);
@Transactional // 默认事务是只读的,所以update或delete需要覆盖事务配置
void deleteAllByClassNo(String classNo);
}
测试
package com.jpa.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
@ExtendWith(value = {SpringExtension.class})
@SpringBootTest
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Test
public void getInfo() {
// 构建一个学生实体
StudentEntity studentEntity = new StudentEntity();
for (int i = 1; i < 10; i++) {
studentEntity.setNo("20140801032" + String.valueOf(i));
studentEntity.setClassNo("317");
studentEntity.setGrade(60+i);
// 插入数据
studentRepository.save(studentEntity);
}
System.out.println(studentRepository.findByNo("201408010320"));
}
@Test
public void getPageClassNo() {
Page<StudentEntity> page = studentRepository.findAllByClassNo("317", PageRequest.of(0, 3));
page.getContent().forEach(System.out::println);
}
@Test
public void getPageClassNoSort() {
Sort sort = Sort.by("grade").descending(); // 以成绩降序排列
Page<StudentEntity> page = studentRepository.findAllByClassNo("317", PageRequest.of(0, 3, sort));
page.getContent().forEach(System.out::println);
}
@Test
public void getGoodStudent() {
List<StudentEntity> list = studentRepository.getGoodStudent(80, "317", "2014%"); // 注意通配符'%'不要漏写
list.forEach(System.out::println);
}
@Test
public void getAllSpecificationStudent() {
// 构造specification
// 多说一句:<?> 是范型通配符
Specification<StudentEntity> spec = (Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) -> {
// 谓词
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.greaterThan(root.get("grade"), 60));
criteriaQuery.orderBy(criteriaBuilder.desc((root.get("grade"))));
criteriaQuery.where(criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])));
return criteriaQuery.getRestriction();
};
Page<StudentEntity> page = studentRepository.findAll(spec, PageRequest.of(0, 3));
page.getContent().forEach(System.out::println);
}
}