Hibernate + Derby: сравнения между «BOOLEAN» и «INTEGER» не поддерживаются.

У меня проблема с запросом базы данных Derby. Я использую Hibernate с JPA. Проблема связана (вероятно) с булевыми столбцами. Каждый запрос заканчивается ошибкой:

org.hibernate.exception.SQLGrammarException: сравнение между 'BOOLEAN' и 'INTEGER' не поддерживается. Типы должны быть сопоставимы. Строковые типы также должны иметь соответствующие параметры сортировки. Если параметры сортировки не совпадают, возможное решение — привести операнды к параметрам сортировки по умолчанию (например, SELECT tablename FROM sys.systables WHERE CAST(tablename AS VARCHAR(128)) = 'T1')

Ниже вы можете найти пример кода и конфигурации. Образцы упрощены для удобства чтения. Вот мой объект JPA:

@Entity
public abstract class Task implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    protected long id;

    @Column
    protected boolean deleted;

    public long getId() {
        return id;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setId(long id) {
        this.id = id;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    @Override
    public int hashCode() {
        return id;
    }

    @Override
    public boolean equals(Object object) {
        if (object == null) {
            return false;
        }

        if (!this.getClass().equals(object.getClass())) {
            return false;
        }

        EntityObject other = (EntityObject) object;

        if (this.id != other.id) {
            return false;
        }

        return true;
    }

    @Override
    public String toString() {
        return "EntityObject[ id=" + id + " ]";
    }
}

Мой JPA-запрос:

SELECT t FROM Task t WHERE deleted = false

Моя конфигурация JPA:

<persistence-unit name="PU1" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/myapp</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
  <property name="hibernate.hbm2ddl.auto" value="update"/>
  <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
</properties>
</persistence-unit>

Что не так? Как это исправить? Спасибо за любые предложения.


person Rafal    schedule 11.04.2012    source источник
comment
Каков тип данных Task.deleted в дерби? Это немного далеко, но, возможно, hibernate.hbm2ddl.auto=update не применяет изменения типа данных.   -  person samlewis    schedule 12.04.2012
comment
Task.deleted является логическим значением в базе данных Derby. Схема базы данных актуальна и синхронизирована с классами сущностей.   -  person Rafal    schedule 12.04.2012


Ответы (4)


Логический тип данных был добавлен в Derby 10.7, вы, похоже, используете 10.7 или новее, поэтому вам следует использовать org.hibernate.dialect.DerbyTenSevenDialect, который добавляет поддержку логических значений.

person samlewis    schedule 11.04.2012
comment
К сожалению, это не помогло. Более того, для обоих диалектов в журналах есть предупреждение: Диалект DerbyDialect устарел; вместо этого используйте один из диалектов конкретной версии. Команда Hibernate уже сообщила о подобной проблеме как об ошибке: bug1 и bug2 Спасибо за помощь - я попробую понизить версию Derby сейчас. - person Rafal; 12.04.2012
comment
Кстати, моя версия Дерби 10.8.1.2. - person Rafal; 12.04.2012

Вы должны установить логическое значение в качестве параметра:

String queryString = "SELECT t FROM Task t WHERE t.deleted = :trueValue";
Query query = entityManager.createQuery(queryString);
query.setParameter("trueValue", true);
query.getResultList();

Надеюсь, это сработает для вас ;)

person Pierre B    schedule 23.05.2012

Даунгрейд не помог. Вот действительное решение, которое работает для меня:

import java.sql.Types;
import org.hibernate.dialect.DerbyTenSevenDialect;

public class DerbyDialect extends DerbyTenSevenDialect {

    public DerbyDialect() {
        // fix Derby dialect boolean data type mapping error
        registerColumnType(Types.BOOLEAN, "INTEGER");
    }
}

Я предполагаю, что лучше настроить сопоставление констант «true» и «false» на диалекте с типом данных Derby, но на данный момент этого достаточно.

person Rafal    schedule 21.04.2012

Использовал подход Рафаля, но также должен добавить

@Override
public String toBooleanValueString(boolean bool) {
    return bool ? "1" : "0";
}

на моем диалекте. В противном случае он не работает в Hibernate 4.2.8.

Также я не смог явно указать свой диалект в файле persistence.xml, так как мое приложение работает с Oracle и Derby. Итак, я добавил преобразователь диалекта для своего диалекта:

<property name="hibernate.dialect_resolvers" value="...DerbyBoolAsIntDialectResolver"/>

Сам резольвер:

public class DerbyBoolAsIntDialectResolver extends AbstractDialectResolver {
    @Override
    protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
        String databaseName = metaData.getDatabaseProductName();
        int databaseMajorVersion = metaData.getDatabaseMajorVersion();

        if ( "Apache Derby".equals( databaseName ) ) {
            final int databaseMinorVersion = metaData.getDatabaseMinorVersion();
            if ( databaseMajorVersion > 10 || ( databaseMajorVersion == 10 && databaseMinorVersion >= 7 ) ) {
                return new DerbyBoolAsIntDialect();
            }
        }
        return null;
    }
}
person Alex Chevelev    schedule 14.12.2013