I aggree with gschadow on the use of UUIDs.
To be more precise: the all problem comes with mutability of the
hashCode and equals functions, in conjunction with the behavior of
(hashed or not) collections.
There are two options:
1. Use UUIDs as primary key (NOT generated by Hibernate) and implements
hashCode and equals functions as relying on object identity:
(a la EJB3...)
@MappedSuperclass
public abstract class BaseEntity implements java.io.Serializable {
@Id
private String id; // Could be a numeric type...
public BaseEntity() {
this.id = java.util.UUID.randomUUID().toString()
}
...
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object o) {
return (o == this || (o instanceof BaseEntity &&
id.equals(((BaseEntity)o).id));
}
}
Whether this kind of enitity is saved or not, hashCode value will be
always the same.
2. (if you worry about primary key efficiency) Use UUIDs as persistent
immutable field:
@MappedSuperclass
public abstract class BaseEntity implements java.io.Serializable {
@Column(name="__UUID__", unique=true, nullable=false,
updatable=false, length = 36)
private String internalUUID;
@Id @Generated
private Integer id;
public BaseEntity() {
this.internalUUID = java.util.UUID.randomUUID().toString()
}
...
@Override
public int hashCode() {
return internalUUID.hashCode();
}
@Override
public boolean equals(Object o) {
return (o == this || (o instanceof BaseEntity &&
internalUUID.equals(((BaseEntity)o).internalUUID));
}
}
This solution is even better because primary key is an efficient numeric
type and you can completly hide internalUUID for inherited classes.
Whatever is your choice, you still have the ability to override those
methods to fit special purpose... |