Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to stop Hibernate from corrupting boolean literals in @Where annotations?

I'd like to use @Where annotation in Hibernate to remove objects which have been marked 'deleted' by a boolean property on that object. For example the following should prevent any deleted addresses from being loaded by Hibernate:

@OneToMany(mappedBy="contact")
@Where(clause="deleted=FALSE")
private Set<Address> addresses; 

However when I use a clause like deleted=FALSE then Hibernate will mangle the boolean literal by prefixing it with a table name, which causes the query to fail. For example:

select ... from address address0_ where  ( address0_.deleted=address0_.FALSE)  and address0_.contact_id=?

What I expected is something like (address0_.deleted=FALSE) instead of (address0_.deleted=address0_.FALSE).

Is there a way to specify the @Where clause or configure Hibernate to correctly output the boolean value?


PS. Note that it is possible with some databases to specify the boolean value as a string literal like this:

@Where(clause="deleted='FALSE'")

That will get converted to (address0_.deleted='FALSE') which works just fine in, for example, PostgreSQL. However I am using HSQLDB for this project, and HSQLDB does not seem to support boolean string literals. On HSQL I get the following exception when using deleted='FALSE':

org.hsqldb.HsqlException: data exception: invalid character value for cast

like image 985
gutch Avatar asked May 24 '12 03:05

gutch


2 Answers

I've discovered bug reports about this which have been unresolved for more than six years! The Hibernate issue tracker has HHH-1587, HHH-2775 and ANN-647 on the problem.

The solution is to create a custom Dialect class which registers true, false and unknown as keywords (these are the official boolean literals in the SQL spec). This causes Hibernate to recognise them as keywords and thus stop prefixing them as if they were columns.

Here's my custom Dialect class which solved the problem for me:

public class ImprovedHSQLDialect extends HSQLDialect {

    public ImprovedHSQLDialect() {
        super();
        registerKeyword("true");
        registerKeyword("false");
        registerKeyword("unknown");
    }
}

Once this dialect is in use, @Where(clause="deleted=FALSE") works correctly.

like image 190
gutch Avatar answered Nov 16 '22 12:11

gutch


When the column is created as BOOLEAN in the table defintion, the latest HSQLDB supports WHERE active = TRUE , WHERE active = 'TRUE' as well as WHERE active.

Hibernate may be creating a BIT column, in which case WHERE active = TRUE, WHERE active = B'1' or WHERE active = 1 will work.

Please use version 2.2.8 or greater for these capabilities.

like image 30
fredt Avatar answered Nov 16 '22 12:11

fredt