2009-07-20 13 views

Respuesta

7

La única manera en que he descubierto cómo hacerlo es tener dos propiedades para mi clase. el booleano para la API de programación que no está incluida en la asignación. Es getter y setter reference una variable char privada que es Y/N. Luego tengo otra propiedad protegida que se incluye en la asignación hibernate y sus getters y setters hacen referencia a la privacidad variable de tipo char directamente.

+1

Tuve que hacer algo similar: cambié el tipo de miembro de Boolean a String. En getters y setters (que obtuvieron y definieron Boolean) escribí el código para convertir Y/N al valor booleano correspondiente. – sengs

+4

La otra respuesta de ChssPly76 es la correcta. – bernardn

+0

@bernardn No, es el mejor. – alexander

128

Hibernate tiene un tipo de integrado "YES_NO" que hacer lo que quiera. se asigna a un CHAR (1) en la columna de la base de datos.

asignación básica: <property name="some_flag" type="yes_no"/>

mapeo de anotación (extensiones de Hibernate):

@Type(type="yes_no") 
public boolean getFlag(); 
+24

Para aquellos que estén interesados, también hay un tipo "true_false" que almacenará "T" o "F". –

+0

Esto funcionó, pero no pude usarlo porque es una anotación específica de hibernación. Gracias por la respuesta. Podría usarlo en un proyecto diferente. – sengs

+0

esto es para hibernate 4 y posterior, eso significa para java 1.6 y posterior. doesnt work for hibernate 3. * –

1

hacer incluso mejor la correlación booleano para S/N, añadir a su configuración de hibernación:

<!-- when using type="yes_no" for booleans, the line below allow booleans in HQL expressions: --> 
<property name="hibernate.query.substitutions">true 'Y', false 'N'</property> 

Ahora se puede use booleanos en HQL, por ejemplo:

"FROM " + SomeDomainClass.class.getName() + " somedomainclass " + 
"WHERE somedomainclass.someboolean = false" 
+0

Esto es global. No es adecuado para propiedades singulares. – maxxyme

0

Hacer de forma genérica JPA utilizando anotaciones getter, el ejemplo siguiente funciona para mí con Hibernate 3.5.4 y Oracle 11g. Tenga en cuenta que el getter y el setter mapeados (getOpenedYnString y setOpenedYnString) son métodos privados. Esos métodos proporcionan la asignación pero todo el acceso programático a la clase está utilizando los métodos getOpenedYn y setOpenedYn.

private String openedYn; 

@Transient 
public Boolean getOpenedYn() { 
    return toBoolean(openedYn); 
} 

public void setOpenedYn(Boolean openedYn) { 
    setOpenedYnString(toYesNo(openedYn)); 
} 

@Column(name = "OPENED_YN", length = 1) 
private String getOpenedYnString() { 
    return openedYn; 
} 

private void setOpenedYnString(String openedYn) { 
    this.openedYn = openedYn; 
} 

Aquí es util la clase con métodos estáticos y toYesNotoBoolean:

public class JpaUtil { 

    private static final String NO = "N"; 
    private static final String YES = "Y"; 

    public static String toYesNo(Boolean value) { 
     if (value == null) 
      return null; 
     else if (value) 
      return YES; 
     else 
      return NO; 
    } 

    public static Boolean toBoolean(String yesNo) { 
     if (yesNo == null) 
      return null; 
     else if (YES.equals(yesNo)) 
      return true; 
     else if (NO.equals(yesNo)) 
      return false; 
     else 
      throw new RuntimeException("unexpected yes/no value:" + yesNo); 
    } 
} 
+0

¿por qué el voto hacia abajo? –

+0

No lo sé, pero corregido lo que pude. – peterh

70

Esto es pura APP sin usar getters/setters. A partir de 2013/2014 es la mejor respuesta sin necesidad de utilizar ningún anotaciones específicas de Hibernate, pero tenga en cuenta esta solución es JPA 2.1, y no estaba disponible cuando se hizo la pregunta primero:

@Entity 
public class Person {  

    @Convert(converter=BooleanToStringConverter.class) 
    private Boolean isAlive;  
    ... 
} 

Y luego:

@Converter 
public class BooleanToStringConverter implements AttributeConverter<Boolean, String> { 

    @Override 
    public String convertToDatabaseColumn(Boolean value) {   
     return (value != null && value) ? "Y" : "N";    
     }  

    @Override 
    public Boolean convertToEntityAttribute(String value) { 
     return "Y".equals(value); 
     } 
    } 

Editar:

La implementación anterior considera algo diferente de carácter "Y", incluyendo null, como false. ¿Es eso correcto? Algunas personas consideran esto incorrecto y creen que null en la base de datos debe ser null en Java.

Pero si vuelve null en Java, se le dará un NullPointerException si el campo es un primitivo booleano. En otras palabras, a menos que algunos de sus campos usen realmente la clase Boolean, es mejor considerar null como false, y usar la implementación anterior.Entonces Hibernate no emitirá ninguna excepción independientemente del contenido de la base de datos.

Y si desea aceptar null y emiten excepciones si el contenido de la base de datos no son estrictamente correcto, entonces supongo que no debe aceptar ningún personajes, aparte de "Y", "N" y null. Consígalo coherente y no acepte ninguna variación como "y", "n", "0" y "1", lo que hará que su vida sea más difícil más adelante. Se trata de una aplicación más estricta:

@Override 
public String convertToDatabaseColumn(Boolean value) { 
    if (value == null) return null; 
    else return value ? "Y" : "N"; 
    } 

@Override 
public Boolean convertToEntityAttribute(String value) { 
    if (value == null) return null; 
    else if (value.equals("Y")) return true; 
    else if (value.equals("N")) return false; 
    else throw new IllegalStateException("Invalid boolean character: " + value); 
    } 

Y sin embargo, otra opción, si desea permitir null en Java, pero no en la base de datos:

@Override 
public String convertToDatabaseColumn(Boolean value) { 
    if (value == null) return "-"; 
    else return value ? "Y" : "N"; 
    } 

@Override 
public Boolean convertToEntityAttribute(String value) { 
    if (value.equals("-") return null; 
    else if (value.equals("Y")) return true; 
    else if (value.equals("N")) return false; 
    else throw new IllegalStateException("Invalid boolean character: " + value); 
    } 
+0

El convertidor muestra la idea, pero por supuesto no funciona. El convertidor usa los valores posibles de 'Y',' N' y 'T'. Tampoco estoy seguro de que uno deba omitir el caso de tener un valor nulo como resultado de una conversión. – Matthias

+0

@Matthias Sí, T era un error tipográfico. Lo arreglé. Gracias. – MarcG

+0

Tuve un problema al utilizar el campo Y/N con JPQL y publiqué una pregunta de seguimiento aquí: http://stackoverflow.com/questions/39581225/unable-to-render-boolean-literal-value-when-using-attributeconverter- for-boole –

0

usando JPA 2.1 convertidores es la mejor solución, sin embargo, si está utilizando una versión anterior de JPA, puedo recomendar una solución más (o solución alternativa). Cree una enumeración llamada BooleanWrapper con 2 valores de T y F y añádale el siguiente método para obtener el valor ajustado: public Boolean getValue() { return this == T; }, asócielo con @Enumerated (EnumType.STRING).

8

Utilicé el concepto de la respuesta publicada por @marcg y funciona muy bien con JPA 2.1. Su código no era del todo correcto, así que publiqué mi implementación en funcionamiento. Esto convertirá los campos de entidad Boolean en una columna de caracteres Y/N en la base de datos.

de mi clase de entidad:

@Convert(converter=BooleanToYNStringConverter.class) 
@Column(name="LOADED", length=1) 
private Boolean isLoadedSuccessfully; 

Mi clase de convertidor:

/** 
* Converts a Boolean entity attribute to a single-character 
* Y/N string that will be stored in the database, and vice-versa 
* 
* @author jtough 
*/ 
public class BooleanToYNStringConverter 
     implements AttributeConverter<Boolean, String> { 

    /** 
    * This implementation will return "Y" if the parameter is Boolean.TRUE, 
    * otherwise it will return "N" when the parameter is Boolean.FALSE. 
    * A null input value will yield a null return value. 
    * @param b Boolean 
    */ 
    @Override 
    public String convertToDatabaseColumn(Boolean b) { 
     if (b == null) { 
      return null; 
     } 
     if (b.booleanValue()) { 
      return "Y"; 
     } 
     return "N"; 
    } 

    /** 
    * This implementation will return Boolean.TRUE if the string 
    * is "Y" or "y", otherwise it will ignore the value and return 
    * Boolean.FALSE (it does not actually look for "N") for any 
    * other non-null string. A null input value will yield a null 
    * return value. 
    * @param s String 
    */ 
    @Override 
    public Boolean convertToEntityAttribute(String s) { 
     if (s == null) { 
      return null; 
     } 
     if (s.equals("Y") || s.equals("y")) { 
      return Boolean.TRUE; 
     } 
     return Boolean.FALSE; 
    } 

} 

Esta variante también es divertido si te gusta emoticonos y está harto y cansado de S/N o T/F en tu base de datos En este caso, su columna de base de datos debe tener dos caracteres en lugar de uno. Probablemente no es un gran problema.

/** 
* Converts a Boolean entity attribute to a happy face or sad face 
* that will be stored in the database, and vice-versa 
* 
* @author jtough 
*/ 
public class BooleanToHappySadConverter 
     implements AttributeConverter<Boolean, String> { 

    public static final String HAPPY = ":)"; 
    public static final String SAD = ":("; 

    /** 
    * This implementation will return ":)" if the parameter is Boolean.TRUE, 
    * otherwise it will return ":(" when the parameter is Boolean.FALSE. 
    * A null input value will yield a null return value. 
    * @param b Boolean 
    * @return String or null 
    */ 
    @Override 
    public String convertToDatabaseColumn(Boolean b) { 
     if (b == null) { 
      return null; 
     } 
     if (b) { 
      return HAPPY; 
     } 
     return SAD; 
    } 

    /** 
    * This implementation will return Boolean.TRUE if the string 
    * is ":)", otherwise it will ignore the value and return 
    * Boolean.FALSE (it does not actually look for ":(") for any 
    * other non-null string. A null input value will yield a null 
    * return value. 
    * @param s String 
    * @return Boolean or null 
    */ 
    @Override 
    public Boolean convertToEntityAttribute(String s) { 
     if (s == null) { 
      return null; 
     } 
     if (HAPPY.equals(s)) { 
      return Boolean.TRUE; 
     } 
     return Boolean.FALSE; 
    } 

} 
+0

¿Es necesario el unboxing 'b.booleanValue()'? –

Cuestiones relacionadas