1. 标题
在日常开发中,随着Mybatis的流行,之前开发都是使用Mybatis。在新公司使用Spring Data Jpa,
通过该篇文章记录使用的相关情况和记录,用于巩固加深。
2.Spring Data JPA
注意:
1.如果是查询直接使用@Query注解,如果是更新操作需要添加注解 @Modifying
2.如果联表查询需要获取两张表中的多个字段,可以使用map或者自定义一个Dto对象
3.分页对象参数
1.HQL语句查询
在SpringDataJPA中,HQL语句操作的对象都是实体类对象,在HQL语句中返回的对象和条件都为实体类字段
1. 单表单条件查询
示例:
@Query("select 实体类 from 实体类 where name = :name ")
findByName(@Param("name ") String name )
如果存在多个参数,根据示例添加参数即可,实体类对象可以取别名,返回对象和实体类名称必须统一
要不都为别名,要不都为实体类对象
2.单表多条件查询
示例:
@Query("select a from 实体类 a where a.name = :name and a.age = :age ")
使用HQL语句进行查询需要注意关键字的使用,如果根据多条件查询 一般都使用findBy条件And条件And条件
示例:
findByNameAndAge(@Param("name ") String name,@Param("age") String age)
使用关键词JPA会自动拼装生成查询语句,提高开发效率,具体关键词可以参考SpringDataJPA官方文档
3. 联表多条件查询
示例:
@Query(" select a from UserEntity a left join DeveloperEntity b on a.id = b.userId
where a.name = :name and b.deleted = :deleted")
findSend(@Param("name ") String name,@Param("deleted") String deleted)
**但是需要注意的是HQL语句中条件都不能为空,必须确保参数必须存在**
更新语句可以直接使用SpringDataJPA中自带的Save,delete,SaveAll等
4. Dto对象的封装
示例:
@Query(" select new Dto(a.id,a.name,b.name as debtName) from UserEntity a
left join DeveloperEntity b on a.id = b.userId
where a.name = :name and b.deleted = :deleted")
findSend(@Param("name ") String name,@Param("deleted") String deleted)
Dto对象中字段的顺序需要和返回中的字段顺序一致,并提供全参构造器进行入参
2.原生SQL语句查询
一般使用原生SQL语句都用于比较麻烦的联表多条件查询语句,因为HQL语句已经满足于一般的查询语句
比如 高级查询 有的条件为空 有的条件不为空 一般都使用原生SQL语句或者Specification多条件查询
示例:
@Query(value="select u.* from user u left join developer d on u.id = d.user_id
where a.name = :name and d,deleted = :deleted
and if(:userId is not null,a.user_id = :userId,1=1) ",
countQuery="select count(u.id) from user u left join developer d on u.id = d.user_id
where a.name = :name and d,deleted = :deleted
and if(:userId is not null,a.user_id = :userId,1=1) ",nativeQuery = true)
findSend(@Param("name ") String name,@Param("deleted") String deleted,@Param("userId") String userId)
注意
1.如果使用原生SQL用于查询分页列表,countQuery建议都加上,因为实际项目中有时候出现过
countQuery不存在报错的情况,有时候不加也可以
2.使用原生SQL查询 SQL语句中使用都必须为数据库表名和字段,返回对象也为别名(表名).*。
3. 如果使用原生SQL返回Dto对象和HQL语句中同理
3.Specification多条件查询
使用Specification作为条件 代码的可读性和可维护性比较好,但是使用比较麻烦,具体使用倾向需要根据
实际开发情况
1.使用Specification其实就是使用SpringDataJPA的findAll查询
示例:
// 分页参数 和排序条件 Sort可多条件排序
Pageable pageable = PageRequest.of(request.getPageNumber() - 1, request.getPageSize(),
new Sort(Sort.Direction.DESC, "createTime"))
findAll(
return (root, query, criteriaBuilder) -> {
List ps = new ArrayList();
QueryCaseInfoAction action = request.getData();
//添加不为空的条件
ps.add(criteriaBuilder.equal(root.get("deleted"), DeletedType.NON));
// 判断传入的条件是否为空 不为空才入参
if(StringUtils.isNotBlank(contextTenantId)){
ps.add(criteriaBuilder.equal(root.get("tenantId"), contextTenantId));
}
// 该条件用于 前端一个字段(后端数据库匹配多个条件的模糊查询)
if (StringUtils.isNotBlank(fuzzyMatching)) {
ps.add(criteriaBuilder.or
(criteriaBuilder.like(root.get("preCaseNum"), "%" + fuzzyMatching + "%"),
criteriaBuilder.like(root.get("caseNum"), "%" + fuzzyMatching + "%"),
criteriaBuilder.like(root.get("customerName"), "%" + fuzzyMatching + "%")));
}
// 实际查询
if (startTime !=null && endTime !=null) {
ps.add(criteriaBuilder.between(root.get("createTime"), startTime,endTime));
}
// 大于比较查询
if (startTime !=null && endTime ==null) {
ps.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), startTime));
}
// 小于比较查询
if (startTime ==null && endTime !=null) {
ps.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), endTime));
}
// 联表查询
if (StringUtils.isNotEmpty(state)) {
//如果状态不为空
predicateList.add(criteriaBuilder.equal(root.get("state").as(String.class), state));
}
//创建联表查询对象
Subquery subquery = query.subquery(String.class);
// 需要关联的表实体类
Root logRoot = subquery.from(ProcessLogEntity.class);
// 构建查询语句
subquery.select(logRoot.get("processId"))
//拼装条件
.where(criteriaBuilder.and(
criteriaBuilder.equal(logRoot.get("processId"), root.get("id")),
criteriaBuilder.equal(logRoot.get("auditorId"), userId)));
// 添加关联表的查询语句到SQL中
ps.add(criteriaBuilder.or(criteriaBuilder.exists(subquery),
criteriaBuilder.equal(root.get("starterId"), userId)));
Predicate[] arr = new Predicate[ps.size()];
return query.where(ps.toArray(arr)).getRestriction();
}; pageable);