2012-05-24 17 views
7

Me gustaría utilizar la anotación @Where en Hibernate para eliminar objetos que han sido marcados como "eliminados" por una propiedad booleana en ese objeto. Por ejemplo, el siguiente debe evitar cualquier dirección de borrados de ser cargado por Hibernate:¿Hay alguna manera de evitar que Hibernate corrompa los literales booleanos en @Where annotations?

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

Sin embargo cuando se utiliza una cláusula como deleted=FALSE entonces Hibernate mangle el literal booleano prefijándolo con un nombre de la tabla, lo que provoca que la consulta fallar. Por ejemplo:

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

Lo que esperaba es algo así como (address0_.deleted=FALSE) en lugar de (address0_.deleted=address0_.FALSE).

¿Hay alguna manera de especificar la cláusula @Where o configurar Hibernate para que muestre correctamente el valor booleano?


PS. en cuenta que es posible con algunos bases de datos para especificar el valor booleano como una cadena literal de esta manera:

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

que hará que convierte a (address0_.deleted='FALSE') que funciona muy bien en, por ejemplo, PostgreSQL. Sin embargo, estoy usando HSQLDB para este proyecto, y HSQLDB no parece ser compatible con literales de cadena booleanos. En HSQL consigo la siguiente excepción cuando se utiliza deleted='FALSE':

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

+0

¿Recordó especificar HSQLDB Dialect en la configuración de hibernación? – Affe

+0

Sí, estoy usando 'org.hibernate.dialect.HSQLDialect' y he verificado que Hibernate realmente lo está usando. – gutch

Respuesta

5

he descubierto informes de errores sobre este que han sido resuelto en más de seis años! El rastreador de problemas de Hibernate tiene HHH-1587, HHH-2775 y ANN-647 en el problema.

La solución es crear una clase personalizada que registra dialecto true, false y unknown como palabras clave (estos son los literales booleanos oficiales en la especificación SQL). Esto hace que Hibernate los reconozca como palabras clave y dejen de ponerles prefijos como si fueran columnas.

Aquí es mi clase de dialecto a medida que resolvió el problema para mí:

public class ImprovedHSQLDialect extends HSQLDialect { 

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

Una vez que este dialecto está en uso @Where(clause="deleted=FALSE"), funciona correctamente.

1

Cuando se crea la columna como booleanos en el Defintion mesa, la última HSQLDB soporta WHERE active = TRUE, WHERE active = 'TRUE', así como WHERE active.

Hibernate puede estar creando una columna BIT, en cuyo caso WHERE active = TRUE, WHERE active = B'1' o WHERE active = 1 funcionarán.

Utilice la versión 2.2.8 o superior para estas capacidades.

+0

¿Estás seguro de eso? El error descrito en mi pregunta ocurrió en la última HSQLDB (versión 2.2.8).La documentación actual no menciona ningún soporte para la conversión string-boolean en http://hsqldb.org/doc/guide/sqlgeneral-chapt.html, así que no estoy seguro de que sea una característica de HSQLDB. – gutch

+0

Los documentos no pueden cubrir todas las conversiones posibles. Si la tabla tiene una columna BOOLEAN, entonces todo lo anterior funciona. Hibernate debe crear una columna BIT, en cuyo caso WHERE active = TRUE, WHERE active = B'1 'o WHERE active = 1 funcionará. – fredt

+0

En ese caso, es posible que al especificar el apropiado 'columnDefinition' en la anotación' @ Column' pueda hacerlo funcionar. Pero en lo que a mí respecta, es incorrecto que Hibernate trate una palabra reservada como 'FALSO 'como nombre de columna, así que creo que es una mejor solución usar el método' registerKeyword' como lo describo en mi respuesta: es simple e instantáneamente lo arregla en todos los objetos de Hibernate. – gutch

Cuestiones relacionadas