java - Hibernate ManyToOne n+1 使用 id 选择

标签 java hibernate

我遇到了一个关于 n+1 选择查询的奇怪问题。我的映射看起来像这样:

@Entity
@IdClass(MyTablePK.class)
@Table(name = "my_table", schema = "schema")
public class MyTable {

    @Id
    @Column(name = "name", nullable = false, length = 12)
    private String name="";

    @Id
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "myStringValue", referencedColumnName = "myStringValue")
    private AdditionalData data;

    ... (other fields, getters, setters)
}

public class MyTablePK implements Serializable {

    private String name;

    private AdditionalData data;

    (getters,setters)

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MyTablePK that = (MyTablePK) o;

        if (name!= null ? !name.equals(that.name) : that.name!= null) return false;
        return !(data!= null ? !data.equals(that.data) : that.data!= null);

    }

    @Override
    public int hashCode() {
        int result = name!= null ? name.hashCode() : 0;
        result = 31 * result + (data!= null ? data.hashCode() : 0);
        return result;
    }
}

@Entity
@Table(name = "info", schema = "schema")
public class AdditionalData implements Serializable {

    @Id
    @Column(name = "recno")
    private Long recno;

    @Column(name = "info1", length = 3)
    private String info1;

    @Column(name = "info2", length = 3)
    private String info2;

    ... (getters, setters)

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        AdditionalData data = (AdditionalData) o;

        return recno.equals(data.recno);

    }

    @Override
    public int hashCode() {
        return recno.hashCode();
    }
}

现在,我从 MyTable 中选择所有值。正如预期的那样,我得到了 n+1 个选择,对于 MyTable 的每一行,都有一个新的 AdditionalData 查询到达。为了解决这个问题,我写了一个 join fetch 查询:

FROM MyTable mytab join fetch mytab.data

然而...并没有改变任何东西。

现在,有趣的是,如果我暂时忽略业务需求,并删除 @IdClass 使 name 成为唯一的 @Id - 一切正常,所有数据都是通过一个询问。这是为什么?我不能用复合 id 的一部分来对抗 n+1 selects 吗?

以防万一 - 我使用 Hibernate 4.3.5.Final 和 Oracle 数据库

最佳答案

这可能与这里的这个已知问题有关:https://hibernate.atlassian.net/browse/HHH-10292

尝试映射 myStringValue 列两次。一次作为 id 的一部分,作为 String,另一次作为 AdditionalData,在连接列中带有 insertable = false, updatable = false

关于java - Hibernate ManyToOne n+1 使用 id 选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33804395/

相关文章:

java - 为什么 Spring 有 JdbcDaoSupport 类,但没有类似的 JmsSupport 类?

java - javac -target 1.3 是否保证这些类将在 JRE 1.3 下运行?

JAVA - JSON 将枚举列表序列化为类

Java/Hibernate + HSQLDB java.sql.BatchUpdateException : data exception: string data, 右截断

java - 使用 JPA 从集合中删除子项

java - Android 中的对象到字符串数组

java - 用 java.awt.Robot 模拟退格键

java - 设计模式只返回对象中的某些 LDAP 属性

hibernate - 带有Criteria的Grails,或者一种按预定顺序排序的快速方法

hibernate - 无法使gradle获得liquibase-hibernate插件工作