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

sen*_*ngs 76 java hibernate jpa

我可以将JPA/hibernate设置为持久化Boolean类型Y/N吗?在数据库中(列定义为varchar2(1).它当前将它们存储为0/1.数据库是Oracle.

Chs*_*y76 139

Hibernate有一个内置的"yes_no"类型,可以做你想要的.它映射到数据库中的CHAR(1)列.

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

注释映射(Hibernate扩展):

@Type(type="yes_no")
public boolean getFlag();
Run Code Online (Sandbox Code Playgroud)

  • 对于那些感兴趣的人,还有一个"true_false"类型,它将存储"T"或"F". (27认同)
  • 给出这个答案时,@ storm_buster Hibernate 4不存在.它与Hibernate 3.x和java 1.5完美搭配 (7认同)
  • 如何把0或1呢? (2认同)

Mar*_*rcG 81

这是纯粹的JPA而不使用getter/setter.截至2013/2014,它是不使用任何Hibernate特定注释的最佳答案,但请注意此解决方案是JPA 2.1,并且在首次提出问题时无法使用:

@Entity
public class Person {    

    @Convert(converter=BooleanToStringConverter.class)
    private Boolean isAlive;    
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后:

@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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑:

上面的实现考虑了与字符"Y"不同的任何内容,包括nullas false.那是对的吗?这里的一些人认为这是不正确的,并且相信null在数据库中应该是nullJava.

但是如果你null在Java中返回,它会给你一个NullPointerExceptionif你的字段是一个原始的布尔值.换句话说,除非你的一些领域的实际使用类布尔也最好考虑nullfalse,并使用上述实现.然后,无论数据库的内容如何,​​Hibernate都不会发出任何异常.

如果你确实想要接受null并发出异常,如果数据库的内容不严格正确,那么我猜你不应该接受"Y","N"和"Y"之外的任何字符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);
    }
Run Code Online (Sandbox Code Playgroud)

还有另一个选择,如果你想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);
    }
Run Code Online (Sandbox Code Playgroud)


Jim*_*ugh 11

我使用了@marcg发布的答案中的概念,它与JPA 2.1一起使用效果很好.他的代码不太正确,所以我发布了我的工作实现.这会将Boolean实体字段转换为数据库中的Y/N字符列.

从我的实体类:

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

我的转换器类:

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

}
Run Code Online (Sandbox Code Playgroud)

如果您喜欢表情符号,并且只是厌倦了数据库中的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;
    }

}
Run Code Online (Sandbox Code Playgroud)


Spe*_*ort 7

我弄清楚如何做到这一点的唯一方法是为我的班级提供两个属性.一个作为编程API的布尔值,未包含在映射中.它是getter和setter引用的私有char变量,它是Y/N. 然后我有另一个受保护的属性,它包含在hibernate映射中,它的getter和setter直接引用private char变量.

  • ChssPly76的另一个答案是正确的. (4认同)