I have following dao method:
@Override
public List<AdminRole> findAll() {
Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(AdminRole.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
return criteria.list();
}
Actually I want to retrieve all entries from database.
Sometimes I see duplicates. This happens when I add user with AdminRole.
I have read that it is possible when I use EAGER
fetch type and this should be fix adding following line:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
But this doesn't help me.
my mapping:
@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();
}
}
and
@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;
//...
}
I cannot switch fetch type.
I don't want to put this list into set.
There is no reason to use DISTINCT_ROOT_ENTITY
or anything similar, all you need is:
session.createCriteria(AdminRole.class).list();
If you get duplicates, then you really have them in the database. Check the code which saves AdminRole
s either directly or by cascading from other entities.
When cascading PERSIST
/MERGE
operations from other entities, make sure that the operation is cascaded to a persistent/detached AdminRole
instance, not to a transient (new) one.
My money's on messing with hashCode/equals overrides and Hibernate proxies.
From EqualsandHashCode
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).
First I'd use org.apache.commons.lang3
like so (it's obviously way too expensive for Hibernate entities but works ok w/ them and if it works that should validate my hunch):
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);
}
If this works you could go with a less expensive approach like so:
@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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With