Criteria.DISTINCT_ROOT_ENTITY 不防止重复的对象
Criteria.DISTINCT_ROOT_ENTITY doesn't prevent duplicated objects
我有以下dao方法:
@Override
public List<AdminRole> findAll() {
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(AdminRole.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return criteria.list();
}
实际上我想从数据库中检索所有条目。
有时我会看到重复的内容。当我使用 AdminRole 添加用户时会发生这种情况。
我读到当我使用 EAGER
获取类型时是可能的,这应该是修复添加以下行:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
但这对我没有帮助。
我的映射:
@Entity
@Table(name = "terminal_admin_role")
public class AdminRole {
@Id
@Column(name = "role_id", nullable = false, unique = true)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id")
@SequenceGenerator(name = "user_id", sequenceName = "user_id")
private Long adminId;
@Column(name = "role")
private String role;
public AdminRole(String role) {
this.role = role;
}
public AdminRole() {
}
// get set
@Override
public String toString(){
return role;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AdminRole)) {
return false;
}
AdminRole adminRole = (AdminRole) o;
if (!role.equals(adminRole.role)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return role.hashCode();
}
}
和
@Entity
@Table(name = "terminal_admin")
public class TerminalAdmin {
@ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinTable(name = "admin_role", joinColumns = {
@JoinColumn(name = "admin_id", nullable = false) },
inverseJoinColumns = { @JoinColumn(name = "role_id",
nullable = false) })
private Set<AdminRole> adminRoles;
//...
}
P.S.
我无法切换获取类型。
我不想将此列表放入集合中。
没有理由使用 DISTINCT_ROOT_ENTITY
或类似的东西,您只需要:
session.createCriteria(AdminRole.class).list();
如果你得到重复项,那么你确实在数据库中有它们。检查直接或通过从其他实体级联保存 AdminRole
s 的代码。
当从其他实体级联 PERSIST
/MERGE
操作时,确保操作级联到 persistent/detached AdminRole
实例,而不是瞬态(新) 一个。
我的钱花在搞乱 hashCode/equals 覆盖和 Hibernate 代理上。
However, once you close the Hibernate session, all bets are off. [...] Hence, if you keep collections of objects around between sessions, you will start to experience odd behavior (duplicate objects in collections, mainly).
首先,我会像这样使用 org.apache.commons.lang3
(这对于 Hibernate 实体来说显然太昂贵了,但与它们一起工作正常,如果它工作应该验证我的直觉):
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
如果这行得通,您可以采用像这样的更便宜的方法:
@Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder();
hcb.append(role);
return hcb.toHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof AdminRole)) {
return false;
}
AdminRole that = (AdminRole) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(role, that.role);
return eb.isEquals();
}
我有以下dao方法:
@Override
public List<AdminRole> findAll() {
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(AdminRole.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return criteria.list();
}
实际上我想从数据库中检索所有条目。
有时我会看到重复的内容。当我使用 AdminRole 添加用户时会发生这种情况。
我读到当我使用 EAGER
获取类型时是可能的,这应该是修复添加以下行:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
但这对我没有帮助。
我的映射:
@Entity
@Table(name = "terminal_admin_role")
public class AdminRole {
@Id
@Column(name = "role_id", nullable = false, unique = true)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id")
@SequenceGenerator(name = "user_id", sequenceName = "user_id")
private Long adminId;
@Column(name = "role")
private String role;
public AdminRole(String role) {
this.role = role;
}
public AdminRole() {
}
// get set
@Override
public String toString(){
return role;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof AdminRole)) {
return false;
}
AdminRole adminRole = (AdminRole) o;
if (!role.equals(adminRole.role)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return role.hashCode();
}
}
和
@Entity
@Table(name = "terminal_admin")
public class TerminalAdmin {
@ManyToMany(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinTable(name = "admin_role", joinColumns = {
@JoinColumn(name = "admin_id", nullable = false) },
inverseJoinColumns = { @JoinColumn(name = "role_id",
nullable = false) })
private Set<AdminRole> adminRoles;
//...
}
P.S.
我无法切换获取类型。
我不想将此列表放入集合中。
没有理由使用 DISTINCT_ROOT_ENTITY
或类似的东西,您只需要:
session.createCriteria(AdminRole.class).list();
如果你得到重复项,那么你确实在数据库中有它们。检查直接或通过从其他实体级联保存 AdminRole
s 的代码。
当从其他实体级联 PERSIST
/MERGE
操作时,确保操作级联到 persistent/detached AdminRole
实例,而不是瞬态(新) 一个。
我的钱花在搞乱 hashCode/equals 覆盖和 Hibernate 代理上。
However, once you close the Hibernate session, all bets are off. [...] Hence, if you keep collections of objects around between sessions, you will start to experience odd behavior (duplicate objects in collections, mainly).
首先,我会像这样使用 org.apache.commons.lang3
(这对于 Hibernate 实体来说显然太昂贵了,但与它们一起工作正常,如果它工作应该验证我的直觉):
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
如果这行得通,您可以采用像这样的更便宜的方法:
@Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder();
hcb.append(role);
return hcb.toHashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof AdminRole)) {
return false;
}
AdminRole that = (AdminRole) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(role, that.role);
return eb.isEquals();
}