0/1ではなくブール型のY / Nを格納するように(JPAを使用して)休止状態を構成します


80

Booleanタイプを永続化するようにJPA / hibernateを設定できますY/Nか?データベース内(列はとして定義されていvarchar2(1)ます。現在、それらはとして格納されてい0/1ます。データベースはOracleです。

回答:


8

これを行う方法を理解した唯一の方法は、クラスに2つのプロパティを設定することです。1つは、マッピングに含まれていないプログラミングAPIのブール値です。ゲッターとセッターは、Y / Nであるプライベートchar変数を参照します。次に、休止状態のマッピングに含まれている別の保護されたプロパティがあり、そのゲッターとセッターはプライベートchar変数を直接参照します。

編集:指摘されているように、Hibernateに直接組み込まれている他のソリューションがあります。組み込みのオプションではうまく機能しないレガシーフィールドで作業している状況で機能する可能性があるため、この回答は残しておきます。その上、このアプローチに深刻な悪影響はありません。


1
私は同様のことをしなければなりませんでした-私はメンバーのタイプをブール値から文字列に変更しました。ゲッターとセッター(ブール値を取得して設定)で、Y / Nを対応するブール値に変換するコードを記述しました。
sengs

@bernardnいいえ、それはより良いものです。
アレクサンダー2015


146

Hibernateには、必要な処理を実行する「yes_no」タイプが組み込まれています。これは、データベースのCHAR(1)列にマップされます。

基本的なマッピング: <property name="some_flag" type="yes_no"/>

アノテーションマッピング(Hibernate拡張機能):

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

28
興味のある人のために、「T」または「F」のいずれかを格納する「true_false」タイプもあります。
Matt Solnit

これは機能しましたが、休止状態固有のアノテーションであるため、使用できませんでした。答えてくれてありがとう。別のプロジェクトで使用する可能性があります。
sengs 2009

これはHibernate4以降用です。つまり、Java1.6以降用です。hibernate3では機能しません。*
storm_buster 2012

7
@storm_buster Hibernate 4は、この回答が与えられたときには存在しませんでした。Hibernate3.xおよび
java1.5で

3
では、0または1を置く方法は?
JavaTechnical 2014年

84

これは、ゲッター/セッターを使用しない純粋なJPAです。2013/2014の時点では、Hibernate固有のアノテーションを使用しないベストアンサーですが、このソリューションはJPA 2.1であり、最初に質問されたときには利用できなかったことに注意してください。

@Entity
public class Person {    

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

その後:

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

編集:

上記の実装では、を含む文字「Y」とは異なるものはすべてと見なさnullfalseます。あれは正しいですか?ここにいる何人かの人々はこれを間違っていると考えてnullおり、データベースはnullJavaでなければならないと信じています。

ただしnull、Javaに戻るとNullPointerException、フィールドがプリミティブブール値であるかどうかがわかります。言い換えれば、あなたのフィールドのいくつかは、実際に使用しない限り、クラスをブールそれが考慮することが最善だnullとしてfalse、上記の実装を使用します。その場合、Hibernateは、データベースの内容に関係なく、例外を発行しません。

あなたが受け入れたくない場合やnull、データベースの内容は厳密には正しくない場合はとEMIT例外、その後、私はあなたが受け入れるべきではないと思う任意の「Y」、「N」とは別に文字をnull。一貫性を保ち、「y」、「n」、「0」、「1」などのバリエーションを受け入れないでください。これにより、後で生活が困難になるだけです。これはより厳密な実装です。

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

さらに別のオプションとしてnull、Javaで許可したいが、データベースでは許可したくない場合:

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

コンバーターはアイデアを示していますが、もちろん機能していません。コンバータの可能な値を使用しYNそしてT。また、変換の結果としてnull値を持つ場合を省略すべきかどうかもわかりません。
マティアス

@Matthiasはい、Tはタイプミスでした。それを私が直した。ありがとう。
MarcG 2014年

JPQLでY / Nフィールドを使用する際に問題が発生し、フォローアップの質問をここに投稿しました:stackoverflow.com/questions/39581225/…–
Chris Williams

11

@marcgによって投稿された回答の概念を使用しましたが、JPA2.1でうまく機能します。彼のコードは完全に正しくなかったので、私は私の実用的な実装を投稿しました。これにより、BooleanエンティティフィールドがデータベースのY / N文字列に変換されます。

私のエンティティクラスから:

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

私のコンバータークラス:

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

}

このバリアントは、絵文字が大好きで、データベースのY / NまたはT / Fにうんざりしている場合にも役立ちます。この場合、データベースの列は1文字ではなく2文字である必要があります。おそらく大したことではありません。

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

}

ボックス化解除 'b.booleanValue()'は必要ですか?
LeOn-Han Li 2015年

データベース値のNULLプロパティを除いてNULL、この回答は@MarKG回答に付加価値を提供しません。その違いをコメントとして捉えるのが最善です。
モーニッシュ

あなたしている5年遅すぎた男
ジム・タフ

2

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

これで、HQLでブール値を使用できます。次に例を示します。

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

2
これはグローバルです。特異な特性には不十分です。
maxxyme 2016年

0

ゲッターアノテーションを使用して一般的なJPAの方法でそれを行うために、以下の例はHibernate3.5.4とOracle11gで機能します。マップされたgetterとsetter(getOpenedYnStringおよびsetOpenedYnString)はプライベートメソッドであることに注意してください。これらのメソッドはマッピングを提供しますが、クラスへのすべてのプログラムによるアクセスはgetOpenedYnandsetOpenedYnメソッドを使用しています。

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

静的メソッドtoYesNoを持つutilクラスと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);
    }
}

-1

JPA 2.1コンバーターを使用するのが最善の解決策ですが、以前のバージョンのJPAを使用している場合は、もう1つの解決策(または回避策)をお勧めします。TとFの2つの値を持つBooleanWrapperという名前の列挙型を作成し、それに次のメソッドを追加してラップされた値を取得します。public Boolean getValue() { return this == T; }、@ Enumerated(EnumType.STRING)でマップします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.