Hi all!
I am trying to implement a custom usertype (org.hibernate.usertype.UserType) to use with my entities and am getting a GenericJDBCException. This is really frustrating. I hope someone can give me some pointers or good tutorials. Thnx
Trying to accomplish:
MyEntity.<MyType>listOfMyTypes;
When flushing session:
org.hibernate.exception.GenericJDBCException: could not insert collection: [foo.bar.TableEntity.listOfMyTypes#20001950] SQL: insert into TABLE_listOfMyTypes (TABLE_ID, MYTYPE_LIST) values (?, ?)
at ...
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1205)
at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:171)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
I do not understand why this is happening. MyType should be a data type to be used by many different entities and is not an entity by it self. The SQL in the error message is suggesting that it is trying to insert each type into the database (but it should only be one column in one entity). The generated sql has severel flaws as there is no table called TABLE_listOfMyTypes. There is however a TABLE with a column called MY_TYPES. The name listOfMyTypes is the entity variable.
What is really bothering me is that before this exception is coming, myUserType is hardly used. What happens is that during loading of the hibernate context, the sqlTypes-method is invoked. Just before the exception, the deepCopy-method is invoked. The nullSafeSet-method that should produce the String for the databse is NOT invoked.
My field:
Code:
@javax.persistence.Column(name = "MYTYPE_LIST", nullable = true)
@org.hibernate.annotations.CollectionOfElements
@org.hibernate.annotations.Type(type = "foo.bar.MyUserType")
private List<foo.bar.MyType> listOfMyTypes = new ArrayList<foo.bar.MyType>();
MyUserType
Code:
public class MyUserType implements UserType {
@Override
public Object assemble(Serializable cached, Object owner) {
return cached;
}
@Override
public Serializable disassemble(Object value) {
return (Serializable) value;
}
@Override
public boolean equals(Object x, Object y) {
return x.equals(y);
}
@Override
public Object deepCopy(Object value) {
return value;
}
@Override
public int hashCode(Object x) {
return x.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
return foo.bar.MyType.createListFrom(rs.getString(names[0])); // this bag is only mapped to one column
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
}
st.setString(index, foo.bar.MyType.createStringFrom(value));
}
@Override
public Object replace(Object original, Object target, Object owner) {
return original;
}
@Override
public Class returnedClass() {
return foo.bar.MyType.class;
}
@Override
public int[] sqlTypes() {
return new int[] {
Types.VARCHAR
};
}
}
Versions:
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-ehcache.version>3.3.1.GA</hibernate-ehcache.version>