Отображение логического с Hibernate - PullRequest
7 голосов
/ 31 мая 2011

У меня проблемы с гибернацией.Недавно я установил свой 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 ]

4 голосов
/ 20 февраля 2012

Для тех, кто столкнулся с той же проблемой, что и я, я использовал комбинацию из двух ответов, опубликованных здесь.

Я реализовал пользовательский тип для обработки моего поля 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, и он работает как шарм:)

4 голосов
/ 01 июня 2011

Если вы не можете изменить тип 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)

см. примеры здесь

удачи:)

3 голосов
/ 31 мая 2011

Вы можете определить свой столбец БД как char(1), а в своем файле отображения Hibernate определите свойство как type="yes_no", которое является логическим типом Java.Они будут отображаться как значения Y и N в БД.

Если вы хотите использовать tiny_int, тогда размер должен быть равен 1, но я не уверен на 100%, как этоотображается в файле HBM.

1 голос
/ 31 мая 2011

попробуйте это:

<property column="opener" name="opener" access="field" />

при условии, что вы получили геттер

 boolean isOpener() ;

и сеттер

void setOpener(boolean b);
0 голосов
/ 03 июня 2011

Это сложно, потому что у вас нет доступа к базе данных. Но это можно сделать с небольшим трудом

Что вам нужно будет сделать, это создать собственный класс типов. Этот класс будет в основном извлекать значение из базы данных (1 или 0) и будет содержать логику, которая возвращает истинный или ложный логический объект.

Вот пример:

http://alenovarini.wikidot.com/mapping-a-custom-type-in-hibernate

Ваше отображение для нового типа будет выглядеть так:

    <typedef class="com.path.to.my.package.CustomBooleanType" name="myBoolType" />

Этот метод классов nullSafeGet вернет ваш логический объект, который будет содержать значение true или false.

поэтому ваше новое отображение будет содержать:

<property column="opener" name="opener" type="myBoolType"/>
0 голосов
/ 31 мая 2011

Вы можете попробовать использовать numeric_boolean как тип:

<property column="opener" name="opener" type="numeric_boolean"/>
...