休眠:获取太多行

Posted

技术标签:

【中文标题】休眠:获取太多行【英文标题】:Hibernate: getting too many rows 【发布时间】:2012-09-29 13:00:05 【问题描述】:

我在使用 Hibernate 从数据库中获取行时遇到问题。当我只想得到一行时,我收到了 20 行。当我想从大约 1.5k 行的表中获取所有行时,我正好收到 15.2k 行。 该表的实体类具有复合主键。

这是我获取所有行的代码:

Criteria criteria = getSession().createCriteria(type);
criteria.setCacheable(true).setCacheRegion(BaseEntity.PACKAGE);
criteria.list();

这是我的实体类:

@javax.persistence.Entity
@Table(name = "my_table")
public class My extends MyEntity<MyPK> 

    @EmbeddedId
    private MyPK id;

    @Column(name = "text", nullable = false)
    protected String text;

    @ManyToOne
    @JoinColumn(name = "property", nullable = false, insertable = false, updatable = false)
    protected Option option;

    @Override
    public MyPK getId() 
        return id;
    

    @Override
    public void setId(MyPK id) 
        this.id = id;
    

    //getters and setter

这是MyPK类:

@Embeddable
public class MyPK implements Serializable 

   @Column(name = "qwerty")
   protected String qwerty;

   @Column(name = "property")
   protected String property;

   //constructors, getters and setters

MyEntity 类是带有@MappedSuperclass 注释的抽象类。这是这个类头:

@MappedSuperclass
public abstract class MyEntity<T extends Serializable>

我做错了什么? EmbeddedId 有这个问题吗?

编辑 #1 正如我已经意识到这是问题所在:

@ManyToOne
@JoinColumn(name = "property", nullable = false, insertable = false, updatable = false)
protected Option option;

此对象包含另一个表的外键。而这个另一个表引用了另一个。最后一张表有 10 行用于上一张表。结果我得到行数量 * 10。问题可能出在我的实体中的 Hibernate 注释。

【问题讨论】:

返回的对象都是同一个实例吗?意思是你得到了 20 个完全相同的对象引用吗? @SteveEbersole:我想是的。我明天会检查,因为目前我不能。我从 Hibernate 控制台检查了 sql,我意识到 Hibernate 正在从数据库中获取其他几个表。这些表当然是通过外键连接的。但我不知道为什么简单地从一个表中获取所有行,我的代码得到的附加表很少。对于数据库中的一行,我得到十行作为查询结果。 @SteveEbersole :我已经检查过了。我为一个对象获取 10 个实例,为另一个对象获取 10 个实例。 【参考方案1】:

看起来您可能正急切地在某个地方加入多对一关系。默认行为是为数据库返回的每一行获取一个实体。如果您不想更改急切获取,但确实想删除结果中的重复项,则需要使用此ResultTransformer

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

【讨论】:

【参考方案2】:

@Embeddable 仅表示 MyPK 的列将是 My 类中的列。 您的问题可能是 @ManyToOne @JoinColumn(name = "property"),因为它与 MyPK 中的 "property" 相同

【讨论】:

是的,和MyPK中的“property”是一样的。我这样写是因为这是主键的一部分,也是这个表中的外键。【参考方案3】:

您可以使用此方法在条件上设置最大结果数:setMaxResults(int maxResults)

【讨论】:

是的,我可以,但我需要更复杂的解决方案。 既然有一个简单的解决方案,为什么还要一个复杂的解决方案?! 因为我不知道我想要返回多少行。此计数存储在数据库中,可能会有所不同。【参考方案4】:

主键类需要根据聚合值(qwertyproperty,此处)定义 equals() 和 hashCode()。很可能在处理 ResultSet 时,Hibernate 不会看到跨多行的实体键是相等的。

来自 JPA 2.0 规范的第 2.4 节(如果有帮助的话):

主键类必须定义equals和hashCode方法。价值的语义 这些方法的相等性必须与数据库类型的数据库相等性一致 键映射到的位置

【讨论】:

我已经定义了equals()hashCode(),但我的问题还是一样。您还有其他建议吗? 我想知道我的实体是否正确,所以我也问了这个问题:***.com/q/12849545/845220 你能也读一下这个吗?

以上是关于休眠:获取太多行的主要内容,如果未能解决你的问题,请参考以下文章

使用 Java spring 和休眠的 Oracle 插入需要太多时间

在休眠中的多对多映射中仅插入一个表

从应用程序获取休眠会话计数

如何从休眠会话中获取 jdbc 连接? [复制]

为啥休眠在获取较少行数时较慢?

具有多个关联的休眠获取