配置休眠(使用JPA)以将Y / N存储为布尔类型(而不是0/1)


80

我可以设置JPA /休眠将Boolean类型持久化为Y/N吗?在数据库中(该列定义为varchar2(1)。当前将其存储为0/1。数据库为Oracle。

Answers:


8

我弄清楚如何执行此操作的唯一方法是为类提供两个属性。一个作为编程API的布尔值,不包含在映射中。它的getter和setter引用一个私有字符变量Y / N。然后,我还有另一个受保护的属性,它包含在休眠映射中,它的getter和setter直接引用私有char变量。

编辑:正如已经指出的那样,还有直接内置于Hibernate中的其他解决方案。我留下这个答案是因为它可以在您处理的旧字段不适用于内置选项的情况下使用。最重要的是,这种方法不会造成严重的负面影响。


1
我必须做类似的事情-我将成员的类型从Boolean更改为String。在getter和setter(获取并设置布尔值)中,我编写了将Y / N转换为相应布尔值的代码。
2009年

@bernardn不,这是更好的选择。
亚历山大


145

Hibernate具有内置的“ yes_no”类型,可以执行您想要的操作。它映射到数据库中的CHAR(1)列。

基本映射: <property name="some_flag" type="yes_no"/>

注释映射(Hibernate扩展):

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

28
对于那些感兴趣的人,还有一个“ true_false”类型将存储“ T”或“ F”。
Matt Solnit 09年

这行得通,但是我不能使用它,因为它是休眠特定的注释。谢谢你的回答。可能在其他项目中使用它。
2009年

这适用于休眠4及更高版本,这意味着适用于Java 1.6及更高版本。确实为休眠3工作。*
storm_buster 2012年

7
给出此答案时,@storm_buster休眠4不存在。它的工作原理完全正常使用Hibernate 3.x和Java 1.5的
ChssPly76

3
怎么放0或1呢?
JavaTechnical

84

这是纯JPA,不使用getter / setter。截至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”不同的任何内容,包括null,如false。那是对的吗?这里有些人认为这是不正确的,并认为null数据库中应该使用nullJava。

但是,如果您返回nullJava,则NullPointerException如果您的字段是原始布尔值,它将给您一个提示。换句话说,除非你的一些领域的实际使用类布尔也最好考虑nullfalse,并使用上述实现。这样,无论数据库内容如何,​​Hibernate都不会发出任何异常。

并且,如果您确实想接受null并发出异常(如果数据库的内容不完全正确),那么我猜您不应该接受除“ 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);
    }

还有另一种选择,如果要允许使用nullJava而不允许使用数据库:

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

转换器显示了这个想法,但是当然不起作用。该转换器使用的可能值YNT。我也不确定是否应该省略由于转换而导致具有空值的情况。
马赛厄斯

@Matthias是的,T是一个错字。我修好了它。谢谢。
MarcG 2014年

我在使用JPQL的Y / N字段时遇到问题,并在此处发布了后续问题:stackoverflow.com/questions/39581225/…–
克里斯·威廉姆斯

11

我使用了@marcg发布的答案中的概念,它在JPA 2.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感到厌倦,则此变体也很有趣。在这种情况下,您的数据库列必须是两个字符而不是一个字符。可能没什么大不了的。

/**
 * 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-韩立2015年

除了数据库值的NULL属性外NULL,此答案不提供@MarKG答案以外的任何值。最好抓住这种差异作为评论。
Mohnish

您晚了5年
Jim Tough

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

为了使用getter注释以通用JPA方式完成此任务,下面的示例适用于Hibernate 3.5.4和Oracle 11g。请注意,映射的getter和setter(getOpenedYnStringsetOpenedYnString)是私有方法。这些方法提供了映射,但是对类的所有编程访问都使用getOpenedYnsetOpenedYn方法。

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的早期版本,我可以推荐另一个解决方案(或解决方法)。创建一个名为BooleanWrapper的枚举,它具有2个T和F值,并向其添加以下方法以获取包装的值:public Boolean getValue() { return this == T; },使用@Enumerated(EnumType.STRING)对其进行映射。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.