This is probably a bug!
When i am trying to find my already persisted Entity (Membership with Composite Id ( @IdClass ))
after when my transaction commited it cause
Code:
4:00:20,593 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2] TwoPhaseCoordinator.beforeCompletion - failed for com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple@1f5e42b
javax.persistence.PersistenceException: org.hibernate.HibernateException: identifier of an instance of kz.bee.wx.security.Membership was altered from kz.bee.wx.security.MembershipPk@1a532c to kz.bee.wx.security.MembershipPk@8a7ac2b
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629)
i assume what after calling method em.find() it associates my MembershipPk with found Entity and at sync state it replaces with new MembershipPk.
Here is my sample code
Code:
User u=new User("myuser");
Role r=new Role("myrole");
Group g=new Group("mygroup");
Membership m = new Membership();
m.setUser(u);
m.setRole(r);
m.setGroup(g);
MembershipPk mk = new MembershipPk();
mk.setUser(u);
mk.setRole(r);
mk.setGroup(g);
System.out.println(em.find(m.getClass(), mk));
and my entity is
Code:
package kz.bee.wx.security;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name = "WX_MEMBERSHIP")
@IdClass(MembershipPk.class)
public class Membership {
private User user;
private Role role;
private Group group;
private boolean enabled;
@Id
@ManyToOne
@JoinColumn(name = "USER_NAME_")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Id
@ManyToOne
@JoinColumn(name = "ROLE_NAME_")
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
@Id
@ManyToOne
@JoinColumn(name = "GROUP_NAME_")
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@Column(name = "ENABLED_")
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Transient
public boolean isActive() {
return this.isEnabled() && this.getRole().isEnabled() && this.getGroup().isEnabled();
}
@Override
public String toString() {
return user+":"+role+":"+group;
}
@Override
public boolean equals(Object arg0) {
if (arg0 == this) {
return true;
}
else if (arg0 instanceof Membership) {
return user.getName().equals(((Membership)arg0).user.getName()) &&
role.getName().equals(((Membership)arg0).role.getName()) &&
group.getName().equals(((Membership)arg0).group.getName());
}
return false;
}
@Override
public int hashCode() {
return user.hashCode() ^ role.hashCode() ^ group.hashCode();
}
}
and primary key
Code:
package kz.bee.wx.security;
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Embeddable
public class MembershipPk implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private User user;
private Role role;
private Group group;
@ManyToOne
@JoinColumn(name = "USER_NAME_")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@ManyToOne
@JoinColumn(name = "ROLE_NAME_")
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
@ManyToOne
@JoinColumn(name = "GROUP_NAME_")
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
@Override
public boolean equals(Object arg0) {
if (arg0 == this) {
return true;
}
else if (arg0 instanceof MembershipPk) {
return user.getName().equals(((MembershipPk)arg0).user.getName()) &&
role.getName().equals(((MembershipPk)arg0).role.getName()) &&
group.getName().equals(((MembershipPk)arg0).group.getName());
}
return false;
}
@Override
public int hashCode() {
return user.hashCode() ^ role.hashCode() ^ group.hashCode();
}
}
p.s User, Role and Group are simple classes with name as @Id