configurationhibernate(使用JPA)来存储布尔types的Y / N而不是0/1

我可以设置JPA / hibernate作为Y/N持久Booleantypes吗? 在数据库中(该列定义为varchar2(1) ,当前存储为0/1 ,数据库为Oracle。

我已经想出了如何做到这一点的唯一方法是为我的课程有两个属性。 一个作为编程API的布尔值,不包含在映射中。 它是getter和setter引用一个私有字符variables是Y / N。 然后我有另一个被包含在hibernate映射中的受保护的属性,它的getters和setter直接引用私有charvariables。

Hibernate有一个内置的“yes_no”types,可以做你想做的事情。 它映射到数据库中的CHAR(1)列。

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

注释映射(Hibernate扩展):

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

这是纯粹的JPA,没有使用getters / setters。 截至2013/2014年,这是最好的答案,而不使用任何Hibernate特定的注释,但请注意这个解决scheme是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应该在Java中为null

但是如果你在Java中返回null ,如果你的字段是一个原始的布尔值 ,它将会给你一个NullPointerException 。 换句话说,除非你的某些字段实际上使用了布尔类 ,否则最好把null看作false ,并使用上面的实现。 那么Hibernate将不会发出任何exception,不pipe数据库的内容如何。

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

还有一个select,如果你想允许在Java中为null ,但不在数据库中:

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

我使用了@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; } } 

要做更好的布尔映射到Y / N,添加到你的hibernateconfiguration:

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

为了以通用的JPA方式使用getter注释来实现,下面的例子适用于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; } 

下面是使用静态方法toYesNotoBoolean的util类:

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

使用JPA 2.1转换器是最好的解决scheme,但是如果您使用JPA的早期版本,我可以推荐一个更多的解决scheme(或解决方法)。 使用T和F的2个值创build一个名为BooleanWrapper的枚举,并添加以下方法来获取包装值: public Boolean getValue() { return this == T; } public Boolean getValue() { return this == T; } ,使用@Enumerated(EnumType.STRING)映射它。