Criteria.DISTINCT_ROOT_ENTITY不会阻止重复的对象

时间:2015-10-14 14:07:43

标签: java hibernate orm criteria hibernate-criteria

我有以下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。

我无法切换抓取类型。

我不想把这个列表放进去。

2 个答案:

答案 0 :(得分:2)

没有理由使用DISTINCT_ROOT_ENTITY或类似内容,您只需要:

session.createCriteria(AdminRole.class).list();

如果你得到重复项,那么你真的在数据库中拥有它们。检查直接或通过级联来保存AdminRole的代码。

当从其他实体级联PERSIST / MERGE操作时,请确保将操作级联到持久/分离AdminRole实例,而不是瞬态(新)实例。< / p>

答案 1 :(得分:1)

我的钱是乱搞hashCode / equals覆盖和Hibernate代理。

来自EqualsandHashCode

  

然而,一旦你关闭了Hibernate会话,所有的赌注都会被关闭。 [...]因此,如果你在会话之间保留对象的集合,你将开始经历奇怪的行为(主要是集合中的重复对象)。

首先我会像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();
}