Spring Data -Specification用法和常用查询方法(in,join,equal等)
Spring Data -Specification用法和常用查询方法(in,join,equal等)
前言
在这一年里技术更新,从使用Mybatis转为Spring Data,总体感受是终于不用在自己写映射了,也可以少写方法和对应字段了。接下来总结在工作中常用的查询方式和方法,例如equal,join,in等。积少成多,在这里只收藏了用过查询与方法(如果方法可以用得更有,有更多的用法和不足之处请联系我)。
入门例子
controller层,这里是个简单查询获取所有用户并分页
@GetMapping("/list")
@ApiOperation(value = "所有用户列表")
public Result list(@RequestParam Map<String, Object> params) {
Page page = userService.queryPage(params);
return Result.ok().put("page", page);
}
接下对service层的实现,功能是实现关键字搜索,这里因为简单并没有单独将Specification提出来,主要是对Specification接口有个大概的认识。
@Override
public page queryPage(Map<String, Object> params) {
//MapUtils方法用来取除params中的方法,来自于 org.apache.commons.collections.MapUtils;
String keyword = MapUtils.getSrting(params,"keyword");
Page page = sysUserRepository.findAll(new Specification<SysUserEntity>() {
@Override
public Predicate toPredicate(Root<SysUserEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<>();
if (StringUtils.isNotBlank(keyword)) {
List<Predicate> temp = new ArrayList<>();
for (String oneKeyword : keywordCopyStr) {
temp.add(criteriaBuilder.like(root.<String>get("mobile"), "%" + oneKeyword + "%"));
temp.add(criteriaBuilder.like(root.<String>get("trueName"), "%" + oneKeyword + "%"));
}
predicates.add(criteriaBuilder.or(temp.toArray(new Predicate[temp.size()])));
}
return criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
});
return page;
}
Repository层中为了支持这样的查询,sysUserRepository需要继承JpaRepository(基本查询),JpaSpecificationExecutor(分页),这个接口是不需要再去实现的,到了Repository层就行,再对此进行扩充(比Mybatis简单多了)。
public interface sysUserRepository extends JpaRepository<SysCaptchaEntity, String>, JpaSpecificationExecutor<SysCaptchaEntity> {
}
Repository层常用写法
- 按着类字段查询 按着类关系关联查询不需要写语句的查询就不在详细讲解,给个例子看看就行
//查询第一个
EngineerVersionControl findTopByProjectIdAndOldOrderByVersionDesc(String projectId, int old);
//查询存在
boolean existsByProjectId(String projectId);
//排序
List<EngineerVersionControl> findByProjectIdOrderByVersionDesc(String projectId);
- @Query语句查询
一般不会做物理删除,而是逻辑删除。保存操作使用save或者saveAll方法
//更新 必有@Modifying,和使用hiberna一样,HQL语句的写法
@Transactional(rollbackFor = Exception.class)
@Modifying
@Query("update SysUserEntity u set u.isDelete = ?2 ,u.gmtModified= ?3 where u.id = ?1 ")
int deleteIsUpdate(String id, int deleted, Date date);
//查询
@Query("select u from SysUserEntity u where u.id in ?1 and u.isDelete = 0 ")
Page<SysUserEntity> findAllUser(List<String> userIds, Pageable pageable);
//多表查询
@Query(value = " select p from DictionaryEntity p , DictionaryContentEntity w " +
" Where w.ContentEntity.id = ?1 and p.id = w.DictionaryEntity.id and p.deleted = ?2 ORDER BY p.dictionary")
List<WebsiteDictionaryEntity> webOnwDictionary(String id,int isDeleted);
3.使用@Query实现写sql语句的查询
再spring data 中不仅有HQl语句,在功能太复杂的时候,可以使用sql语句进行本地查询
@Query(value="select serve.* from service_serve serve " +
"left join company_info_user cominfo on serve.company_info_user_id=cominfo.company_info_user_id" +
" left join user_company company on cominfo.company_info_user_id=company.company_info_user_id " +
" left join employee employeeen3_ on company.user_company_id=employeeen3_.user_company_id " +
" left join user userentity4_ on employeeen3_.user_id=userentity4_.user_id " +
" where userentity4_.user_id=?1 and employeeen3_.activity_management_power=1" +
" order by serve.gmt_create desc " +
"limit ?2 , ?3 " ,nativeQuery = true)
List<ServiceServeEntity> queryByCompany(String userId,int startPoint,int endPoint);
4.@Param(value = “name”)查询,这是两种写法。一种?,一种@Param()
@Query(value="select activity.* from service_activity activity " +
"left join company_info_user cominfo on activity.company_id=cominfo.company_info_user_id" +
" left join user_company company on cominfo.company_info_user_id=company.company_info_user_id " +
" left join employee employeeen3_ on company.user_company_id=employeeen3_.user_company_id " +
" left join user userentity4_ on employeeen3_.user_id=userentity4_.user_id " +
" where userentity4_.user_id=:userId and employeeen3_.service_management_power=1 and activity.status=:status" +
" order by activity.gmt_create desc " +
"limit :startPoint , :endPoint " ,nativeQuery = true)
List<ServiceActivityEntity> queryByCompanyAndStatus(@Param(value="userId")String userId,@Param(value="status")int status, @Param(value="startPoint")int startPoint, @Param(value="endPoint")int endPoint);
Specification 的用法
下面是个较为全面的例子,将一个较为复杂的查询提取成一个方法。这个方法时使用and的方式拼接,接下来的每一个查询都需要使用把finalConditions拼上,如同 finalConditions = criteriaBuilder.and(finalConditions, taskFastPre)。
public class TaskProjectSpecs {
public static Specification<Task> where(Map params, String userId, List<String> taskIds) {
//lambda表达式
return (Root<Task> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) -> {
//开始
Predicate finalConditions = criteriaBuilder.conjunction();
//提取参数
String taskFast = MapUtils.getString(params, "taskFast");
//lile 和join 用法 join可跟,JoinType.LEFT等
if (StringUtils.isNotBlank(taskFast)) {
Predicate taskFastPre = criteriaBuilder.like(root.join("taskType",JoinType.LEFT).<String>get("id"), "%" + taskFast + "%");
finalConditions = criteriaBuilder.and(finalConditions, taskFastPre);
}
//between用法
if ((null != createBegin) && (null != createEnd)) {
Predicate datePredicate = null;
if (createBegin.after(createEnd)) {
datePredicate = criteriaBuilder.between(root.get("gmtCreate"), createEnd, createBegin);
} else {
datePredicate = criteriaBuilder.between(root.get("gmtCreate"), createBegin, createEnd);
}
finalConditions = criteriaBuilder.and(finalConditions, datePredicate);
}
//equale
if (null != emergency && 0 != emergency) {
finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("emergencyLevel"), emergency));
}
//大于 不等于
if (status != null) {
finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.greaterThan(root.get("startDate"), new Date()));
finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.notEqual(root.get("status"), 1));
}
// or
if (StringUtils.isNotBlank(keyword)) {
finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.or(
criteriaBuilder.like(root.get("taskName"), "%" + keyword + "%"),
criteriaBuilder.like(root.join("project").get("name"), "%" + keyword + "%"))
);
}
//in
if (taskIds.size() > 0) {
CriteriaBuilder.In<Object> in = criteriaBuilder.in(root.get("id"));
for (String id : taskIds) {
in.value(id);
}
finalConditions = criteriaBuilder.and(finalConditions, in);
}
return query.where(finalConditions).getRestriction();
};
}
}
上面的方法是and凭借,还有一种add的方法,本质一样,都是构建query.where()查询。
public class UserSpecs {
public static Specification<SysUserEntity> where(String keyword, Date createdAtBegin, Date createdAtEnd, List<String> userIds) {
return (Root<SysUserEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (StringUtils.isNotBlank(keyword)) {
List<Predicate> temp = new ArrayList<>();
Set<String> keywordCopyStr = StringUtil.cutToArray(keyword);
for (String oneKeyword : keywordCopyStr) {
temp.add(cb.like(root.<String>get("mobile"), "%" + oneKeyword + "%"));
temp.add(cb.like(root.<String>get("trueName"), "%" + oneKeyword + "%"));
}
predicates.add(cb.or(temp.toArray(new Predicate[temp.size()])));
}
//未删除
predicates.add(cb.equal(root.get("isDelete"), Constant.NOT_DELETED));
query.where(predicates.toArray(new Predicate[predicates.size()]));
return query.getRestriction();
};
}
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
总结
基本将常用的都包含完了,以后遇到了新的写法再更新上去。
</div>
Spring Data -Specification用法和常用查询方法(in,join,equal等)的更多相关文章
- Spring Data Jpa (四)注解式查询方法
详细讲解声明式的查询方法 1 @Query详解 使用命名查询为实体声明查询是一种有效的方法,对于少量查询很有效.一般只需要关心@Query里面的value和nativeQuery的值.使用声明式JPQ ...
- EasyUi+Spring Data 实现按条件分页查询
Spring data 介绍 Spring data 出现目的 为了简化.统一 持久层 各种实现技术 API ,所以 spring data 提供一套标准 API 和 不同持久层整合技术实现 . 自己 ...
- Spring Data JPA中的动态查询 时间日期
功能:Spring Data JPA中的动态查询 实现日期查询 页面对应的dto类private String modifiedDate; //实体类 @LastModifiedDate protec ...
- Spring Data Jpa (二)JPA基础查询
介绍Spring Data Common里面的公用基本方法 (1)Spring Data Common的Repository Repository位于Spring Data Common的lib里面, ...
- Elasticsearch java api 常用查询方法QueryBuilder构造举例
转载:http://m.blog.csdn.net/u012546526/article/details/74184769 Elasticsearch java api 常用查询方法QueryBuil ...
- spring data jpa使用原生sql查询
spring data jpa使用原生sql查询 @Repository public interface AjDao extends JpaRepository<Aj,String> { ...
- Spring data jpa 实现简单动态查询的通用Specification方法
本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字 ...
- Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)
推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...
- Spring Data Jpa的四种查询方式
一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...
随机推荐
- (转)jQuery中append(),prepend()与after(),before()的区别
在jQuery中,添加元素有append(),prepend和 after(),before()两种共四个. 根据字面意思我们可以看出他们分别是追加,添加和之前,之后,意思相近.同时他们又都有添加元素 ...
- utf8mb4 使用注意
数据库的表的定义如果是utf8mb4的富文本时,关联的字段必须指定为非utf8,否则 跟其他的表关联的时候,会非常慢,以至于索引都不能使用. 也就是必须的字段才可以使用这个 utf8mb4 ,否则检索 ...
- [React Native] 解析JSON文件
在编写代码时,开发者有时需要存储一些比较多,在应用程序运行时不需要更改的数据.文件大不便于写在代码中,可以把这些数据存储到JSON文件中. 优点非常明显: 1. 数据存放在单独的文件中,代码精简有条理 ...
- 【JZOJ1637】【ZJOI2009】狼和羊的故事
题目描述 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干 ...
- jupyter的简单操作
jupyter简单使用 esc+ m 切换到标记模式 shift + enter 运行 a 向上新增代码块 b 向下新增代码块 dd 删除代码块 y python代码模式 file --- downl ...
- HZOJ trade
强烈谴责$skyh$的没$\Huge 脸$行为. 很经典的可反悔贪心,然而我一直以为是sbdp还一直想着怎么优化…… 正常的贪心肯定是不对的. 但是由于A-C=A-B+B-C, 所以用一个小根堆维护, ...
- Revit安装失败怎样卸载重新安装Revit,解决Revit安装失败的方法总结
技术帖:Revit没有按照正确方式卸载,导致Revit安装失败.楼主也查过网上关于如何解决Revit安装失败的一些文章,是说删除几个Revit文件和Revit软件注册表就可以解决Revit安装失败的问 ...
- mysql通过TEXT字段进行关联的优化方案
mysql如果通过超长的字段进行on关联,会导致效率很低,7k关联1.4k,结果为30+W的数据量,执行时间高达50秒. 将这个字段进行md5,然后再通过md5后的值进行关联,执行效率会大大优化,同样 ...
- SDUT-3346_数据结构实验之二叉树七:叶子问题
数据结构实验之二叉树七:叶子问题 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知一个按先序输入的字符序列,如abd ...
- javascript实现html中关键字查询
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...