1、服务层调用dao继承的接口中的方法
2、使用jpql语句进行查询
3、可以引入原生的sql语句
4、根据jpa规定的特殊命名方法完成查询
5、动态查询
1、服务层调用dao继承的接口中的方法dao层继承的继承JpaRepository和JpaSpecificationExecutor这两个接口,JpaRepository<操作的实体类, 主键类型> 封装了基本的curd操作,JpaSpecificationExecutor<操作的实体类类型> 封装了复杂的查询(分页、排序等)。
2、使用jpql语句进行查询可以引入jpql(JPA查询语言)语句进行查询(jpql语句类似于sql语句,只不过sql操作的是数据表和字段,jpql操作的是对象和属性,比如 from Resume where id=xxx)
详细介绍参考https://www.yiibai.com/jpa
dao层代码
public interface ResumeDao extends JpaRepository<Resume, Long>, JpaSpecificationExecutor<Resume> {
@Query("from Resume where id=?1") // 这个"1"代表的下面方法形参中引入参数的位置作为查询id
public Resume findByJpql(Long id); // 使用jpql语句根据id查询数据
}
测试
@Test
public void testJpql() {
Resume byJpql = resumeDao.findByJpql(1L);
System.out.println(byJpql);
}
3、可以引入原生的sql语句
dao层
public interface ResumeDao extends JpaRepository<Resume, Long>, JpaSpecificationExecutor<Resume> {
/**
* 使用原生sql语句查询,需要将nativeQuery属性设置为true,默认为false(jpql语句)
* @param id
* @return
*/
@Query(value = "select * from tb_resume where id=?1", nativeQuery = true)
public Resume findBySql(Long id); // 使用sql语句根据id查询数据
}
测试
@Test
public void testSql() {
Resume byJpql = resumeDao.findByJpql(2L);
System.out.println(byJpql);
}
4、根据jpa规定的特殊命名方法完成查询
可以在接口中自定义方法,而且不必引入jpql或者sql语句,这种方式叫做方法命名规则,也就是说定义的接口方法名是按照一定规则形成的,那么框架就能根据我们的方法名推断出我们的意图
dao层
public interface ResumeDao extends JpaRepository<Resume, Long>, JpaSpecificationExecutor<Resume> {
/**
* 方法名命名规则
* 按照name模糊查询(like)
* 方法名以findBy开头
* -属性名(首字母大写)
* -查询方式(模糊查询、等价查询,如果不写查询方式,默认等价查询
* 多个字段查询时时用And或Or进行连接,后面也跟属性名和其查询方式
*/
public List<Resume> findByNameLike(String name);
public List<Resume> findByNameLikeAndAddress(String name, String address);
}
测试
@Test
public void testMethodName() {
List<Resume> list = resumeDao.findByNameLike("张%");
System.out.println(list);
}
@Test
public void testMethodName2() {
List<Resume> list = resumeDao.findByNameLikeAndAddress("张%", "北京");
System.out.println(list);
}
5、动态查询
service层传入Dao层的条件不确定,把service拿到的条件封装成一个对象传递给Dao层,这个对象就叫做Specification(对条件的一个封装)
Specification接口中的方法
* <p>
* Optional<T> findOne(@Nullable Specification<T> var1); // 根据条件查询单个对象
* <p>
* List<T> findAll(@Nullable Specification<T> var1); // 根据条件查询所有
* <p>
* Page<T> findAll(@Nullable Specification<T> var1, Pageable var2); // 根据条件进行查询,并且进行分页
* <p>
* List<T> findAll(@Nullable Specification<T> var1, Sort var2); // 根据条件进行查询,并进行排序
* <p>
* long count(@Nullable Specification<T> var1); // 根据条件统计
* <p>
* interface Specification<T>
* Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3); // 用来封装查询条件
* Root:根属性(查询所需要的任何属性都可以从根对象中获取)
* CriteriaQuery:自定义查询方式,用不上
* CriteriaBuilder:查询构造器,封装了很多的查询条件(like 和等值查询等)
动态查询单个对象
@Test
public void testSpecification() {
/**
* 动态条件封装
* 匿名内部类
* toPredicate:动态组装查询条件
* 借助于两个参数完成条件的封装
* Root:获取需要查询对象的属性
* CriteriaBuilder:构建查询条件,内部封装了很多查询条件(模糊查询、精准查询)
* 需求根据name("张三")查询简历 select * from tb_resume where name="张三"
*/
Specification<Resume> specification = new Specification<Resume>() {
@Override
public Predicate toPredicate(Root<Resume> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
// 获取到name属性
Path<Object> name = root.get("name");
// 使用CriteriaBuilder针对name属性构建条件(精准查询)
Predicate predicate = criteriaBuilder.equal(name, "张三");
return predicate;
}
};
Optional<Resume> optional = resumeDao.findOne(specification);
Resume resume = optional.get();
System.out.println(resume);
}
动态查询多个
@Test
public void testSpecificationMultiCon() {
/**
* 需求:根据name(指定为"张三"),address以"北"开头(模糊匹配),查询简历
*/
Specification<Resume> specification = new Specification<Resume>() {
@Override
public Predicate toPredicate(Root<Resume> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
// 获取到name属性
Path<Object> name = root.get("name");
Path<Object> address = root.get("address");
// 条件1:使用CriteriaBuilder针对name属性构建条件(精准查询)
Predicate predicate1 = criteriaBuilder.equal(name, "张三");
// 条件2:address以"北"开头(模糊匹配)
Predicate predicate2 = criteriaBuilder.like(address.as(String.class), "北%"); // as作用将其转换为Expression,并且指定参数类型
// 组合两个条件
Predicate predicate = criteriaBuilder.and(predicate1, predicate2);
return predicate;
}
};
Optional<Resume> optional = resumeDao.findOne(specification);
Resume resume = optional.get();
System.out.println(resume);
}
排序
@Test
public void testSort() {
Sort sort = new Sort(Sort.Direction.DESC, "id"); // 根据id进行倒序
List<Resume> list = resumeDao.findAll(sort);
for (int i = 0; i < list.size(); i++) {
Resume resume = list.get(i);
System.out.println(resume);
}
}
分页
@Test
public void testPage() {
/**
* 第一个参数:当前查询的页数
* 第二个参数:每页查询的数量
*/
Pageable pageable = PageRequest.of(0, 2);
Page<Resume> all = resumeDao.findAll(pageable);
System.out.println(all);
}
到此这篇关于SpringDataJPA详解增删改查操作方法的文章就介绍到这了,更多相关SpringDataJPA增删改查内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!