Configurez hibernate (en utilisant JPA) pour stocker Y / N pour le type booléen au lieu de 0/1

Puis-je configurer JPA / hibernate pour conserver Boolean types Boolean Y/N ? Dans la firebase database (la colonne est définie comme varchar2(1) . Elle les stocke actuellement sous la forme 0/1 . La firebase database est Oracle.

La seule façon dont j’ai compris comment faire est d’avoir deux propriétés pour ma classe. Un comme booléen pour l’API de programmation qui n’est pas inclus dans le mapping. C’est getter et setter font référence à une variable de caractère privé qui est Y / N. J’ai ensuite une autre propriété protégée qui est incluse dans le mappage d’hibernation et ses getters et setters font directement référence à la variable char privée.

Hibernate a un type “yes_no” intégré qui ferait ce que vous voulez. Il correspond à une colonne CHAR (1) de la firebase database.

Mappage de base:

Mappage d’annotation (extensions Hibernate):

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

Ceci est pur JPA sans utiliser des getters / setters. À partir de 2013/2014, c’est la meilleure réponse sans utiliser des annotations spécifiques à Hibernate, mais veuillez noter que cette solution est JPA 2.1 et n’était pas disponible lorsque la question a été posée pour la première fois:

 @Entity public class Person { @Convert(converter=BooleanToSsortingngConverter.class) private Boolean isAlive; ... } 

Et alors:

 @Converter public class BooleanToSsortingngConverter implements AtsortingbuteConverter { @Override public Ssortingng convertToDatabaseColumn(Boolean value) { return (value != null && value) ? "Y" : "N"; } @Override public Boolean convertToEntityAtsortingbute(Ssortingng value) { return "Y".equals(value); } } 

Modifier:

L’implémentation ci-dessus considère que tout ce qui est différent du caractère “Y”, y compris null , est false . Est-ce exact? Certaines personnes considèrent cela comme incorrect et pensent que null dans la firebase database doit être null en Java.

Mais si vous retournez null en Java, cela vous donnera une NullPointerException si votre champ est un booléen primitif . En d’autres termes, à moins que certains de vos champs n’utilisent réellement la classe Boolean, il est préférable de considérer null comme false et d’utiliser l’implémentation ci-dessus. Hibernate n’émettra alors aucune exception, quel que soit le contenu de la firebase database.

Et si vous voulez accepter des exceptions null et émises si le contenu de la firebase database n’est pas ssortingctement correct, alors vous ne devriez accepter aucun caractère en dehors de “Y”, “N” et null . Rendez-le cohérent et n’acceptez aucune variation comme “y”, “n”, “0” et “1”, ce qui rendra votre vie plus difficile plus tard. Ceci est une implémentation plus ssortingcte:

 @Override public Ssortingng convertToDatabaseColumn(Boolean value) { if (value == null) return null; else return value ? "Y" : "N"; } @Override public Boolean convertToEntityAtsortingbute(Ssortingng 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); } 

Et encore une autre option, si vous voulez autoriser null en Java mais pas dans la firebase database:

 @Override public Ssortingng convertToDatabaseColumn(Boolean value) { if (value == null) return "-"; else return value ? "Y" : "N"; } @Override public Boolean convertToEntityAtsortingbute(Ssortingng 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); } 

J’ai utilisé le concept de la réponse publiée par @marcg et cela fonctionne très bien avec JPA 2.1. Son code n’était pas tout à fait correct, alors j’ai posté mon implémentation de travail. Cela convertira Boolean champs d’entité Boolean en une colonne de caractères Y / N dans la firebase database.

De ma classe d’entité:

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

Ma classe de convertisseur:

 /** * Converts a Boolean entity atsortingbute to a single-character * Y/N ssortingng that will be stored in the database, and vice-versa * * @author jtough */ public class BooleanToYNSsortingngConverter implements AtsortingbuteConverter { /** * 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 Ssortingng convertToDatabaseColumn(Boolean b) { if (b == null) { return null; } if (b.booleanValue()) { return "Y"; } return "N"; } /** * This implementation will return Boolean.TRUE if the ssortingng * 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 ssortingng. A null input value will yield a null * return value. * @param s Ssortingng */ @Override public Boolean convertToEntityAtsortingbute(Ssortingng s) { if (s == null) { return null; } if (s.equals("Y") || s.equals("y")) { return Boolean.TRUE; } return Boolean.FALSE; } } 

Cette variante est également amusante si vous aimez les émoticons et que vous en avez assez de Y / N ou T / F dans votre firebase database. Dans ce cas, votre colonne de firebase database doit comporter deux caractères au lieu d’un. Probablement pas un gros problème.

 /** * Converts a Boolean entity atsortingbute to a happy face or sad face * that will be stored in the database, and vice-versa * * @author jtough */ public class BooleanToHappySadConverter implements AtsortingbuteConverter { public static final Ssortingng HAPPY = ":)"; public static final Ssortingng 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 Ssortingng or null */ @Override public Ssortingng convertToDatabaseColumn(Boolean b) { if (b == null) { return null; } if (b) { return HAPPY; } return SAD; } /** * This implementation will return Boolean.TRUE if the ssortingng * is ":)", otherwise it will ignore the value and return * Boolean.FALSE (it does not actually look for ":(") for any * other non-null ssortingng. A null input value will yield a null * return value. * @param s Ssortingng * @return Boolean or null */ @Override public Boolean convertToEntityAtsortingbute(Ssortingng s) { if (s == null) { return null; } if (HAPPY.equals(s)) { return Boolean.TRUE; } return Boolean.FALSE; } } 

Pour faire un meilleur mappage booléen sur Y / N, ajoutez à votre configuration d’hibernation:

  true 'Y', false 'N' 

Maintenant, vous pouvez utiliser des booléens dans HQL, par exemple:

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

Pour le faire d’une manière JPA générique en utilisant les annotations getter, l’exemple ci-dessous fonctionne pour moi avec Hibernate 3.5.4 et Oracle 11g. Notez que le getter et le setter getOpenedYnSsortingng ( getOpenedYnSsortingng et setOpenedYnSsortingng ) sont des méthodes privées. Ces méthodes fournissent le mappage mais tous les access par programme à la classe utilisent les méthodes getOpenedYn et setOpenedYn .

 private Ssortingng openedYn; @Transient public Boolean getOpenedYn() { return toBoolean(openedYn); } public void setOpenedYn(Boolean openedYn) { setOpenedYnSsortingng(toYesNo(openedYn)); } @Column(name = "OPENED_YN", length = 1) private Ssortingng getOpenedYnSsortingng() { return openedYn; } private void setOpenedYnSsortingng(Ssortingng openedYn) { this.openedYn = openedYn; } 

Voici la classe util avec les méthodes statiques toYesNo et toBoolean :

 public class JpaUtil { private static final Ssortingng NO = "N"; private static final Ssortingng YES = "Y"; public static Ssortingng toYesNo(Boolean value) { if (value == null) return null; else if (value) return YES; else return NO; } public static Boolean toBoolean(Ssortingng 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); } } 

L’utilisation des convertisseurs JPA 2.1 est la meilleure solution. Toutefois, si vous utilisez une version antérieure de JPA, je peux vous recommander une solution supplémentaire (ou une solution de contournement). Créez une énumération appelée BooleanWrapper avec 2 valeurs de T et F et ajoutez la méthode suivante pour obtenir la valeur public Boolean getValue() { return this == T; } : public Boolean getValue() { return this == T; } public Boolean getValue() { return this == T; } , mappez-le avec @Enumerated (EnumType.STRING).