jpa多表联查动态_Spring Data JPA 连表动态条件查询
多表查询在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 连表动态条件查询相关推荐
- jpa多表联查动态_Spring Data JPA实现动态多表关联查询
在面向关系型数据库(例如:MySQL)的查询中,动态的.多表关联的查询属于比较复杂的情况.所以,我们只要掌握了这种复杂的查询,当面对其他查询情况时,就能做到胸有成竹. 在java工程中,目前我所了解到 ...
- spring data jpa从入门到精通_Spring Data JPA的简单入门
前言 spring data JPA是spring团队打造的sping生态全家桶的一部分,本身内核使用的是hibernate核心源码,用来作为了解java持久层框架基本构成的样本是再好不过的选择.最近 ...
- java多表查询返回数据_spring data jpa如何在多张数据库表中查询返回某些字段值?...
对于多表联查需要使用springdata jpa的@Query标注实现,例如最代码的我的私信列表的查询:public static final String POSTREPOSITORY_FINDAL ...
- 在每个运行中运行多个查询_Spring Data JPA的运行原理及几种查询方式
Spring Data JPA的运行原理: @PersistenceContext(name="entityManagerFactory") private EntityManag ...
- java增删改查实例源码_Spring Data JPA 实现简单的CRUD增删改查源码案例
Spring专题 Spring Data JPA 实现简单的CRUD增删改查源码案例 Spring Data JPA旨在简化JPA基础知识库构建和减少需要与数据库进行通信的代码量.第一部分是如何配置H ...
- Spring Data JPA使用必备(二):Spring Data JPA方法命名规则实现SQL自动生成
Spring data JPA是一个好东西,但是对于很多习惯于写SQL,直接怼数据库的人来说,这个真的用不习惯,还被一致认为是一个不易于程序员发展的技术.因为JPA提供了标准的封装,在操作数据库的时候 ...
- jpa 动态查询条件 数组_Spring data jpa 复杂动态查询方式总结
一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一. 诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...
- jpa 定义中间表实体_Spring Data JPA实体详解
1. Spring Data JPA实体概述 JPA提供了一种简单高效的方式来管理Java对象(POJO)到关系数据库的映射,此类Java对象称为JPA实体或简称实体.实体通常与底层数据库中的单个关系 ...
- querydsl动态 sql_Spring data jpa 复杂动态查询方式总结
一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一. 诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...
最新文章
- 计算机word基础知识菜单,Word试卷模板_电脑基础知识_IT/计算机_资料
- 语言 重量计算_R语言 第五章 高级绘图工具(4)
- 牛客练习赛89——牛牛小数点(未解决)
- Linux学习笔记---常用shell命令
- centos安装词典——图形界面的和命令行
- svn-the working copy is locked due to a previous
- 在Flex中获取一个屏幕截图(Screenshot)并将其传递给ASP.NET
- 移动端WEB开发,click,touch,tap事件浅析
- dqpsk的matlab,基于MATLAB的理想_4_DQPSK系统仿真.pdf
- Spring 常用的注解
- Python-常用模块有哪些
- 联想电脑如何启动BIOS并开启CPU虚拟化功能
- Nginx入门以及开源博客Tale的部署
- Collaborative Evolutionary Reinforcement Learning
- Python爬虫常用库requests、beautifulsoup、selenium、xpath总结
- HBuilder X 未检测到手机或模拟器(安卓端)
- 编译内核遇到:error: ‘ovl_v1_fs_type’ undeclared (first use in this function)错误
- python csv 大文件_python 快速把超大txt文件转存为csv的实例
- 自然语言处理NLP文本分类顶会论文阅读笔记(二)
- selenium 无头模式截屏
热门文章
- 【历史上的今天】8 月 13 日:Oracle 起诉 Google,Java 版权案正式开启!
- 用Bi-GRU语义解析,实现中文人物关系分析 | 附完整代码
- 47 张图带你 MySQL 进阶
- “手把手撕LeetCode题目,扒各种算法套路的裤子”
- 从 VMWare 到阿里神龙,虚拟化技术 40 年演进史
- 小米回应暴力裁员;报告称安卓手机贬值速度是 iPhone 两倍;Ant Design 4.0.1 发布| 极客头条...
- QQ 群文件紧急扩容;钟南山团队与阿里云联手推进新冠疫苗研发;PhpStorm 2019.3.3 发布| 极客头条...
- ​不容错过的 13 个 JavaScript 实用技巧!
- 腾讯云刘颖:与微信共建小程序开发者生态,让小程序开发更简单
- 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!