自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JPA的好搭檔 - QueryDSL

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
QueryDSL 的簡(jiǎn)單應(yīng)用,用寫(xiě)SQL的方法來(lái)寫(xiě)代碼,是不是很舒服呢!文中的例子僅僅淺嘗輒止,希望大家可以實(shí)際應(yīng)用一下,后續(xù)我也會(huì)更深入的講解一些 QueryDSL 的高級(jí)用法。

?0. 前言

相對(duì)于 MyBatis ,本人更喜歡 Spring Data JPA ,因?yàn)樗厦嫦驅(qū)ο蟮乃枷耄欢?JPA 對(duì)復(fù)雜的查詢(xún)支持較弱,常見(jiàn)的有兩種方式:

一種方式是Repository繼承JpaSpecificationExecutor接口,優(yōu)點(diǎn)是支持復(fù)雜查詢(xún)、編譯期可以規(guī)避一些語(yǔ)法錯(cuò)誤,缺點(diǎn)是語(yǔ)法晦澀難懂,學(xué)習(xí)成本太高。

還有一種方式就是直接寫(xiě) SQL ,可以通過(guò)JdbcTemplate或者@Query注解的方式查詢(xún),優(yōu)點(diǎn)是簡(jiǎn)單,缺點(diǎn)嘛...先看段代碼:

@Query(value="select bs.* from " +
"(select t.baseid,t.basesn,t.basecreatorfullname,t.basestatus,t.basesummary,'北京' faultprovince, '北京' faultcity, " +
"replace(t.INC_ResponseLevel,'響應(yīng)','') 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,'否','未預(yù)處理','否','是') flagpretreatment,decode(t.flagPretreatment,null,'否','未預(yù)處理','否','是') 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 = '傳輸網(wǎng)絡(luò)故障處理工單' 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,'響應(yīng)','') 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,'否','未預(yù)處理','否','是') flagpretreatment,decode(t.flagPretreatment,null,'否','未預(yù)處理','否','是') 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);

看著想吐,就是直接寫(xiě)SQL的缺點(diǎn)。

下面隆重介紹 JPA 的最佳搭檔:QueryDSL。它的語(yǔ)法跟SQL一樣簡(jiǎn)單,且代碼清晰,具有代碼提示、編譯期錯(cuò)誤檢查等優(yōu)勢(shì)。同時(shí),在架構(gòu)的層次上實(shí)現(xiàn)了讀寫(xiě)分離:JPA負(fù)責(zé)增刪改、QueryDSL負(fù)責(zé)查詢(xún)。

1. QueryDsl介紹

QueryDSL 是一個(gè)通用的查詢(xún)框架,專(zhuān)注于通過(guò) Java API 構(gòu)建類(lèi)型安全的SQL查詢(xún)。

QueryDSL 可以通過(guò)一組通用的查詢(xún) API 為用戶構(gòu)建出適合不同類(lèi)型ORM框架或者是 SQL 的查詢(xún)語(yǔ)句,也就是說(shuō) QueryDSL 是基于各種 ORM 框架以及 SQL 之上的一個(gè)通用的查詢(xún)框架。

借助 QueryDSL 可以在任何支持的 ORM 框架或者 SQL 平臺(tái)上以一種通用的API方式來(lái)構(gòu)建查詢(xún)。目前 QueryDSL 支持的平臺(tái)包括 JPA、JDO、SQL、Mongodb 等等。

2. 引入QueryDSL

本文以gradle構(gòu)建為例,前提是已引入 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. 創(chuàng)建JPA Entity

我們分別創(chuàng)建兩個(gè)示例實(shí)體類(lèi):職員表、部門(mén)表。

/**
* 職員表
*/
@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;//部門(mén)ID
}

/**
* 部門(mén)表
*/
@Data
@Entity
@Table(name = "T_DEP")
public class Dep {
@Id
private String id;//ID
@Column
private String depName;//部門(mén)名稱(chēng)
}

編譯后,QueryDSL 會(huì)幫助我們會(huì)自動(dòng)生成兩個(gè)Q類(lèi):QEmp、QDep ,我們之后進(jìn)行的所有查詢(xún)都是圍繞這些Q類(lèi)來(lái)進(jìn)行的。

4. 簡(jiǎn)單查詢(xún)

QueryDSL提供了一種類(lèi)似于SQL的面向?qū)ο髮?xiě)法,并且是類(lèi)型安全的,搭配上IDEA的語(yǔ)句提示功能,寫(xiě)起SQL來(lái)非常舒服。

請(qǐng)欣賞下面的例子:

public void simpleSql(){
QEmp emp = QEmp.emp;//員工表
/**
* 簡(jiǎn)單條件查詢(xún)、排序,相當(dāng)于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();

/**
* 分組查詢(xún),相當(dāng)于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();

/**
* 分頁(yè)查詢(xún),相當(dāng)于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. 復(fù)雜查詢(xún)

QueryDSL對(duì)于復(fù)雜查詢(xún)的支持也是相當(dāng)優(yōu)秀的,比如多表關(guān)聯(lián)、動(dòng)態(tài)條件查詢(xún)等。

public void complexSql(){
QEmp emp = QEmp.emp;//員工表
QDep dep = QDep.dep;//部門(mén)表

/**
* 關(guān)聯(lián)查詢(xún),相當(dāng)于sql:
* select e.* from T_EMP e
* left join T_DEP d on e.dep_id = d.id
* where d.dep_name = '財(cái)務(wù)部'
*/
List<Emp> empList = queryFactory.select(emp)
.from(emp)
.leftJoin(dep).on(emp.depId.eq(dep.id))
.where(dep.depName.eq("財(cái)務(wù)部"))
.fetch();

/**
* 嵌套查詢(xún),相當(dāng)于sql:
* select e.* from T_EMP e
* where e.dep_id = (
* select id form T_DEP where dep_name = '財(cái)務(wù)部'
* )
*/
List<Emp> empList1 = queryFactory.select(emp)
.from(emp)
.where(emp.depId.eq(
queryFactory.select(dep.id).from(dep)
.where(dep.depName.eq("財(cái)務(wù)部"))
))
.fetch();

/**
* 動(dòng)態(tài)條件、別名、獲取不同結(jié)果:

*/
BooleanBuilder condition = new BooleanBuilder();
condition.and(emp.age.goe(25));
if (true) {//動(dòng)態(tài)條件
condition.and(emp.sex.eq("男"));
}
queryFactory.select(emp.name.as("fullname"))
.where(condition)
.fetch();//查找多個(gè)結(jié)果,返回集合
//.fetchOne();//查詢(xún)只返回一個(gè)結(jié)果,如果返回多個(gè)則拋異常
//.fetchFirst();//返回多個(gè)結(jié)果時(shí),只取第一個(gè)
}

小結(jié)

以上就是 QueryDSL 的簡(jiǎn)單應(yīng)用,用寫(xiě)SQL的方法來(lái)寫(xiě)代碼,是不是很舒服呢!文中的例子僅僅淺嘗輒止,希望大家可以實(shí)際應(yīng)用一下,后續(xù)我也會(huì)更深入的講解一些 QueryDSL 的高級(jí)用法。

責(zé)任編輯:武曉燕 來(lái)源: Java技術(shù)指北
相關(guān)推薦

2022-05-26 07:42:22

Python編輯器VSCode

2023-02-24 13:07:07

2022-11-14 09:55:34

長(zhǎng)江存儲(chǔ)

2011-05-20 07:40:08

2021-05-29 20:45:37

辦公

2017-11-09 16:02:26

11.11

2021-03-24 16:59:15

存儲(chǔ)

2019-09-18 13:32:00

DELL筆記本

2023-07-17 11:25:35

.NET程序WinDbgPerfview

2019-12-11 10:00:10

區(qū)塊鏈區(qū)塊鏈技術(shù)

2011-06-22 10:13:58

TRILLFCoESTP

2020-06-02 10:00:33

GitHub 技術(shù)開(kāi)發(fā)

2009-07-03 10:48:12

JSP和JSF

2019-12-23 13:52:51

區(qū)塊鏈物聯(lián)網(wǎng)IOT

2019-11-07 13:22:15

戴爾

2022-10-10 16:14:28

元宇宙互聯(lián)網(wǎng)虛擬世界

2012-03-16 16:43:59

華碩無(wú)線路由器

2009-12-08 12:32:09

GoogleChrome瀏覽器

2012-03-06 11:25:40

ibmdw
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)