2012-04-11 1 views
4

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

org.hibernate.exception.SQLGrammarException: Сравнение между «BOOLEAN» и «INTEGER» не поддерживается. Типы должны быть сопоставимы. Строковые типы также должны иметь соответствующую сортировку. Если параметры сортировки не совпадают, то возможным решением является приведение операнды, чтобы заставить их сортировки по умолчанию (например ВЫБРАТЬ имя_таблицы FROM sys.systables WHERE CAST (имя_таблицы 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> 

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

+0

Какого типа данных Task.deleted в дерби? Это немного длинный снимок, но, возможно, hibernate.hbm2ddl.auto = update не применяет изменения типа данных. – samlewis

+0

Task.deleted является логическим в базе данных Derby. Схема базы данных обновляется до уровня сущностей. – Rafal

ответ

0

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

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"); 
    } 
} 

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

4

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

+0

К сожалению, это не помогло. Более того, для диалектов в журналах есть предупреждение: «Диалект DerbyDialect устарел, вместо этого используйте один из диалектов, специфичных для версии». Аналогичная проблема уже упоминается как ошибка для команды Hibernate: [bug1] (https://hibernate.onjira.com/browse/HHH-6961?page=com.atlassian.jirafisheyeplugin%3Afisheye-issuepanel) и [bug2] (https : //hibernate.onjira.com/browse/HHH-7059) Спасибо за помощь. Сейчас я попробую понизить Derby. – Rafal

+0

BTW, моя версия Derby - 10.8.1.2 – Rafal

3

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

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

Надеется, что она будет работать для вас;)

2

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

@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; 
    } 
}