Има ли начин да спрете Hibernate да поврежда булевите литерали в анотациите @Where?

Бих искал да използвам анотация @Where в Hibernate, за да премахна обекти, които са маркирани като „изтрити“ от булево свойство на този обект. Например следното трябва да предотврати зареждането на изтрити адреси от Hibernate:

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

Когато обаче използвам клауза като deleted=FALSE, тогава Hibernate ще обезобрази булевия литерал, като го постави като префикс с име на таблица, което води до неуспех на заявката. Например:

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

Това, което очаквах, е нещо като (address0_.deleted=FALSE) вместо (address0_.deleted=address0_.FALSE).

Има ли начин да посочите клаузата @Where или да конфигурирате Hibernate за правилно извеждане на булевата стойност?


PS. Обърнете внимание, че е възможно с някои бази данни да укажете булевата стойност като низов литерал по този начин:

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

Това ще бъде преобразувано в (address0_.deleted='FALSE'), което работи добре в, например, PostgreSQL. Въпреки това използвам HSQLDB за този проект и HSQLDB изглежда не поддържа булеви низови литерали. В HSQL получавам следното изключение, когато използвам deleted='FALSE':

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


person gutch    schedule 24.05.2012    source източник
comment
Запомнихте ли да посочите HSQLDB Dialect в настройката за хибернация?   -  person Affe    schedule 24.05.2012
comment
Да, използвам org.hibernate.dialect.HSQLDialect и проверих дали Hibernate действително го използва.   -  person gutch    schedule 24.05.2012


Отговори (2)


Открих доклади за грешки за това, които не са разрешени повече от шест години! Инструментът за проследяване на проблеми в Hibernate има HHH-1587, HHH-2775 и ANN-647 по проблема.

Решението е да се създаде персонализиран клас Dialect, който регистрира true, false и unknown като ключови думи (това са официалните булеви литерали в спецификацията на SQL). Това кара Hibernate да ги разпознае като ключови думи и по този начин да спре да ги поставя като префикс, сякаш са колони.

Ето моя персонализиран клас Dialect, който реши проблема за мен:

public class ImprovedHSQLDialect extends HSQLDialect {

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

След като този диалект се използва, @Where(clause="deleted=FALSE") работи правилно.

person gutch    schedule 24.05.2012
comment
Изглежда, че HHH-1587 и ANN-647 са коригирани междувременно. Е, изминаха още шест години, откакто публикувахте този отговор :-) - person Attila Csipak; 23.03.2018

Когато колоната е създадена като BOOLEAN в дефиницията на таблицата, най-новата HSQLDB поддържа WHERE active = TRUE, WHERE active = 'TRUE', както и WHERE active.

Hibernate може да създава колона BIT, в който случай WHERE active = TRUE, WHERE active = B'1' или WHERE active = 1 ще работят.

Моля, използвайте версия 2.2.8 или по-нова за тези възможности.

person fredt    schedule 24.05.2012
comment
Сигурен ли си в това? Грешката, описана в моя въпрос, възникна на най-новата HSQLDB (версия 2.2.8). В текущата документация не се споменава никаква поддръжка за преобразуване на низови булеви стойности в hsqldb.org/doc /guide/sqlgeneral-chapt.html така че не съм убеден, че това е функция на HSQLDB. - person gutch; 25.05.2012
comment
Документите не могат да покрият всички възможни реализации. Ако таблицата има колона BOOLEAN, тогава всичко по-горе работи. Hibernate трябва да създава колона BIT, в който случай WHERE active = TRUE, WHERE active = B'1' или WHERE active = 1 ще работи. - person fredt; 25.05.2012
comment
В този случай е възможно посочването на подходящия columnDefinition в анотацията @Column да го накара да работи. Но що се отнася до мен, не е правилно Hibernate да третира запазена дума като FALSE като име на колона, така че мисля, че е по-добро решение да се използва методът registerKeyword, както описвам в отговора си — той е прост и незабавно го коригира във всички Обекти в хибернация. - person gutch; 28.05.2012