Hibernate 休眠条件以获取第一条记录

Hibernate 休眠条件以获取第一条记录,hibernate,criteria,hibernate-criteria,criteria-api,detachedcriteria,Hibernate,Criteria,Hibernate Criteria,Criteria Api,Detachedcriteria,我正在尝试解决系统中与分页相关的错误。当用户选择一条记录时,我们使用分页将所有相关记录检索回用户 设置页面maxResults后,DB将检索max记录,但这些记录会被复制并返回到hibernate。然后Hibernate检索重复记录并将剩余记录返回到UI。这导致返回的记录数与页面最大大小不一致 使用hibernate和criteria查询,这是执行的SQL,用于检索所有相关记录 select this_.id , this_.created_date , this_.

我正在尝试解决系统中与分页相关的错误。当用户选择一条记录时,我们使用分页将所有相关记录检索回用户

设置页面maxResults后,DB将检索max记录,但这些记录会被复制并返回到hibernate。然后Hibernate检索重复记录并将剩余记录返回到UI。这导致返回的记录数与页面最大大小不一致

使用hibernate和criteria查询,这是执行的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
选择
这个,这个,,
此创建日期,
这是再分析用户,
这个图书馆,
这个州,,
这是比较类别id,
这是芯片组的id,
这是一个图书馆工具包,
这是序列工具包id,
此模板套件id,
这个模板类型,
ucc.id,
usrp.user\u id,
usrp.run\u参数\u id,
user1.id,
user1.templateType,
utt.VALUE,
urp.id,
uki.id为id1_214_5_,
uki.unique_名称,
uki1.id,
uki1.唯一的名称,
ukart.KIT_ID,
uart.RUN_类型,
uart.RUN_类型,
uki2.id,
uki2.唯一的名称,
uki3.id,
uki3.唯一的名称,
utt.VALUE,
从…起
用户本
左外连接
用户\比较\类别ucc
在本例中,比较类别id=ucc.id
内连接
用户\u已保存\u运行\u参数usrp
在这个u.id=usrp.user id上
左外连接
用户用户1
在usrp.user\u id=user1.id上
左外连接
用户模板类型utt
在user1.templateType=utt.VALUE上
左外连接
用户运行参数urp
在usrp.run\u参数上\u id=urp.id
内连接
用户_KITINFO uki
在这个u.chipkit上id=uki.id
内连接
用户_KITINFO uki1
在这个库中,库id=uki1.id
内连接
用户\u套件\u允许\u运行\u类型ukart
关于uki1.id=ukart.KIT\u id
内连接
用户\u允许\u运行\u类型uart
在ukart.ALLOWED\u RUN\u TYPE=uart.RUN\u TYPE上
内连接
用户_KITINFO uki2
在这个目录上,sequencingkit\u id=uki2.id
内连接
用户_KITINFO uki3
在这个u.templatekit上_id=uki3.id
内连接
用户模板类型utt
在这个函数上,templateType=utt.VALUE
哪里
utt.VALUE in(
“自定义”、“安装顺序”
) 
这是再分析,用户=false
这个州(
“锁定”,“草稿”
) 
和utt.VALUE'install_seq'
还有uki。独一无二的名字是“Chip-Chock”
**和usrp.value='amplitude_1'**
和uart.RUN\u输入(
“样本”
) 
和uki1.unique_name='Blane Library Kit'
和utt.VALUE'install_seq'
和uki3。唯一的_name='Moon试剂盒'
和uki2。唯一的_name='Star Seq Kit'
订购人
这是创建日期描述
限制5偏移0
我所观察到的是,具有USER\u SAVED\u RUN\u参数的用户具有@OneToMany关系,因此我看到了重复项,我需要以某种方式添加一个条件usrp.value='Amplication\u 1,以便仅从该表中选择第一条记录


有办法吗?首先,我希望我可以尝试SQL,然后hibernate criteria query。

我不知道如何构造查询,但在执行集合的联接获取时使用
setFirstResult
setMaxResults
会导致问题。通常,在这种情况下,Hibernate不会对查询应用限制,因为这将导致无法正确获取集合。所以Hibernate将获取所有内容并在内存中进行分页,这是非常低效的

如果您使用联接获取,那么您就不走运了。JPA要求托管实体和数据库的状态在事务结束时必须同步,因此仅获取实体的部分集合实际上会删除未获取的元素,这就是JPA不允许这样做的原因。不过,您可以使用Hibernate来执行此操作,但我不推荐使用它,因为它可能会导致删除

因此,为了得到您想要的,您需要编写一个HQL或JPA条件查询,并将数据提取到DTO中。在查询中,您可以选择所需的所有字段,并可以定义您提到的连接条件。如果仍要获取集合,则有其他方法可以实现分页。Blaze Persistence提供了一个简单的API,支持高效的密钥集分页:

关于DTO,我认为这是一个完美的DTO用例

我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型

在Blaze持久性实体视图中,您的用例的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数据集成允许您像使用Spring数据投影一样使用它: