I have a problem with querying Derby database. I am using Hibernate with JPA. Problem is related (probably) to boolean columns. Each query ends with error:
org.hibernate.exception.SQLGrammarException: Comparisons between 'BOOLEAN' and 'INTEGER' are not supported. Types must be comparable. String types must also have matching collation. If collation does not match, a possible solution is to cast operands to force them to the default collation (e.g. SELECT tablename FROM sys.systables WHERE CAST(tablename AS VARCHAR(128)) = 'T1')
Below you may find sample code and configuration. Samples are simplified for easier reading. Here is my JPA entity:
@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 + " ]";
}
}
My JPA query:
SELECT t FROM Task t WHERE deleted = false
My JPA configuration:
<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>
What is wrong? How to fix that? Thanks for any suggestions.
Boolean datatype was added in Derby 10.7, you appear to be using 10.7 or newer so you should use the org.hibernate.dialect.DerbyTenSevenDialect
dialect which adds Boolean support.
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 ;)
Used Rafal's approach but also have to add
@Override
public String toBooleanValueString(boolean bool) {
return bool ? "1" : "0";
}
in my Dialect. Otherwise it doesn't work under Hibernate 4.2.8.
Also I wasn't be able to specify my dialect explicitly in persistence.xml as my app runs against Oracle and Derby. So I've added a dialect resolver for my dialect:
<property name="hibernate.dialect_resolvers" value="...DerbyBoolAsIntDialectResolver"/>
Resolver itself:
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;
}
}
Downgrade didn't helped. Here is valid solution which works for me:
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");
}
}
I guess it is better to configure 'true' and 'false' constants mapping in dialect to Derby data type, but above is good enough for now.
来源:https://stackoverflow.com/questions/10113122/hibernate-derby-comparisons-between-boolean-and-integer-are-not-supported