java - Hibernate 总是运行冗余查询

标签 java mysql hibernate one-to-one

我的数据模型中有一对一关系,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();

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

我正在使用 hibernate 5.10 和 mysql 5.7.17

最佳答案

记住这两件事。

OneToOne 的默认抓取策略是 EAGER。

LAZY 只能在关联不可为空的 OneToOne 关联上工作。

你的问题类似于N+1选择问题

解决 N+1 SELECT 问题:

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;

关于java - Hibernate 总是运行冗余查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46417061/

相关文章:

mysql - 使用 Spring、hibernate 和 C3P0 的设置重现 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException

java - 从 Java 文件中读取特定行

java - 在 SQLite 3 数据库中查询 URL 字符串

mysql - MySQL 存储函数中的 FLOAT 类型可以被截断吗?

php - 非英文字符在我的 PHP 页面上显示为问号 - 在数据库中显示正常

php - 创建一个 View ,获取排名、用户名和用户记录数

java - 在 Spring+JPA 中更新级联子级时出现 UnsupportedOperationException

java - AuditQuery如何加入实体

java - EchoServer(Java)不将消息返回给客户端(golang)

java - 如何调用接口(interface)的特定实现类