¿Puedo configurar JPA/Hibernate para persistir Boolean
tipos como Y/N
? En la base de datos (la columna se define como varchar2(1)
. Actualmente los almacena como 0/1
. La base de datos es Oracle.Configurar Hibernate (usando JPA) para almacenar Y/N para tipo Boolean en lugar de 0/1
Respuesta
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.
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();
Para aquellos que estén interesados, también hay un tipo "true_false" que almacenará "T" o "F". –
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
esto es para hibernate 4 y posterior, eso significa para java 1.6 y posterior. doesnt work for hibernate 3. * –
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"
Esto es global. No es adecuado para propiedades singulares. – maxxyme
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 toYesNo
toBoolean
:
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);
}
}
¿por qué el voto hacia abajo? –
No lo sé, pero corregido lo que pude. – peterh
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);
}
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
@Matthias Sí, T era un error tipográfico. Lo arreglé. Gracias. – MarcG
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 –
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).
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;
}
}
¿Es necesario el unboxing 'b.booleanValue()'? –
- 1. Almacenar objetos en columnas con Hibernate JPA
- 2. Hibernate JPA, MySQL y TinyInt (1) para booleana en lugar de bits o carbón
- 3. Hibernate Query Hints para JPA
- 4. Hibernate o EclipseLink para JPA?
- 5. ¿Es posible hacer la conversión de tipo (de boolean a yes_no) en JPA puro?
- 6. ¿Cómo configurar JPA para usar JNDI?
- 7. Usando SELECT para la evaluación BOOLEAN simple
- 8. Spring + Hibernate + JPA
- 9. Compatibilidad con JPA/Hibernate para la migración?
- 10. JPA o Hibernate para Java ¿Persistencia?
- 11. Usando enum vs Boolean?
- 12. Configurar cómo unmarshalls de JAXB boolean
- 13. Configurar las aplicaciones Spring JPA con Hibernate para pruebas unitarias (carga lenta)
- 14. Hibernate (JPA) múltiple @OneToMany para el mismo modelo
- 15. ¿Utiliza siempre contenedores de objetos primitivos para JPA @Id en lugar de tipo primitivo?
- 16. Java: almacenar de manera eficiente boolean [32]?
- 17. Cómo obtener Spring JPA, Hibernate y OSGi para jugar bien?
- 18. Cuándo usar Hibernate/JPA/Toplink?
- 19. ¿Cómo anulo la estrategia GenerationType usando anotaciones de Hibernate/JPA?
- 20. JBoss 5.1: Hibernate con JPA
- 21. JPA/Hibernate Identificación Embedded
- 22. proveedor JPA 2.0 Hibernate
- 23. separan entidades JPA de Hibernate específica ajustes
- 24. jpa hibernate compilación de clave externa compuesta
- 25. Usando DISTINCT en JPA
- 26. Confusión entre JPA e Hibernate en cascada
- 27. JPA Hibernate DBCP Tomcat OutOfMemory
- 28. Diferencia Hibernate 3.5/JPA 2.0
- 29. Hibernate: Crear tablas Mysql InnoDB en lugar de MyISAM
- 30. Cómo configurar Json.NET ContractSerializer para un cierto tipo específico en lugar de globalmente?
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
La otra respuesta de ChssPly76 es la correcta. – bernardn
@bernardn No, es el mejor. – alexander