2009-07-20 5 views

Répondre

7

La seule façon dont j'ai compris comment faire cela est d'avoir deux propriétés pour ma classe. le booléen pour l'API de programmation qui n'est pas inclus dans le mapping C'est getter et setter qui référencent une variable char privée qui est Y/N. J'ai alors une autre propriété protégée qui est incluse dans le mapping hibernate et ses getters et setters font référence au private variables Type de caractères directement.

+1

Je devais faire quelque chose de similaire - J'ai changé le type du membre de Boolean à String. Dans les getters et setters (qui ont obtenu et mis Boolean) j'ai écrit le code pour convertir Y/N à la valeur booléenne correspondante. – sengs

+4

L'autre réponse de ChssPly76 est la bonne. – bernardn

+0

@bernardn Non, c'est le meilleur. – alexander

128

Hibernate a intégré "yes_no" qui ferait ce que vous voulez. Il mappé à une colonne CHAR (1) dans la base de données.

cartographie de base: <property name="some_flag" type="yes_no"/>

mapping Annotation (extensions Hibernate):

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

Pour ceux qui sont intéressés, il y a aussi un type "true_false" qui va stocker "T" ou "F". –

+0

Cela a fonctionné, mais je ne pouvais pas l'utiliser parce que c'est une annotation spécifique d'hibernation. Merci d'avoir répondu. Pourrait l'utiliser dans un projet différent. – sengs

+0

c'est pour hibernate 4 et plus tard, cela signifie pour Java 1.6 et plus tard. doent travail pour hibernate 3. * –

1

Pour même faire mieux cartographie booléenne à Y/N, ajoutez à votre configuration de mise en veille prolongée:

<!-- 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> 

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

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

Ceci est global. Pas adéquat pour les propriétés singulières. – maxxyme

0

A faire De manière générique JPA 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 mappés (getOpenedYnString et setOpenedYnString) sont des méthodes privées. Ces méthodes fournissent le mappage mais tous les accès par programme à la classe utilisent les méthodes getOpenedYn et 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; 
} 

est ici la classe util avec des méthodes statiques toYesNo et 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); 
    } 
} 
+0

pourquoi le vote vers le bas? –

+0

Je ne sais pas, mais corrigé que je pouvais. – peterh

70

Ceci est JPA pur sans utiliser getters/setters. A partir de 2013/2014 est la meilleure réponse sans utiliser des annotations spécifiques à Hibernate, mais s'il vous plaît noter que cette solution est JPA 2.1, et n'a pas été disponible lorsque la question a été posée:

@Entity 
public class Person {  

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

Et puis:

@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); 
     } 
    } 

Edit:

La mise en œuvre considère avant tout différent du caractère "Y", y compris null, comme false. Est-ce exact? Certaines personnes considèrent ceci comme incorrect, et croient que null dans la base de données devrait être null en Java.

Mais si vous revenez null en Java, il vous donnera un NullPointerException si votre champ est un booléen primitive. En d'autres termes, à moins que certains de vos champs utilisent effectivement la classe Boolean, il est préférable de considérer null comme false et d'utiliser l'implémentation ci-dessus.Alors Hibernate n'émettra aucune exception quel que soit le contenu de la base de données.

Et si vous ne voulez accepter null et émettent des exceptions si le contenu de la base de données ne sont pas strictement correcte, alors je suppose que vous ne devriez pas accepter des caractères en dehors de « Y », « N » et null. Rendez-le cohérent, et n'acceptez aucune variation comme «y», «n», «0» et «1», ce qui ne fera que vous rendre la vie plus difficile plus tard. Ceci est une application plus stricte:

@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); 
    } 

Et encore une autre option, si vous voulez permettre null en Java, mais pas dans la base de données:

@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

Le convertisseur montre l'idée, mais ne fonctionne bien sûr pas. Le convertisseur utilise les valeurs possibles de "Y", "N" et "T". Je ne suis pas sûr que l'on doive omettre le cas d'avoir une valeur nulle à la suite d'une conversion. – Matthias

+0

@Matthias Oui, T était une faute de frappe. Je l'ai corrigé. Merci. – MarcG

+0

J'ai eu un problème en utilisant le champ Y/N avec JPQL et posté une question de suivi ici: http://stackoverflow.com/questions/39581225/unable-to-render-boolean-literal-value-when-using-attributeconverter- for-boole –

0

utilisant 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 solution de contournement). Créez une énumération appelée BooleanWrapper avec 2 valeurs de T et F et ajoutez-y la méthode suivante pour obtenir la valeur encapsulée: public Boolean getValue() { return this == T; }, mappez-la avec @Enumerated (EnumType.STRING).

8

J'ai utilisé le concept de la réponse posté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 les champs d'entité Boolean en une colonne de caractères Y/N dans la base de données.

De ma classe d'entité:

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

Ma classe de conversion:

/** 
* 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; 
    } 

} 

Cette variante est aussi amusant si vous aimez émoticônes et êtes juste malade et fatigué de Y/N ou T/F dans votre base de données. Dans ce cas, la colonne de votre base de données doit comporter deux caractères au lieu d'un. Probablement pas un gros problème.

/** 
* 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

Le déballage 'b.booleanValue()' est-il nécessaire? –

Questions connexes