通常來說**的後台管理系統對於資料的查詢需要提供多種查詢條件,並且要求在使用者任意的選擇條件進行查詢:
這種情況下後端需要通過不同的條件組合對資料庫進行查詢,mybatis的標籤能夠很好地實現這個功能:只需要在
if
標籤中對引數進行判空,非空則拼接where 條件即可。
但是對於spring data jpa 這種高度封裝的框架來說可能會稍微複雜一些,總結了幾種使用spring data jpa 實現動態條件資料庫查詢的方案,主要有以下四種:
這種方法簡單粗暴:列舉所有查詢條件的所有組合情況並根據不同的近況進行不同條件的資料庫查詢:
//偽**
if(name = null)
else
}else
else
}
這種做法在引數極少的情況下才有可能被使用,3個引數就會出現6種組合,4個引數就有16種組合。組合情況會隨著引數的增多出現指數式的上公升,非常難以維護。
spring data 提供了jpaspecificationexecutor介面繼承這個介面提供了findall findone等過載方法,在查詢的時候可以通過**來構建不同的查詢條件,並且支援分頁行為
public
inte***ce
userrepository
extends
jparepository
,jpaspecificationexecutor
具體的使用方式不做贅述,感興趣的可以自行檢索。
這種方法的缺陷在於:雖然同樣支援多表查詢,但是關聯的方式非常侷限(需要在實體中有外來鍵關係對映才能使用)無法指定通過兩張表的哪兩個欄位是用於關聯的
如果出於某些原因,兩張表在業務上是關聯的,但是在資料庫和實體中並沒有通過外來鍵和@onetoone
onetomany
等註解進行關聯的話 ,這種specification是無法進行關聯查詢的
不過在少量資料的情況下可以通過先查詢一張表在拼接in
查詢來完成某些效能要求不高的查詢
spring data jpa底層的實現是hibernate ,而且通過原始碼可以發現其實jpa底層的資料庫操作其實都是基於entitymanager來完成的,entitymanager 是 相當於hibernate中的session物件。我們可以從容器中獲取entitymanager物件 然後根據條件動態的拼接hql語句最終 通過entitymanager物件來執行:
public
class
custombatchsubscriberdaoimpl
implements
custombatchsubscriberdao
if(null != age)
//...
datahql = datahql + wherehql;
query query = entitymanager.
createquery
(datahql)
;//注入引數
for(map.entry
entry : param.
entryset()
)int start =
(pageno -1)
* pagesize +1;
query = query.
setfirstresult
(start)
.setmaxresults
(pagesize)
; list resultlist = query.
getresultlist()
;//查詢count
counthql = counthql + wherehql;
query countquery = entitymanager.
createquery
(counthql)
;for
(map.entry
entry : param.
entryset()
) object count = countquery.
getsingleresult()
;//組裝分頁物件
pagevo
pagevo =
newpagevo
(pageno, pagesize)
; pagevo.
settotal
((long) count)
; pagevo.
setdatalist
(resultlist)
;return pagevo;
}
這種方案是最被經常使用的方法 , 通常在使用spring data jpa來建立專案的時候會 抽取出持久層介面基類和實現來提供 基於hql的查詢,而hql的拼接則放在業務層進行處理即可,所以並不會使**變得特別更加臃腫難以維護。
示例如下:
public
inte***ce
userrepository extend jparepository
其實就是將引數拼到hql或sql裡利用邏輯表示式or來實現引數為空時條件不生效:
name引數為空 則第乙個where條件為:
# name引數為空 則第乙個where條件為
where
(u.name =
null
ornull
isnull
)
可見null is null
條件永遠成立,所以改條件不會生效
反之當name引數不為空的時候 第乙個where條件為:
# name引數為 「李四」
where
(u.name =
'李四'
or'李四'
isnull
)
可見'李四' is null
這一條件永遠不成立,所以只有前面的條件生效。
利用這種方式可以非常方便的實現類似於動態查詢的效果,但是這種方式只能判空 , 所以在某些情況下可能需要先在業務層進行判斷,不符合條件的話就把引數置為空在呼叫
spring data的有點在於簡化持久層開發,高度的封裝在極大程度上隱藏了資料庫操作的細節,當然這並不意味著無法實現靈活的資料操作。
以上幾種動態查詢的方法各有優缺,需要根據具體的業務場景選擇最合適的方案
關於Spring Data Jpa的分頁 跨表查詢
jqa的query使用原生sql查詢 nativequery true 的時候不支援排序的,需要在sql裡面加上 order by spring data jpa本地查詢 帶分頁方式 query value select u.from user u inner join project user p...
spring data jpa實體繼承
spring jpa中我們要將sql對映到物件,尤其是在spring boot這種高度自動化的環境下使用,大量的最優目錄結構與命名規則可以大大降低配置,約定大於配置貫穿其中。例如我們定義查詢dao,繼承jparepository即可。然後返回的物件,我們可以定義model entity table ...
SpringData JPA分頁查詢
首先我們需要知道springdata jpa 的幾個介面 其實看名字就大概懂了,也可以很方便的使用 首先我們的持久化層繼承jparepository,相當於繼承了增刪改查的持久化層以及分頁查詢的持久化層 所以如果我們要使用分頁查詢 我們只需要直接呼叫 由一開始的圖也可以看到pageable的其中乙個...