【问题标题】:Criteria.DISTINCT_ROOT_ENTITY doesn't prevent duplicated objectsCriteria.DISTINCT_ROOT_ENTITY 不会阻止重复的对象
【发布时间】:2016-01-12 16:15:00
【问题描述】:

我有以下 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 fetch 类型时它是可能的,这应该可以修复添加以下行:

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;      
    //...
}

附言

我无法切换获取类型。

我不想将此列表放入集合中。

【问题讨论】:

  • 我认为那是不同的,只是因为用户对象值不同。 AdminRole 将指向许多用户对象,因此具有相同值的 AdminRole 对象作为查询的结果出现,因为每个对象都有自己的用户对象并且用户对象值不同。
  • @Ry Kannan 你能建议解决问题的方法吗?
  • 我认为您应该添加要选择不同的字段。 [链接]:(stackoverflow.com/questions/5196243/…)
  • “有时”是什么意思?您添加了一个具有管理员角色的用户,然后您在执行查询时总是看到重复?
  • @Dragan Bozanovic 实际上你是对的

标签: java hibernate orm criteria hibernate-criteria


【解决方案1】:

没有理由使用DISTINCT_ROOT_ENTITY 或类似的东西,你只需要:

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

如果你得到重复,那么你真的有它们在数据库中。检查保存AdminRoles 的代码,直接或从其他实体级联。

从其他实体级联PERSIST/MERGE 操作时,请确保该操作级联到持久/分离的AdminRole 实例,而不是临时(新)实例。

【讨论】:

  • 我检查了数据库,但没有找到重复项
  • 插入 TerminalAdmin 时实际上与复制角色有关的问题
【解决方案2】:

我的钱花在搞乱 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();
}

【讨论】:

  • 你仍然可以在 hashCode/equals 方法中使用 getter,不需要反射
  • @VasilyLiaskovsky 你是对的,但我只提到了使用 apache.common 的反射帮助器进行 hashCode/equals 覆盖以确认我的预感的快速而肮脏的方法......
  • @Filip 第一个解决方案不会改变什么
猜你喜欢
  • 1970-01-01
  • 2013-02-27
  • 2015-05-21
  • 2020-06-30
  • 1970-01-01
  • 2019-03-07
  • 1970-01-01
  • 2018-11-21
  • 2014-09-21
相关资源
最近更新 更多