我在使用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注释。
答案 0 :(得分:7)
看起来你可能正热切地加入某个地方的多对一关系。默认行为是您为数据库返回的每一行获取一个实体。如果您不想更改热切的提取,但想要删除结果中的重复项,则需要使用此ResultTransformer
:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
答案 1 :(得分:2)
@Embeddable 仅表示 MyPK 的列将是我的类中的列。
您的问题可能是@ManyToOne @JoinColumn(name = "property")
,因为它与MyPK中的 “属性 ”相同
答案 2 :(得分:1)
您可以使用此方法在条件上设置此结果来设置最大结果数:setMaxResults(int maxResults)
答案 3 :(得分:1)
主键类需要根据聚合值(qwerty
和property
来定义equals()和hashCode())。很可能在处理ResultSet时,Hibernate没有看到多行中的实体键相等。
从JPA 2.0规范的2.4节(如果它有帮助):
主键类必须定义equals和hashCode方法。价值的语义 这些方法的相等性必须与数据库类型的数据库相等一致 密钥映射到哪个