[英]Hibernate Criteria to take the first record
我正在嘗試解決系統中與分頁相關的錯誤。 當用戶選擇一條記錄時,我們使用分頁將所有關聯的記錄檢索回給用戶。
設置頁面 maxResults 后,DB 檢索最大記錄,但它們被復制並返回到休眠狀態。 Hibernate 然后檢索重復項並將剩余的記錄返回給 UI。 這會導致返回的記錄數與頁面最大大小之間不一致。
使用休眠和條件查詢,這是執行檢索所有關聯記錄的 SQL。
select
this_.id ,
this_.created_date ,
this_.is_reanalysis_user ,
this_.library ,
this_.state ,
this_.compare_category_id ,
this_.chipkit_id ,
this_.librarykit_id ,
this_.sequencingkit_id ,
this_.templatekit_id ,
this_.templateType ,
ucc.id ,
usrp.user_id ,
usrp.run_parameter_id ,
user1.id ,
user1.templateType ,
utt.VALUE ,
urp.id ,
uki.id as id1_214_5_,
uki.unique_name ,
uki1.id ,
uki1.unique_name ,
ukart.KIT_ID ,
uart.RUN_TYPE ,
uart.RUN_TYPE ,
uki2.id ,
uki2.unique_name ,
uki3.id ,
uki3.unique_name ,
utt.VALUE ,
from
USER this_
left outer join
USER_compare_category ucc
on this_.compare_category_id=ucc.id
inner join
USER_SAVED_RUN_PARAMETER usrp
on this_.id=usrp.user_id
left outer join
USER user1
on usrp.user_id=user1.id
left outer join
USER_TEMPLATE_TYPES utt
on user1.templateType=utt.VALUE
left outer join
USER_RUN_PARAMETER urp
on usrp.run_parameter_id=urp.id
inner join
USER_KITINFO uki
on this_.chipkit_id=uki.id
inner join
USER_KITINFO uki1
on this_.librarykit_id=uki1.id
inner join
USER_KIT_ALLOWED_RUN_TYPES ukart
on uki1.id=ukart.KIT_ID
inner join
USER_ALLOWED_RUN_TYPES uart
on ukart.ALLOWED_RUN_TYPE=uart.RUN_TYPE
inner join
USER_KITINFO uki2
on this_.sequencingkit_id=uki2.id
inner join
USER_KITINFO uki3
on this_.templatekit_id=uki3.id
inner join
USER_TEMPLATE_TYPES utt
on this_.templateType=utt.VALUE
where
utt.VALUE in (
'custom', 'install_seq'
)
and this_.is_reanalysis_user=false
and this_.state in (
'Locked', 'Draft'
)
and utt.VALUE<>'install_seq'
and uki.unique_name='Chip-Chock'
**and usrp.value='amplitude_1'**
and uart.RUN_TYPE in (
'sample'
)
and uki1.unique_name='Blane Library Kit'
and utt.VALUE<>'install_seq'
and uki3.unique_name='Moon reagent Kit'
and uki2.unique_name='Star Seq Kit'
order by
this_.created_date desc
limit 5 offset 0
我觀察到的是 USER WITH USER_SAVED_RUN_PARAMETER 具有 @OneToMany 關系,因此我看到重復,我需要以某種方式添加一個條件usrp.value='amplitude_1 ' 以僅從該表中選擇第一條記錄。
有沒有辦法做到這一點? 首先,我希望我可以嘗試使用 SQL,然后進行休眠條件查詢。
我不知道您如何構造查詢,但是在執行集合的連接提取時使用setFirstResult
和setMaxResults
會導致問題。 通常,在這種情況下,Hibernate 不會對查詢應用限制,因為這會導致無法正確獲取集合。 因此 Hibernate 會獲取所有內容並在內存中進行分頁,這是非常低效的。
如果你使用連接獲取,你就不走運了。 JPA 要求在事務結束時托管實體和數據庫的狀態必須同步,因此僅獲取實體的部分集合實際上會刪除未獲取的元素,這就是 JPA 不允許這樣做的原因。 但是,您可以使用 Hibernate 執行此操作,但我不推薦它,因為它可能會導致刪除。
所以為了得到你想要的東西,你需要編寫一個 HQL 或 JPA Criteria 查詢並將數據提取到 DTO 中。 在查詢中,您選擇您需要的所有字段,並可以定義您提到的連接條件。 如果您仍然想獲取集合,還有其他方法可以實現分頁。 Blaze-Persistence 提供了一個簡單的 API,支持高效的密鑰集分頁: https : //persistence.blazebit.com/documentation/core/manual/en_US/index.html#pagination
關於 DTO,我認為這是Blaze-Persistence Entity Views的完美用例。
我創建了該庫以允許在 JPA 模型和自定義接口或抽象類定義的模型之間輕松映射,例如類固醇上的 Spring Data Projections。 這個想法是您按照自己喜歡的方式定義目標結構(域模型),並通過 JPQL 表達式將屬性(getter)映射到實體模型。
使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:
@EntityView(User.class)
public interface UserDto {
@IdMapping
Long getId();
Instant getCreatedDate();
@Mapping("savedRunParameters[value = 'aplitude_1']")
RunParameterDto getRunParameter();
@EntityView(RunParameter.class)
interface RunParameterDto {
@IdMapping
Long getId();
}
// Other mappings
}
查詢是將實體視圖應用於查詢的問題,最簡單的只是按 id 查詢。
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
Spring Data 集成允許您幾乎像 Spring Data Projections 一樣使用它: https : //persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.