4

我在查询 Derby 数据库时遇到问题。我正在使用带有 JPA 的 Hibernate。问题(可能)与布尔列有关。每个查询都以错误结束:

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

4 回答 4

4

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

于 2012-04-11T22:18:06.160 回答
3

You have to set your boolean as a parameter:

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

Hope it will work for you ;)

于 2012-05-23T08:24:42.100 回答
2

降级没有帮助。这是对我有用的有效解决方案:

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 数据类型,但现在上面已经足够好了。

于 2012-04-21T21:52:51.483 回答
1

使用了 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;
    }
}
于 2013-12-14T12:55:49.067 回答