JPA的好搭档 - QueryDSL(jpa缺点)
ccwgpt 2024-09-21 13:43 47 浏览 0 评论
今天给大家介绍一个JPA的好搭档:QueryDSL。
0. 前言
相对于 MyBatis ,本人更喜欢 Spring Data JPA ,因为它更符合面向对象的思想,然而 JPA 对复杂的查询支持较弱,常见的有两种方式:
一种方式是Repository继承JpaSpecificationExecutor接口,优点是支持复杂查询、编译期可以规避一些语法错误,缺点是语法晦涩难懂,学习成本太高。
还有一种方式就是直接写 SQL ,可以通过JdbcTemplate或者@Query注解的方式查询,优点是简单,缺点嘛...先看段代码:
@Query(value="select bs.* from " +
"(select t.baseid,t.basesn,t.basecreatorfullname,t.basestatus,t.basesummary,'北京' faultprovince, '北京' faultcity, " +
"replace(t.INC_ResponseLevel,'响应','') inc_responselevel,t.inc_happentime,t.basecreatedate,t.inc_equipmentmanufacturer, " +
"t.inc_ne_name,t.inc_alarm_id,t.site_alerttype,t.alarmlevel,t.inc_alarm_desc,t.baseacceptouttime,t.basedealouttime, " +
"decode(t.flagPretreatment,null,'否','未预处理','否','是') flagpretreatment,decode(t.flagPretreatment,null,'否','未预处理','否','是') flagpretreatment2, " +
"decode(nvl(t.isImportantIncident, 0),1,'是','否') isimportantincident, decode(nvl(t.INC_IsEffectOP, 0),1,'是','否') inc_iseffectop, " +
"t.operationdeal, t.t0_deal,t.faultdescription,t.dealguomodo,t.inc_alarm_cleartime,t.clearinctime, " +
"t.renewtime,t.baseclosedate,nvl2(t.checkdealresult,'是','否') checkdealresult,g.jtitem1,g.jtitem2,g.jtitem3,t.reasontype " +
"from T_DEMO t, T_DEMO_MAP g " +
"where t.Sheet_type = '传输网络故障处理工单' and t.basestatus = '已归档' " +
"and t.baseCloseDate >= :beginTime and t.baseCloseDate < :endTime " +
"and (t.Withdraw_Desc = g.withdraw_desc or t.alarmname = g.alarmname) " +
"union all " +
"select t.baseid,t.basesn,t.basecreatorfullname,t.basestatus,t.basesummary,'北京' faultprovince, '北京' faultcity, " +
"replace(t.INC_ResponseLevel,'响应','') inc_responselevel,t.inc_happentime,t.basecreatedate,t.inc_equipmentmanufacturer, " +
"t.inc_ne_name,t.inc_alarm_id,t.site_alerttype,t.alarmlevel,t.inc_alarm_desc,t.baseacceptouttime,t.basedealouttime, " +
"decode(t.flagPretreatment,null,'否','未预处理','否','是') flagpretreatment,decode(t.flagPretreatment,null,'否','未预处理','否','是') flagpretreatment2, " +
"decode(nvl(t.isImportantIncident, 0),1,'是','否') isimportantincident, decode(nvl(t.INC_IsEffectOP, 0),1,'是','否') inc_iseffectop, " +
"t.operationdeal,t.t0_deal,t.faultdescription,t.dealguomodo,t.inc_alarm_cleartime,t.clearinctime, " +
"t.renewtime,t.baseclosedate,nvl2(t.checkdealresult,'是','否') checkdealresult,w.jtitem1,w.jtitem2,w.jtitem3,t.reasontype " +
"from WF_BMCC_EOMS_ITDealFault t, (select distinct c.value,c.jtitem1,c.jtitem2,c.jtitem3 from WF_Config_EL_00_NetType c) w " +
"where (t.Sheet_type = 'test0' or t.Sheet_type = 'test1' or t.Sheet_type = 'test2' " +
"or t.Sheet_type = 'test3' or t.Sheet_type = 'test4') and t.basestatus = '已归档' " +
"and t.baseCloseDate >= :beginTime and t.baseCloseDate < :endTime " +
"and t.faultclass = w.value "+
" ) bs " +
"where not exists (select dp.processbaseid from T_DEAL dp,T_GROUPS dg where dp.ProcessBaseSchema = " +
"'DEALFAULT' and dp.processbaseid = bs.baseid and dp.groupid = dg.groupid) ",
nativeQuery=true)
List<DemoEntity> findOne(@Param("beginTime") long beginTime, @Param("endTime") long endTime);
看着想吐,就是直接写SQL的缺点。
下面隆重介绍 JPA 的最佳搭档:QueryDSL。它的语法跟SQL一样简单,且代码清晰,具有代码提示、编译期错误检查等优势。同时,在架构的层次上实现了读写分离:JPA负责增删改、QueryDSL负责查询。
1. QueryDsl介绍
QueryDSL 是一个通用的查询框架,专注于通过 Java API 构建类型安全的SQL查询。
QueryDSL 可以通过一组通用的查询 API 为用户构建出适合不同类型ORM框架或者是 SQL 的查询语句,也就是说 QueryDSL 是基于各种 ORM 框架以及 SQL 之上的一个通用的查询框架。
借助 QueryDSL 可以在任何支持的 ORM 框架或者 SQL 平台上以一种通用的API方式来构建查询。目前 QueryDSL 支持的平台包括 JPA、JDO、SQL、Mongodb 等等。
2. 引入QueryDSL
本文以gradle构建为例,前提是已引入 Spring Data Jpa ,且JPA可正常使用。
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jpa'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
引入JPAQueryFactory
@Service
public class DemoQueryDSL {
@Autowired
private JPAQueryFactory queryFactory;
}
3. 创建JPA Entity
我们分别创建两个示例实体类:职员表、部门表。
/**
* 职员表
*/
@Data
@Entity
@Table(name = "T_EMP")
public class Emp {
@Id
private String id;//ID
@Column
private String name;//姓名
@Column
private Integer age;//年龄
@Column
private String sex;//性别
@Column
private String depId;//部门ID
}
/**
* 部门表
*/
@Data
@Entity
@Table(name = "T_DEP")
public class Dep {
@Id
private String id;//ID
@Column
private String depName;//部门名称
}
编译后,QueryDSL 会帮助我们会自动生成两个Q类:QEmp、QDep ,我们之后进行的所有查询都是围绕这些Q类来进行的。
4. 简单查询
QueryDSL提供了一种类似于SQL的面向对象写法,并且是类型安全的,搭配上IDEA的语句提示功能,写起SQL来非常舒服。
请欣赏下面的例子:
public void simpleSql() {
QEmp emp = QEmp.emp;//员工表
/**
* 简单条件查询、排序,相当于sql:
* select * from T_EMP
* where name like '张%' and age > 25
* order by age desc;
*/
List<Emp> empList = queryFactory.select(emp)
.where(emp.name.startsWith("张").and(emp.age.gt(25)))
.orderBy(emp.age.desc())
.fetch();
/**
* 分组查询,相当于sql:
* select e.dep_id, max(e.age) from T_EMP e
* grouping by e.depId;
*/
List<Tuple> list = queryFactory.select(emp.depId, emp.age.max())
.groupBy(emp.depId)
.fetch();
/**
* 分页查询,相当于sql:
* select * from T_EMP e
* where e.dep_id='123'
* limit 20 10;
*/
List<Emp> pageList = queryFactory.select(emp)
.where(emp.depId.eq("123"))
.offset(20)
.limit(10)
.fetch();
}
5. 复杂查询
QueryDSL对于复杂查询的支持也是相当优秀的,比如多表关联、动态条件查询等。
public void complexSql() {
QEmp emp = QEmp.emp;//员工表
QDep dep = QDep.dep;//部门表
/**
* 关联查询,相当于sql:
* select e.* from T_EMP e
* left join T_DEP d on e.dep_id = d.id
* where d.dep_name = '财务部'
*/
List<Emp> empList = queryFactory.select(emp)
.from(emp)
.leftJoin(dep).on(emp.depId.eq(dep.id))
.where(dep.depName.eq("财务部"))
.fetch();
/**
* 嵌套查询,相当于sql:
* select e.* from T_EMP e
* where e.dep_id = (
* select id form T_DEP where dep_name = '财务部'
* )
*/
List<Emp> empList1 = queryFactory.select(emp)
.from(emp)
.where(emp.depId.eq(
queryFactory.select(dep.id).from(dep)
.where(dep.depName.eq("财务部"))
))
.fetch();
/**
* 动态条件、别名、获取不同结果:
*/
BooleanBuilder condition = new BooleanBuilder();
condition.and(emp.age.goe(25));
if (true) {//动态条件
condition.and(emp.sex.eq("男"));
}
queryFactory.select(emp.name.as("fullname"))
.where(condition)
.fetch();//查找多个结果,返回集合
//.fetchOne();//查询只返回一个结果,如果返回多个则抛异常
//.fetchFirst();//返回多个结果时,只取第一个
}
小结
以上就是 QueryDSL 的简单应用,用写SQL的方法来写代码,是不是很舒服呢!文中的例子仅仅浅尝辄止,希望大家可以实际应用一下,后续我也会更深入的讲解一些 QueryDSL 的高级用法。
相关推荐
- 丨公司丨公司大架构整理汇总
-
注:本文转自团队成员原创作品,特此鸣谢(公号:法海图鉴)今日话题公司大架构整理背景介绍经过前几期话题对各种企业类型的介绍,想必大家已经有了初步认识。之后我将带着大家开启对公司的深入了解。本期...
- 图解物理--八年级物理下册最全知识框架导图
-
第七章力1力2弹力3重力第八章运动和力1牛顿第一定律2二力平衡3摩擦力第九章压强1压强2液体压强3大气压强4流体压强与流速的关系第十章浮力1浮力2阿基米德原理3物体的浮沉条件及应用第十一章功...
- 八年级上册生物,思维导图,期末高分必备资料,家长收藏
-
这是八年级上册生物的思维导图,孩子在背诵知识点的时候,可以看一下知识点在导图中的位置,形成对知识点整体的把握,有助于学生拿高分,特别是图片中带红色星星的部分,更是要注意背诵,是重点内容。家长可以把图片...
- 2019政府工作报告精华,这张思维导图里全都有
-
每经记者:李可愚每经编辑:陈星每日经济新闻
- 图解薪酬体系结构设计
-
...
- 司考复习独家总结!一张图总结行政法知识结构体系
-
作为三大实体法之一,行政法的分值在60分左右,行政法在司法考试中一直比较平稳常规,没有偏题怪题,还是比较容易得分的。小编要提醒大家,在3月之前要把三大实体法学习一遍。下图是厚大在线360导学师小周总结...
- 实用干货!高中物理框架图,让零碎知识“串联”起来
-
高中物理学习一定要抓好逻辑结构大框架!了解整个知识框架体系后,更易抓住骨干知识,干掉重难知识点~今天给大家分享高中物理的框架图同学们赶紧收藏起来吧!力学知识结构图光学知识结构图热学、原子物理知识结构图...
- 254m超高层办公楼型钢砼框架-核心筒结构图
-
高度类别:超高层建筑钢筋混凝土结构:框架,框架核心筒钢结构:钢框架建筑功能:办公包含:办公楼57层(-3层)254.150m钻孔灌注桩桩+筏板型钢混凝土框架-钢筋混凝土核心筒西裙房2层(-...
- 砖混结构与框架结构,究竟有何区别?千万别被坑!
-
现在买房装修的人最怕啥?不是价格高,而是房子不安全!两种主流建筑结构,砖混靠墙,框架靠柱子,选错了隔墙都可能要命。简单说,砖混便宜但别碰高层,框架贵点但能保命。砖混那些承重墙根本不能拆,想砸墙改个开放...
- 大师一百——高中化学必考:《元素周期律》考点框架图
-
今天大师给大家带来的是高中化学的《元素周期律》考点框架图,高中的同学必须牢记于心,这种重要的考点,考试是一定会考的!化学大师...
- 需求分析框架图
-
需求分析框架图
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)