Reputation: 604
I'm running into trouble with hibernate. I recently set my hbm2ddl to validate, and it has been complaining a lot about wrong datatypes. I have fixed every problem except for booleans.
I have a field opener
in my class, which is mapped as:
<property column="opener" name="opener" type="boolean"/>
The column opener
is a tinyint (4)
and has a value of 1 or 0. So far I've tried changing the types, but to no avail. I have also tried using the following setting in my hibernate.cfg:
<property name="hibernate.query.substitutions">true 1, false 0</property>
But I am still getting the same error. What am I doing wrong?
org.hibernate.HibernateException: Wrong column type: opener, expected: bit
at org.hibernate.mapping.Table.validateColumns(Table.java:261)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1083)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:116)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:317)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
note: I have no access to the database.
Upvotes: 7
Views: 38581
Reputation: 604
For anyone who ran into the same trouble as me, I used a combination of two answers posted here.
I implemented a custom usertype to handle my tinyint field:
public class TinyIntegerToBoolean implements UserType {
public int[] sqlTypes() {
return new int[]{Types.TINYINT};
}
public Class returnedClass() {
return Boolean.class;
}
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner) throws HibernateException, SQLException {
return (rs.getByte(names[0]) != 0);
}
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor si) throws HibernateException, SQLException {
st.setByte(index, Boolean.TRUE.equals(value) ? (byte) 1 : (byte) 0);
}
/* boilerplate... */
public boolean isMutable() {
return false;
}
public boolean equals(Object x, Object y) throws HibernateException {
if (x == null || y == null) {
return false;
} else {
return x.equals(y);
}
}
public int hashCode(Object x) throws HibernateException {
assert (x != null);
return x.hashCode();
}
public Object deepCopy(Object value) throws HibernateException {
return value;
}
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
}
Then I added the following to my mappings:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<typedef class="com.test.model.TinyIntegerToBoolean" name="tinyint_boolean"/>
</hibernate-mapping>
Then in my opener field I use type=tinyint_boolean
and it works like a charm :)
Upvotes: 4
Reputation: 809
If you can't change your SQL type in your table, i recommend you to do this :
<property name="opener" column="opener" type="path.to.your.package.YourClassUserType"/>
and create your class :
import org.hibernate.usertype.UserType;
public class YourClassUserType implements UserType{
...
}
you have to implement methods from the interface UserType. The implementation will transform byte to boolean (because a TINYINT is mapped in byte in Java)
see examples here
good luck :)
Upvotes: 4
Reputation: 926
This is a tricky one because you have no access to the database. But it can be done with a bit of work
What you will need to do is create a custom type class. This class will basically retrieve the value from the database (1 or 0) and it will contain logic that returns either a true or false Boolean object.
Here is an example:
http://alenovarini.wikidot.com/mapping-a-custom-type-in-hibernate
your mapping for your new type will look like:
<typedef class="com.path.to.my.package.CustomBooleanType" name="myBoolType" />
That classes nullSafeGet method will return your Boolean object that will contain true or false.
so your new mapping will contain:
<property column="opener" name="opener" type="myBoolType"/>
Upvotes: 0
Reputation: 242786
You can try to use numeric_boolean
as a type:
<property column="opener" name="opener" type="numeric_boolean"/>
Upvotes: 1
Reputation: 809
try this :
<property column="opener" name="opener" access="field" />
assuming that you got a getter
boolean isOpener() ;
and a setter
void setOpener(boolean b);
Upvotes: 1
Reputation: 795
You can define your DB column as a char(1)
and in your Hibernate mapping file define the property as type="yes_no"
, which is a Java Boolean type. These will appear as Y
and N
values in the DB.
If you want to use tiny_int
then the size will have to be 1, but I'm not 100% sure how this is mapped in the HBM file.
Upvotes: 3