多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现(使用较为复杂,查询不够灵活),第二种是使用原生sql查询。

JPA原生SQL连表查询

@Repository

public class SqlQueryRepository implements BaseQueryRepository {

private static final String COUNT_REPLACEMENT_TEMPLATE = "select count(%s) $5$6$7";

/**

* 匹配第三组,换成count(*),目前只用到simple

*/

private static final String SIMPLE_COUNT_VALUE = "$3*";

/**

* 复杂查询,count(主对象)

*/

private static final String COMPLEX_COUNT_VALUE = "$3$6";

private static final Pattern COUNT_MATCH;

private static final String IDENTIFIER = "[\\p{Alnum}._$]+";

private static final String IDENTIFIER_GROUP = String.format("(%s)", IDENTIFIER);

@PersistenceContext

private EntityManager entityManager;

// (select\s+((distinct )?(.+?)?)\s+)?(from\s+[\p{Alnum}._$]+(?:\s+as)?\s+)([\p{Alnum}._$]+)(.*)

static {

StringBuilder builder = new StringBuilder();

// from as starting delimiter

builder.append("(?<=from)");

// at least one space separating

builder.append("(?: )+");

// Entity name, can be qualified (any

builder.append(IDENTIFIER_GROUP);

// exclude possible "as" keyword

builder.append("(?: as)*");

// at least one space separating

builder.append("(?: )+");

// the actual alias

builder.append("(\\w*)");

builder = new StringBuilder();

builder.append("(select\\s+((distinct )?(.+?)?)\\s+)?(from\\s+");

builder.append(IDENTIFIER);

builder.append("(?:\\s+as)?\\s+)");

builder.append(IDENTIFIER_GROUP);

builder.append("(.*)");

COUNT_MATCH = compile(builder.toString(), CASE_INSENSITIVE);

}

/**

* 封装原生sql分页查询,自动生成countSql

*

* @param pageable 分页参数

* @param querySql 查询sql,不包含排序

* @param orderSql 排序sql

* @param paramMap 参数列表

* @param clazz 返回对象class

* @param 返回对象

* @return PageImpl

*/

@Override

public Page queryPageable(String querySql, String orderSql, Map paramMap, Pageable pageable, Class clazz) {

String countSql = createCountQuery(querySql);

Query countQuery = (Query)this.entityManager.createNativeQuery(countSql);

Query query = (Query)this.entityManager.createNativeQuery(querySql + orderSql);

// 设置参数

if (paramMap != null && paramMap.size() > 0) {

for (Map.Entry entry : paramMap.entrySet()) {

countQuery.setParameter(entry.getKey(), entry.getValue());

query.setParameter(entry.getKey(), entry.getValue());

}

}

BigInteger totalCount = (BigInteger) countQuery.getSingleResult();

query.setFirstResult((int) pageable.getOffset());

query.setMaxResults(pageable.getPageSize());

// 不使用hibernate转bean,存在数据类型问题

//query.setResultTransformer(Transformers.aliasToBean(clazz));

query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

List resultList = JSON.parseArray(JSON.toJSONString(query.getResultList(), SerializerFeature.WriteMapNullValue), clazz);

return new PageImpl<>(resultList, pageable, totalCount.longValue());

}

/**

* 根据查询sql自动生成countSql,正则匹配

*

* @param sql 查询sql

* @return countSql

*/

public String createCountQuery(String sql) {

Matcher matcher = COUNT_MATCH.matcher(sql);

return matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, SIMPLE_COUNT_VALUE));

}

}

使用示例

@Repository

public class UserInfoDaoImpl implements UserInfoNativeDao {

@Autowired

private BaseQueryRepository baseQueryRepository;

@Override

public Page getUserInfoPageable(String userId, QueryObj queryObj, PageRequest pageable) {

// 拼接查询sql

StringBuilder selectSql = new StringBuilder();

selectSql.append("SELECT rc.xxx xxx, rc.yyy yyy ");

selectSql.append("FROM table_a rs,table_b rc ");

selectSql.append("WHERE rs.user_id = :userId ");

HashMap paramMap = new HashMap<>(16);

paramMap.put("userId", userId);

StringBuilder whereSql = new StringBuilder();

// 企业名称模糊筛选

if (StringUtils.isNotBlank(queryObj.getCompanyName())) {

whereSql.append(" AND rs.company_name like :companyName ");

paramMap.put("companyName", "%" + queryObj.getCompanyName() + "%");

}

// 风险类型筛选 in

if (!CollectionUtils.isEmpty(queryObj.getRiskTypes())) {

whereSql.append(" AND rc.risk_type in :riskType ");

paramMap.put("riskType", queryObj.getRiskTypes());

}

// 添加排序

String orderSql = " ORDER BY xxx desc, yyy desc ";

String querySql = selectSql.append(whereSql).toString();

return baseQueryRepository.queryPageable(querySql, orderSql, paramMap, pageable, UserInfo.class);

}

}

jpa多表联查动态_Spring Data JPA 连表动态条件查询相关推荐

  1. jpa多表联查动态_Spring Data JPA实现动态多表关联查询

    在面向关系型数据库(例如:MySQL)的查询中,动态的.多表关联的查询属于比较复杂的情况.所以,我们只要掌握了这种复杂的查询,当面对其他查询情况时,就能做到胸有成竹. 在java工程中,目前我所了解到 ...

  2. spring data jpa从入门到精通_Spring Data JPA的简单入门

    前言 spring data JPA是spring团队打造的sping生态全家桶的一部分,本身内核使用的是hibernate核心源码,用来作为了解java持久层框架基本构成的样本是再好不过的选择.最近 ...

  3. java多表查询返回数据_spring data jpa如何在多张数据库表中查询返回某些字段值?...

    对于多表联查需要使用springdata jpa的@Query标注实现,例如最代码的我的私信列表的查询:public static final String POSTREPOSITORY_FINDAL ...

  4. 在每个运行中运行多个查询_Spring Data JPA的运行原理及几种查询方式

    Spring Data JPA的运行原理: @PersistenceContext(name="entityManagerFactory") private EntityManag ...

  5. java增删改查实例源码_Spring Data JPA 实现简单的CRUD增删改查源码案例

    Spring专题 Spring Data JPA 实现简单的CRUD增删改查源码案例 Spring Data JPA旨在简化JPA基础知识库构建和减少需要与数据库进行通信的代码量.第一部分是如何配置H ...

  6. Spring Data JPA使用必备(二):Spring Data JPA方法命名规则实现SQL自动生成

    Spring data JPA是一个好东西,但是对于很多习惯于写SQL,直接怼数据库的人来说,这个真的用不习惯,还被一致认为是一个不易于程序员发展的技术.因为JPA提供了标准的封装,在操作数据库的时候 ...

  7. jpa 动态查询条件 数组_Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一.  诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...

  8. jpa 定义中间表实体_Spring Data JPA实体详解

    1. Spring Data JPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系数据库的映射,此类Java对象称为JPA实体或简称实体.实体通常与底层数据库中的单个关系 ...

  9. querydsl动态 sql_Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一.  诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...

最新文章

  1. 计算机word基础知识菜单,Word试卷模板_电脑基础知识_IT/计算机_资料
  2. 语言 重量计算_R语言 第五章 高级绘图工具(4)
  3. 牛客练习赛89——牛牛小数点(未解决)
  4. Linux学习笔记---常用shell命令
  5. centos安装词典——图形界面的和命令行
  6. svn-the working copy is locked due to a previous
  7. 在Flex中获取一个屏幕截图(Screenshot)并将其传递给ASP.NET
  8. 移动端WEB开发,click,touch,tap事件浅析
  9. dqpsk的matlab,基于MATLAB的理想_4_DQPSK系统仿真.pdf
  10. Spring 常用的注解
  11. Python-常用模块有哪些
  12. 联想电脑如何启动BIOS并开启CPU虚拟化功能
  13. Nginx入门以及开源博客Tale的部署
  14. Collaborative Evolutionary Reinforcement Learning
  15. Python爬虫常用库requests、beautifulsoup、selenium、xpath总结
  16. HBuilder X 未检测到手机或模拟器(安卓端)
  17. 编译内核遇到:error: ‘ovl_v1_fs_type’ undeclared (first use in this function)错误
  18. python csv 大文件_python 快速把超大txt文件转存为csv的实例
  19. 自然语言处理NLP文本分类顶会论文阅读笔记(二)
  20. selenium 无头模式截屏

热门文章

  1. 【历史上的今天】8 月 13 日:Oracle 起诉 Google,Java 版权案正式开启!
  2. 用Bi-GRU语义解析,实现中文人物关系分析 | 附完整代码
  3. 47 张图带你 MySQL 进阶
  4. “手把手撕LeetCode题目,扒各种算法套路的裤子”
  5. 从 VMWare 到阿里神龙,虚拟化技术 40 年演进史
  6. 小米回应暴力裁员;报告称安卓手机贬值速度是 iPhone 两倍;Ant Design 4.0.1 发布| 极客头条...
  7. QQ 群文件紧急扩容;钟南山团队与阿里云联手推进新冠疫苗研发;PhpStorm 2019.3.3 发布| 极客头条...
  8. ​不容错过的 13 个 JavaScript 实用技巧!
  9. 腾讯云刘颖:与微信共建小程序开发者生态,让小程序开发更简单
  10. 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!