I am trying to map a table that contains a composite key structure of a surrogate-key and an effective date.
Searching through the Hibernate forums it appears that the only solution is to use a CompositeUserType that will allow one to map a table that uses generated identities:
http://forum.hibernate.org/viewtopic.php?t=969576
Executing my initial attempt at this, the id returned is still 0. It seems that Hibernate is ignoring my @Type annotation. Has anyone had any luck using CompositeUserType to help with Composite Keys containing generated identities? I understand that the Hibernate folks frown on this, but I cannot come up with an elegant solution for effective dated objects (id + eff_dt).
@Entity
public class TemplateObject implements Serializable {
private TemplateObjectPk templateObjectPk;
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="templateObjectId", column=@Column(name="template_object_id", nullable=false)),
@AttributeOverride(name="effDate", column=@Column(name="eff_dt", nullable=false))
})
@Type(type="MyTestUserType")
@Columns(columns = {
@Column(name="template_object_id"),
@Column(name="eff_dt")
})
public TemplateObjectPk getTemplateObjectPk() {
return templateObjectPk;
}
public void setTemplateObjectPk(TemplateObjectPk templateObjectPk) {
this.templateObjectPk = templateObjectPk;
}
@Embeddable
public class TemplateObjectPk implements Serializable {
private int templateObjectId;
private Date effDate;
@Column(name="template_object_id")
public int getTemplateObjectId() {
return templateObjectId;
}
@Column(name="eff_dt")
public Date getEffDate() {
return effDate;
}
}
public class MyTestUserType implements CompositeUserType {
public Class returnedClass() {
return TemplateObjectPk.class;
}
public boolean equals(Object x, Object y) {
if(x == y) return true;
if((x == null) || (y == null)) return false;
return x.equals(y);
}
public Object replace(Object x, Object y, SessionImplementor session, Object owner) {
/* Have no idea what to put in here! */
return x;
}
public int hashCode(Object x) {
int hash = 1;
hash = hash * 31 + new Integer(((TemplateObjectPk)x).getTemplateObjectId()).hashCode();
hash = hash * 31 + (((TemplateObjectPk)x).getEffDate() == null ? 0 : ((TemplateObjectPk)x).getEffDate().hashCode());
return hash;
}
public Object deepCopy(Object x) {
if (x==null) return null;
return new TemplateObjectPk(((TemplateObjectPk)x).getTemplateObjectId(), ((TemplateObjectPk)x).getEffDate());
}
public boolean isMutable() { return true; }
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
Integer templateObjectId = (Integer)Hibernate.INTEGER.nullSafeGet(rs, names[0]);
java.sql.Date effDate = (java.sql.Date)Hibernate.DATE.nullSafeGet(rs, names[1]);
if(templateObjectId == null && effDate == null) return null;
if(effDate == null) return new TemplateObjectPk(templateObjectId, new java.util.Date());
return new TemplateObjectPk(templateObjectId, effDate);
}
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
TemplateObjectPk templateObjectPk = (value==null) ? new TemplateObjectPk() : (TemplateObjectPk)value;
Hibernate.INTEGER.nullSafeSet(st, new Integer(templateObjectPk.getTemplateObjectId()), index);
Hibernate.DATE.nullSafeSet(st, new java.sql.Date(templateObjectPk.getEffDate().getTime()), index+1);
}
public String[] getPropertyNames() {
return new String[] {"template_object_id", "eff_dt" };
}
public Type[] getPropertyTypes() {
return new Type[] {Hibernate.INTEGER, Hibernate.DATE};
}
public Object getPropertyValue(Object component, int property) {
if(property == 0) return new Integer(((Integer)component).intValue());
if(property == 1) return new java.sql.Date(((java.util.Date)component).getTime());
return null;
}
public void setPropertyValue(Object component, int property, Object value) {
TemplateObjectPk templateObjectPk = (TemplateObjectPk)component;
if(property == 0) templateObjectPk.setTemplateObjectId((Integer)value);
else if(property == 1) templateObjectPk.setEffDate((java.sql.Date)value);
}
public Object assemble(Serializable cached, SessionImplementor session, Object owner) {
return deepCopy(cached);
}
public Serializable disassemble(Object value, SessionImplementor session) {
return (Serializable) deepCopy(value);
}