【问题标题】:Hibernate always running redundant queryHibernate 总是运行冗余查询
【发布时间】:2017-09-26 02:47:01
【问题描述】:

我的数据模型中有一个 OneToOne 关系,并且 hibernate 总是查询这两个实体以生成结果集。

这是数据模型

@Entity
public class C1 {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, targetEntity = C2.class)
    private C2 c2;

    //... other stuff
}


@Entity
public class C2 extends OtherClassOutOfDomain {

   @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "c2")
    private C1 c1;

    //... other stuff
}

Hibernate 将我的架构生成为两个表,并且 C1 表具有 C2 的外键,这对我来说是完美的,因为我将更经常使用 C1。

但是

每次我查询 C1 hibernate 生成 1 个查询,每行连接两个实体数据,并为第一个结果中的每一行生成 N 个查询(即使在我访问结果集之前)

例子

Hibernate (just one): 
    select
        this_.id as id1_2_1_,
        this_.c2_id as authDat22_2_1_,
        this_.bio as bio2_2_1_,
        this_.blocked as blocked3_2_1_,
        this_.commentsAmount as comments4_2_1_,
        this_.confirmed as confirme5_2_1_,
        this_.deleted as deleted6_2_1_,
        c22_.id as id1_0_0_,
        c22_.adid as adid2_0_0_,
    from
        c1 this_ 
    inner join
        c2 c22_
            on this_.authData_id=c22_.id

Hibernate (N times as the size of previous query): 
    select
        this_.id as id1_2_1_,
        this_.c2_id as authDat22_2_1_,
        this_.bio as bio2_2_1_,
        this_.blocked as blocked3_2_1_,
        this_.commentsAmount as comments4_2_1_,
        this_.confirmed as confirme5_2_1_,
        this_.deleted as deleted6_2_1_,
        c22_.id as id1_0_0_,
        c22_.adid as adid2_0_0_,
    from
        c1 this_ 
    inner join
        c2 c22_
            on this_.authData_id=c22_.id
    where
            this_.authData_id=?
.....repeat
.....repeat
.....repeat

重复查询的结果在第一个大查询的行中包含...有什么办法可以避免这些不必要的请求?我试过设置为懒惰,但它不起作用

我运行的代码很简单

HibernateUtils.createNewSession().createCriteria(C1.class).list();

在触发嵌套查询之前我什至没有访问结果

我正在使用休眠 5.10 e mysql 5.7.17

【问题讨论】:

  • 可选=假?请尝试使用 true

标签: java mysql hibernate one-to-one


【解决方案1】:

记住这两件事。

OneToOne 的默认抓取策略是 EAGER。

LAZY 只能在 OneToOne 关联不可为空的情况下工作。

您的问题类似于 N+1 Selects Problem

解决 N+1 SELECTs 问题:

HQL 获取连接

要么

来自 C1 C1 左连接获取 c1.c2

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1")
@Fetch(FetchMode.JOIN) 
private C2 c2;

二等舱

@OneToOne(fetch = FetchType.LAZY, mappedBy = "c2")
@Fetch(FetchMode.JOIN) 
private C1 c1;

【讨论】:

    【解决方案2】:

    我找到了解决方案,但我不完全明白为什么。

    由于与 JPA 映射 OneToOne 关系,休眠会将外键放在具有“targetEntity”属性的实体上(THE ENTITY WITH THE ATTRIBUTE NO THE ENTITY SETTED IN ATRIBUTE VALUE)

    通过结构中具有外键的实体进行查询时,休眠将自动查询嵌套实体(我不知道原因)

    为了解决我之前的相关问题,我只需要将注释更改为

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true, optional = false, mappedBy= "c1")
    private C2 c2; 
    
    @OneToOne(fetch = FetchType.LAZY, targetEntity = C1.class) 
    private C1 c1;
    

    【讨论】:

      猜你喜欢
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 2013-09-09
      • 1970-01-01
      • 2021-12-31
      • 2021-10-13
      相关资源
      最近更新 更多