如何解决休眠准则获得第一记录
我正在尝试解决系统中与分页有关的错误。当用户选择一条记录时,我们将使用分页将所有相关记录取回给用户。
在设置页面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,uki2.id,uki2.unique_name,uki3.id,uki3.unique_name,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_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表达式将属性(获取器)映射到实体模型。
针对您的用例的DTO模型可能与Blaze-Persistence Entity-Views相似,如下所示:
@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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。