Отображение логического с Hibernate
У меня проблемы с гибернацией. Недавно я установил мой hbm2ddl для проверки, и он много жаловался на неправильные типы данных. Я исправил все проблемы, кроме логических.
У меня есть поле opener
в моем классе, который отображается как:
<property column="opener" name="opener" type="boolean"/>
Колонка opener
это tinyint (4)
и имеет значение 1 или 0. До сих пор я пытался изменить типы, но безрезультатно. Я также попытался использовать следующие настройки в моем hibernate.cfg:
<property name="hibernate.query.substitutions">true 1, false 0</property>
Но я все еще получаю ту же ошибку. Что я делаю неправильно?
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)
примечание: у меня нет доступа к базе данных.
6 ответов
Если вы не можете изменить тип SQL в своей таблице, я рекомендую вам сделать это:
<property name="opener" column="opener" type="path.to.your.package.YourClassUserType"/>
и создайте свой класс:
import org.hibernate.usertype.UserType;
public class YourClassUserType implements UserType{
...
}
Вы должны реализовать методы из интерфейса UserType. Реализация преобразует байт в логическое значение (поскольку TINYINT отображается в байтах в Java)
удачи:)
Для тех, кто столкнулся с той же проблемой, что и я, я использовал комбинацию из двух ответов, размещенных здесь.
Я реализовал пользовательский тип для обработки моего поля tinyint:
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;
}
}
Затем я добавил следующее в мои отображения:
<?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>
Тогда в моем открывающем поле я использую type=tinyint_boolean
и это работает как шарм:)
Вы можете определить свой столбец БД как char(1)
и в вашем файле отображения Hibernate определите свойство как type="yes_no"
, который является логическим типом Java. Это будет выглядеть как Y
а также N
значения в БД.
Если вы хотите использовать tiny_int
тогда размер должен быть равен 1, но я не уверен на 100%, как это отображается в файле HBM.
Попробуй это:
<property column="opener" name="opener" access="field" />
при условии, что вы получили добытчик
boolean isOpener() ;
и сеттер
void setOpener(boolean b);
Вы можете попробовать использовать numeric_boolean
как тип:
<property column="opener" name="opener" type="numeric_boolean"/>
Это сложно, потому что у вас нет доступа к базе данных. Но это может быть сделано с небольшим количеством работы
Что вам нужно будет сделать, это создать класс пользовательского типа. Этот класс будет в основном извлекать значение из базы данных (1 или 0) и будет содержать логику, которая возвращает истинный или ложный логический объект.
Вот пример:
http://alenovarini.wikidot.com/mapping-a-custom-type-in-hibernate
Ваше отображение для вашего нового типа будет выглядеть так:
<typedef class="com.path.to.my.package.CustomBooleanType" name="myBoolType" />
Этот метод классов nullSafeGet вернет ваш логический объект, который будет содержать истину или ложь.
поэтому ваше новое отображение будет содержать:
<property column="opener" name="opener" type="myBoolType"/>