休眠:获取太多行
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】:主键类需要根据聚合值(qwerty
和 property
,此处)定义 equals() 和 hashCode()。很可能在处理 ResultSet 时,Hibernate 不会看到跨多行的实体键是相等的。
来自 JPA 2.0 规范的第 2.4 节(如果有帮助的话):
主键类必须定义equals和hashCode方法。价值的语义 这些方法的相等性必须与数据库类型的数据库相等性一致 键映射到的位置
【讨论】:
我已经定义了equals()
和hashCode()
,但我的问题还是一样。您还有其他建议吗?
我想知道我的实体是否正确,所以我也问了这个问题:***.com/q/12849545/845220 你能也读一下这个吗?以上是关于休眠:获取太多行的主要内容,如果未能解决你的问题,请参考以下文章