Hibernate + Derby:不支持“BOOLEAN”和“INTEGER”之间的比较

时间:2012-04-11 20:06:31

标签: java hibernate jpa derby

我在查询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>

有什么问题?如何解决?感谢您的任何建议。

4 个答案:

答案 0 :(得分:4)

在Derby 10.7中添加了布尔数据类型,您似乎使用了10.7或更新版本,因此您应该使用添加布尔支持的org.hibernate.dialect.DerbyTenSevenDialect方言。

答案 1 :(得分:3)

您必须将布尔值设置为参数:

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

希望它对你有用;)

答案 2 :(得分:2)

使用Rafal的方法,但也必须添加

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

在我的方言中。否则它在Hibernate 4.2.8下无法正常工作。

此外,当我的应用程序针对Oracle和Derby运行时,我无法在persistence.xml中明确指定我的方言。所以我为我的方言添加了一个方言解析器:

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

答案 3 :(得分: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");
    }
}

我想最好将dialect中的'true'和'false'常量映射到Derby数据类型,但现在上面已经足够了。