Spring Data -Specification用法和常用查询方法(in,join,equal等)

  • 前言
  • 入门例子
  • Repository层常用写法
  • Specification 的用法
  • 总结

前言

在这一年里技术更新,从使用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接口有个大概的认识。

@Overridepublic 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>() {@Overridepublic 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).<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);}//equaleif (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 + "%")));}//inif (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();

总结

基本将常用的都包含完了,以后遇到了新的写法再更新上去。

Spring Data -Specification用法和常用查询方法(in,join,equal等)相关推荐

  1. Spring Data Jpa的JpaRepository的getOne()方法查询数据实体时报错could not initialize proxy

    问题描述:在使用Spring Data Jpa的JpaRepository的getOne()方法查询数据实体时报以下错误: org.hibernate.LazyInitializationExcept ...

  2. java easyui条件组合查询_EasyUi+Spring Data 实现按条件分页查询

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

  3. Spring Data JPA 多表关联查询的实现

    Spring Data JPA 多表关联查询的实现 多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询 ...

  4. Mysql数据库常用查询方法及演示(where条件查询、分页、排序等)

    Mysql数据库常用查询方法及演示 where条件查询的介绍 使用where条件查询可以对表中的数据进行筛选,条件成立的记录会出现在结果集中. where语句支持的运算符: 比较运算符 逻辑运算符 模 ...

  5. ORM框架之Spring Data JPA(三)高级查询---复杂查询

    一.spring data jpa高级查询 1.1Specifications动态查询 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data ...

  6. Spring Data Solr教程:动态查询

    Solr通常被称为搜索服务器,我们可以在实现全文搜索功能时使用它. 但是,当我们实现从搜索表单获取其输入的搜索功能时,利用Solr的性能通常是明智的. 在这种情况下,执行的搜索查询取决于收到的输入. ...

  7. jpa常用查询方法使用总结自定义sql查询

    文章目录 一.JPA自定义查询方法 实体类 1.1 单条件查询一条数据 1.2 单条件查询多条数据 1.3 多条件查询数据 1.4 查询某一个字段 1.5 in查询 1.6 like查询 二.自定义s ...

  8. Pymongo常用查询方法总结

    Python 直接连接mongodb数据库进行查询操作 1.安装所需模块 使用到的是pymongo模块,安装方法:pip install pymongo 2.环境验证 3.连接数据库 import p ...

  9. Spring Data JPA_多表关联查询中应该注意的问题

    今天在写Spring Data JPA的时候发现这样一个问题 问题如下: Caused by: org.hibernate.DuplicateMappingException: Table [sys_ ...

  10. 多线程2(常用的方法:join、interrupt、currentThread、isAlive、setDaemon...)

    常用的方法: 1.join()方法: join()方法:执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再由阻塞状态转为就绪状态. 示例: package venus;import java. ...

最新文章

  1. “35岁才是一个程序员成熟的开始!”
  2. ElementUI中的el-table中实现动态添加一行、删除一行、清空所有行
  3. GC的作用域,方法区和堆
  4. 用c语言编程减法计算,求用C编个大数加减法运算程序
  5. CORS跨域限制以及预请求验证(C++ Qt框架实现)
  6. spark-dataframe与rdd的区别
  7. 山东省计算机考试无法报名,12月20日开始报名!山东2020年3月全国计算机等级考试注意事项来咯...
  8. CAD安装失败Failed Installation aborted, Result=1603
  9. 绑定流详解——网络测试仪实操
  10. 腾讯推出微信公众平台企业服务平台风铃
  11. java 翻译英文_JAVA 一些常用的英文及翻译
  12. 如何获取QQ邮箱授权码
  13. 交换机工作原理和配置命令
  14. 鸿蒙申请银行卡格式错误,办建设银行卡问题
  15. jQuery中的Sizzle引擎分析
  16. mini《猜字》游戏,谁玩谁迷糊
  17. C++ 11 多线程之future
  18. 汽车OBD初级开发入门
  19. AI大模型加持,生成式搜索来了!
  20. 7-10 公路村村通 (最小生成树Prim算法) | PTA数据结构与算法——C语言实现

热门文章

  1. 计算机配置显示器,ControlMyMonitor(电脑显示器配置工具)
  2. C/C++ 如何判断闰年,对判断闰年条件的疑惑解答
  3. 论文总结:云安全研究方向及进展综述
  4. XP需要计算机管理权限,xp无法无法使用管理员权限运行软件的解决步骤
  5. 李白:下终南山过斛斯山人宿置酒
  6. git报错 warning: Clone succeeded, but checkout failed.
  7. HTML网页图片背景以及图片自适应设置
  8. 服务器raid0系统坏了,服务器磁盘阵列raid1、raid0、raid5故障时的数据恢复思路和方法...
  9. vue子组件的使用和事件传递
  10. Linux的LILO引导程序,LILO引导程序