Good day.
I try to implement mapping of ManyToOne association in a legacy database, such that when there is no association, zero (0) is put into a column, not null.
To do this, I found three-years-old topic on this forum (
Relationship foreign key uses '0' instead of null) where solution was proposed.
It is proposed there to use UserType in conjuction with ManyToOne, as
Quote:
ManyToOneType wraps around the identifier Type. So if you wrote a custom type that mapped null->zero and used it as the identifier type of the associated class, then the many-to-one would see that.
I implemented this with a custom UserType and two annotations over the required field, @ManyToOne and @Type(type="my.ZeroedForeignKeyType"), like this:
Code:
@ManyToOne(optional=true)
@LazyToOne(LazyToOneOption.PROXY)
@Type(type="my.ZeroedForeignKeyType")
@JoinColumn(name="f_ASSOCID")
private MyAssoc myAssoc;
Code:
package my;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public class ZeroedForeignKeyType implements UserType {
public ZeroedForeignKeyType() {
}
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
public Object deepCopy(Object value) throws HibernateException {
if (value == null)
return null;
return new Long(((Long) value).longValue());
}
public Serializable disassemble(Object value) throws HibernateException {
return (Long) value;
}
public boolean equals(Object x, Object y) throws HibernateException {
if (x == null && y == null)
return true;
else if (x == null)
return false;
return x.equals(y);
}
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
public boolean isMutable() {
return true;
}
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
long val = rs.getLong(names[0]);
if (val == 0) {
return null;
}
return val;
}
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (value == null) {
st.setLong(index, 0);
} else {
st.setLong(index, (Long)value);
}
}
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return deepCopy(original);
}
public Class<?> returnedClass() {
return Long.class;
}
public int[] sqlTypes() {
return new int[] {Types.INTEGER};
}
}
Yet my
ZeroedForeignKeyType never gets loaded at all!
I placed breakpoints in its every method, constructor included, and it never gets called. I debugged through Hibernate binding code and found that this annotations set leads to the code seemingly avoiding all possible places where @Type is mentioned at all. Yet the guy in the previous topic was pretty positive of the solution working. What do I get wrong?
I use Hibernate 3.2.5, Hibernate Annotations 3.3.0.
Thanks in advance.