I've seen a few base entity implementations before, and the one thing that always kept me from doing it was
@Id @GeneratedValue(strategy=GenerationType.AUTO)
protected Long id;
What if i don't want to auto number rows with a bigint? Maybe i want to use a String or a composite primary key? This lack of flexibilty was a deal breaker for me.
I found a really good implementation of this here, this guy has some good stuff
http://burtbeckwith.com/blog/?p=17 but unfortunately still the auto id. my recent learning all about tricky stuff with generics (lots of fun!) inspired me to take a stab at this.
here's what I've come up with, i think it's pretty good but flaws & criticism is highly encouraged. in a few months i will have millions of subclasses of this thing so it needs to be the best it can be.
first the AbstractEntity class. The primary key type is generic, and we use a custom GenericGenerator where the subclass tells us how to generate it.
log4j is available to all subclasses, we use commons lang for reflective equals & hashcode. this might be a performance issue. you could also do the same for toString, but since i'm using the best web framework ever in stripes,
http://stripes.mc4j.org it likes the id for toString.
we timestamp when the row is updated (might add a seperate one for created), and instead of deleting objects, we soft delete them - mark it as deleted and filter these out in finder methods. see that blog for a very nice spring dao implementation, mine is a combination of that and this gem of an article,
http://www.ibm.com/developerworks/java/ ... icdao.html
Code:
@MappedSuperclass
public abstract class AbstractEntity<PK extends Serializable> implements
Serializable {
protected transient final Log LOG = LogFactory.getLog(getClass());
@Id
@GeneratedValue(generator = IdGen.NAME)
protected PK id;
protected Date timeStamp;
protected boolean deleted;
public AbstractEntity() {
this(null);
}
public AbstractEntity(PK id) {
super();
this.id = id;
}
@Override
public String toString() {
return id.toString();
}
@Override
public boolean equals(final Object that) {
return EqualsBuilder.reflectionEquals(this, that);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
// getters & setters
}
here's a stupid class just to avoid typing those strings everywhere,
Code:
public class IdGen {
public static final String NAME = "CustomIdGenerator";
public static final String MANUAL = "assigned";
public static final String AUTO = "identity";
}
a subclass with an auto long primary key,
Code:
@Entity
@GenericGenerator(name=IdGen.NAME, strategy=IdGen.AUTO)
public class AutoLongPK extends AbstractEntity<Long> {
private static final long serialVersionUID = 1L;
private String prop1;
private String prop2;
// getters & setters
}
and a subclass with a manual string pk,
Code:
@Entity
@GenericGenerator(name=IdGen.NAME, strategy=IdGen.MANUAL)
public class ManualStringPK extends AbstractEntity<String> {
private static final long serialVersionUID = 1L;
private String prop1;
private String prop2;
// getters & setters
}
that is some good stuff, hibernate is the shit! lets get some ideas in here and make this better.
damn i lost a credit for this