【问题标题】:Hibernate + Derby: Comparisons between 'BOOLEAN' and 'INTEGER' are not supportedHibernate + Derby:不支持“BOOLEAN”和“INTEGER”之间的比较
【发布时间】:2012-04-24 04:22:10
【问题描述】:

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

怎么了?如何解决?感谢您的任何建议。

【问题讨论】:

  • derby中Task.deleted的数据类型是什么?这有点远,但也许 hibernate.hbm2ddl.auto=update 没有应用数据类型更改。
  • Task.deleted 在 Derby 数据库中是布尔值。数据库架构与实体类同步。

标签: java hibernate jpa derby


【解决方案1】:

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

【讨论】:

  • 不幸的是,这没有帮助。更重要的是,这两种方言在日志中都有警告:“DerbyDialect 方言已被弃用;请改用其中一种特定于版本的方言”。类似的问题已作为错误报告给 Hibernate 团队:bug1bug2 感谢您的帮助 - 我现在将尝试降级 Derby。
  • 顺便说一句,我的 Derby 版本是 10.8.1.2
【解决方案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 数据类型,但目前以上已经足够了。

【讨论】:

    【解决方案3】:

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

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

    希望它对你有用;)

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多