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. shopify api php 开发,Shopify插件开发基础篇-获取店铺信息
  2. 汽车全景标定(拼接)效果的检验方法
  3. C#与java的比较
  4. 【采用】【风控体系】携程基于大数据分析的实时风控体系
  5. Java源码分析之HashMap(JDK1.8)
  6. 跳表(SkipList)设计与实现(java)
  7. 定价错误: 必要条件 MWST 丢失
  8. VTK:字形2D用法实战
  9. 【ARM】Tiny4412裸板编程之 printf函数
  10. 51单片机计算机实物焊接,基于51单片机的最小系统焊接图 浅谈单片机最小系统...
  11. 智能机器人热点技术大揭秘!
  12. hdu5927Auxiliary Set
  13. resultset 的指针报错原因
  14. 系统学习机器学习之半参数方法(一)--基于距离
  15. dash视频服务器本地搭建 (初探)
  16. 营业执照号码生成规则
  17. 合成文字识别需要的训练竖排文字数据集
  18. PyTorch 1.x 常用知识
  19. 区块链重要基础知识8-1——冷存储以及热存储和他们之间相互如何结合
  20. 函数feof使用注意事项

热门文章

  1. 企业预算管理实践:小故事大道理
  2. Python基础综合
  3. 替换WIN键和Ctrl键
  4. matlab 太阳系仿真,三维仿真太阳系
  5. 编程算法 - 最好牛线(Best Cow Line) 代码(C)
  6. 【SmartDental】小组第一次会议纪要
  7. Win10下VS2019 C++ opencv3.4.x 环境搭建过程 | 找不到opencv_world347d.dll | error LNK2019: 无法解析的外部符号
  8. FFMPEG学习【libavfilter】(二)
  9. 硬件学习之滤波电容的阻抗特性
  10. 项目经理和产品经理的职责