hibernate 一对多 取多方数据重复问题,FetchMode.JOIN、FetchMode.SELECT、FetchMode.SUBSELECT区别

问题描述:稿件附件表数据时出现多条重复数据。

介绍

表:稿件实体Manuscripts (数据库表MANUSCRIPTS),稿件附件实体ManuscriptsAtt(表MANUSCRIPTS_ATT),稿件审核实体:ManuscriptsQuotes

表关系:稿件与稿件附件 一对多;稿件与稿件审核一对多;

代码

稿件实体 Manuscripts 

 

复制代码

@Entity
@Table(name = "MANUSCRIPTS")

public class Manuscripts implements Serializable {

//主键
@Id
@Column(length = 38,name = "ID")
private String id;

......

@OneToMany(targetEntity = ManuscriptsAtt.class,fetch=FetchType.EAGER)
@JoinColumn(name="MANUSCRIPTS_ID")
@Fetch(FetchMode.SUBSELECT)
private Set<ManuscriptsAtt> manuscriptsAtts;

@OneToMany(targetEntity = ManuscriptsQuotes.class,fetch=FetchType.EAGER)
@JoinColumn(name="MANUSCRIPTS_ID")
@Fetch(FetchMode.SUBSELECT)
private Set<ManuscriptsQuotes> manuscriptsQuotes;

......

}
复制代码

稿件附件实体: 

 

复制代码

@Entity
@Table(name = "MANUSCRIPTS_ATT")

public class ManuscriptsAtt implements Serializable {

/**
* 
*/
private static final long serialVersionUID = 1L;

//主键
@Id
@Column(length = 38, name = "ID")
private String id;

.....
//父类
@ManyToOne
@JoinColumn(name = "MANUSCRIPTS_ID")
private Manuscripts manuscripts;

.....}
复制代码

稿件审核实体:

复制代码
@Entity
@Table(name = "MANUSCRIPTS_QUOTES")
public class ManuscriptsQuotes implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    //主键
    @Id
    @Column(length = 38,name = "ID")
    private String id;

    //父类
     @ManyToOne
     @JoinColumn(name = "MANUSCRIPTS_ID")
    private Manuscripts manuscripts;
...
}
复制代码

 

稿件实体 Manuscripts 中oneToMany 下Fetch设置不同结果不同

@Fetch(FetchMode.JOIN) 会使用left join查询 只产生一条sql语句
@Fetch(FetchMode.SELECT) 会产生N+1条sql语句
@Fetch(FetchMode.SUBSELECT) 产生两条sql语句 第二条语句使用id in (…..)查询出所有关联的数据

下面介绍列出附件数据sql和会出现结果

@Fetch(FetchMode.JOIN) 后sql语句和结果(会使用left join查询 只产生一条sql语句)

复制代码
Hibernate: 
    select
        this_.id as id1_13_1_,
        this_.file_address as file_add6_13_1_,
        this_.file_name as file_nam7_13_1_,
        this_.manuscripts_id as manuscr11_13_1_,
        this_.type as type9_13_1_, 
        manusc1_.id as id1_11_0_,
        manusc1_.content as content4_11_0_,
        manusc1_.create_time as create_t5_11_0_,
        manusc1_.title as title21_11_0_,
        manusc1_.type as type22_11_0_ 
        manuscript4_.manuscripts_id as manuscr11_11_5_,
        manuscript4_.id as id1_13_5_,
        manuscript4_.id as id1_13_1_,
        manuscript4_.file_address as file_add6_13_1_,
        manuscript4_.file_name as file_nam7_13_1_,
        manuscript4_.manuscripts_id as manuscr11_13_1_,
        manuscript4_.type as type9_13_1_,
        manuscript5_.manuscripts_id as manuscri7_11_6_,
        manuscript5_.id as id1_14_6_,
        manuscript5_.id as id1_14_2_,
        manuscript5_.department as departme2_14_2_,
        manuscript5_.department_name as departme3_14_2_,
        manuscript5_.editor_person as editor_p4_14_2_,
        manuscript5_.editor_person_name as editor_p5_14_2_,
        manuscript5_.manuscripts_id as manuscri7_14_2_,
        manuscript5_.quote_time as quote_ti6_14_2_ 
    from
        manuscripts_att this_ 
    inner join
        manuscripts manusc1_ 
            on this_.manuscripts_id=manusc1_.id 
    left outer join
        manuscripts_att manuscript4_ 
            on manusc1_.id=manuscript4_.manuscripts_id 
    left outer join
        manuscripts_quotes manuscript5_ 
            on manusc1_.id=manuscript5_.manuscripts_id 
    where
        this_.type=? 
    order by
        this_.createtime desc
复制代码

 FetchMode.JOIN  :会使用left join查询 只产生一条sql语句 ,结果数据重复

@Fetch(FetchMode.SELECT) 后sql语句和结果(会产生N+1条sql语句)

复制代码
Hibernate: 
    select
       this_.id as id1_13_1_,
        this_.file_address as file_add6_13_1_,
        this_.file_name as file_nam7_13_1_,
        this_.manuscripts_id as manuscr11_13_1_,
        this_.type as type9_13_1_,   
        manusc1_.id as id1_11_0_,
        manusc1_.content as content4_11_0_,
        manusc1_.create_time as create_t5_11_0_,
        manusc1_.title as title21_11_0_,
        manusc1_.type as type22_11_0_ 
    from
        manuscripts_att this_ 
    inner join
        manuscripts manusc1_ 
            on this_.manuscripts_id=manusc1_.id 
    where
        this_.type=? 
    order by
        this_.createtime desc
Hibernate: 
    select
        manuscript0_.manuscripts_id as manuscri7_11_0_,
        manuscript0_.id as id1_14_0_,
        manuscript0_.id as id1_14_1_,
        manuscript0_.department as departme2_14_1_,
        manuscript0_.department_name as departme3_14_1_,
        manuscript0_.editor_person as editor_p4_14_1_,
        manuscript0_.editor_person_name as editor_p5_14_1_,
        manuscript0_.manuscripts_id as manuscri7_14_1_,
        manuscript0_.quote_time as quote_ti6_14_1_ 
    from
        manuscripts_quotes manuscript0_ 
    where
        manuscript0_.manuscripts_id=?
Hibernate: 
    select
        manuscript0_.manuscripts_id as manuscr11_11_0_,
        manuscript0_.id as id1_13_0_,
        manuscript0_.id as id1_13_1_,
        manuscript0_.createtime as createti2_13_1_,
        manuscript0_.create_person as create_p3_13_1_,
        manuscript0_.create_person_name as create_p4_13_1_,
        manuscript0_.download_count as download5_13_1_,
        manuscript0_.file_address as file_add6_13_1_,
        manuscript0_.file_name as file_nam7_13_1_,
        manuscript0_.file_suff as file_suf8_13_1_,
        manuscript0_.manuscripts_id as manuscr11_13_1_,
        manuscript0_.type as type9_13_1_,
        manuscript0_.view_count as view_co10_13_1_ 
    from
        manuscripts_att manuscript0_ 
    where
        manuscript0_.manuscripts_id=?
.......................
复制代码

@Fetch(FetchMode.SELECT) 会产生N+1条sql语句 ,结果正确,但是效率低

 

 

@Fetch(FetchMode.SUBSELECT) 产生两条sql语句 第二条语句使用id in (…..)查询出所有关联的数据

复制代码
Hibernate: 
    select
        this_.id as id1_13_1_,
        this_.file_address as file_add6_13_1_,
        this_.file_name as file_nam7_13_1_,
        this_.manuscripts_id as manuscr11_13_1_,
        this_.type as type9_13_1_,   
        manusc1_.id as id1_11_0_,
        manusc1_.content as content4_11_0_,
        manusc1_.create_time as create_t5_11_0_,
        manusc1_.title as title21_11_0_,
        manusc1_.type as type22_11_0_ 
    from
        manuscripts_att this_ 
    inner join
        manuscripts manusc1_ 
            on this_.manuscripts_id=manusc1_.id 
    where
        this_.type=? 
    order by
        this_.createtime desc
Hibernate: 
    select
        manuscript0_.manuscripts_id as manuscri7_11_1_,
        manuscript0_.id as id1_14_1_,
        manuscript0_.id as id1_14_0_,
        manuscript0_.department as departme2_14_0_,
        manuscript0_.department_name as departme3_14_0_,
        manuscript0_.editor_person as editor_p4_14_0_,
        manuscript0_.editor_person_name as editor_p5_14_0_,
        manuscript0_.manuscripts_id as manuscri7_14_0_,
        manuscript0_.quote_time as quote_ti6_14_0_ 
    from
        manuscripts_quotes manuscript0_ 
    where
        manuscript0_.manuscripts_id in (
            select
                manusc1_.id 
            from
                manuscripts_att this_ 
            inner join
                manuscripts manusc1_ 
                    on this_.manuscripts_id=manusc1_.id 
            where
                this_.type=? 
        )
复制代码

FetchMode.SUBSELECT: 产生两条sql语句 第二条语句使用id in (…..)查询出所有关联的数据 结果正确,效率相对高

 

posted @   gxy_java  阅读(4822)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示