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层常用写法

  1. 按着类字段查询 按着类关系关联查询不需要写语句的查询就不在详细讲解,给个例子看看就行
//查询第一个
EngineerVersionControl findTopByProjectIdAndOldOrderByVersionDesc(String projectId, int old);
//查询存在
boolean existsByProjectId(String projectId);
//排序
List<EngineerVersionControl> findByProjectIdOrderByVersionDesc(String projectId);
  1. @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).&lt;String&gt;get("id"), "%" + taskFast + "%");
finalConditions = criteriaBuilder.and(finalConditions, taskFastPre);
}
//between用法
if ((null != createBegin) &amp;&amp; (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 &amp;&amp; 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() &gt; 0) {
CriteriaBuilder.In&lt;Object&gt; 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等)的更多相关文章

  1. Spring Data Jpa (四)注解式查询方法

    详细讲解声明式的查询方法 1 @Query详解 使用命名查询为实体声明查询是一种有效的方法,对于少量查询很有效.一般只需要关心@Query里面的value和nativeQuery的值.使用声明式JPQ ...

  2. EasyUi+Spring Data 实现按条件分页查询

    Spring data 介绍 Spring data 出现目的 为了简化.统一 持久层 各种实现技术 API ,所以 spring data 提供一套标准 API 和 不同持久层整合技术实现 . 自己 ...

  3. Spring Data JPA中的动态查询 时间日期

    功能:Spring Data JPA中的动态查询 实现日期查询 页面对应的dto类private String modifiedDate; //实体类 @LastModifiedDate protec ...

  4. Spring Data Jpa (二)JPA基础查询

    介绍Spring Data Common里面的公用基本方法 (1)Spring Data Common的Repository Repository位于Spring Data Common的lib里面, ...

  5. Elasticsearch java api 常用查询方法QueryBuilder构造举例

    转载:http://m.blog.csdn.net/u012546526/article/details/74184769 Elasticsearch java api 常用查询方法QueryBuil ...

  6. spring data jpa使用原生sql查询

    spring data jpa使用原生sql查询 @Repository public interface AjDao extends JpaRepository<Aj,String> { ...

  7. Spring data jpa 实现简单动态查询的通用Specification方法

    本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字 ...

  8. Spring MVC和Spring Data JPA之按条件查询和分页(kkpaper分页组件)

    推荐视频:尚硅谷Spring Data JPA视频教程,一学就会,百度一下就有, 后台代码:在DAO层继承Spring Data JPA的PagingAndSortingRepository接口实现的 ...

  9. Spring Data Jpa的四种查询方式

    一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...

随机推荐

  1. (转)jQuery中append(),prepend()与after(),before()的区别

    在jQuery中,添加元素有append(),prepend和 after(),before()两种共四个. 根据字面意思我们可以看出他们分别是追加,添加和之前,之后,意思相近.同时他们又都有添加元素 ...

  2. utf8mb4 使用注意

    数据库的表的定义如果是utf8mb4的富文本时,关联的字段必须指定为非utf8,否则 跟其他的表关联的时候,会非常慢,以至于索引都不能使用. 也就是必须的字段才可以使用这个 utf8mb4 ,否则检索 ...

  3. [React Native] 解析JSON文件

    在编写代码时,开发者有时需要存储一些比较多,在应用程序运行时不需要更改的数据.文件大不便于写在代码中,可以把这些数据存储到JSON文件中. 优点非常明显: 1. 数据存放在单独的文件中,代码精简有条理 ...

  4. 【JZOJ1637】【ZJOI2009】狼和羊的故事

    题目描述 "狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......" Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干 ...

  5. jupyter的简单操作

    jupyter简单使用 esc+ m 切换到标记模式 shift + enter 运行 a 向上新增代码块 b 向下新增代码块 dd 删除代码块 y python代码模式 file --- downl ...

  6. HZOJ trade

    强烈谴责$skyh$的没$\Huge 脸$行为. 很经典的可反悔贪心,然而我一直以为是sbdp还一直想着怎么优化…… 正常的贪心肯定是不对的. 但是由于A-C=A-B+B-C, 所以用一个小根堆维护, ...

  7. Revit安装失败怎样卸载重新安装Revit,解决Revit安装失败的方法总结

    技术帖:Revit没有按照正确方式卸载,导致Revit安装失败.楼主也查过网上关于如何解决Revit安装失败的一些文章,是说删除几个Revit文件和Revit软件注册表就可以解决Revit安装失败的问 ...

  8. mysql通过TEXT字段进行关联的优化方案

    mysql如果通过超长的字段进行on关联,会导致效率很低,7k关联1.4k,结果为30+W的数据量,执行时间高达50秒. 将这个字段进行md5,然后再通过md5后的值进行关联,执行效率会大大优化,同样 ...

  9. SDUT-3346_数据结构实验之二叉树七:叶子问题

    数据结构实验之二叉树七:叶子问题 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 已知一个按先序输入的字符序列,如abd ...

  10. javascript实现html中关键字查询

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...