configurationhibernate(使用JPA)来存储布尔types的Y / N而不是0/1
我可以设置JPA / hibernate作为Y/N
持久Boolean
types吗? 在数据库中(该列定义为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( getOpenedYnString
和setOpenedYnString
)是私有方法。 这些方法提供映射,但是对类的所有编程访问都使用getOpenedYn
和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; }
下面是使用静态方法toYesNo
和toBoolean
的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)映射它。
- 设置SQL Server的Maven依赖关系
- Hibernate JPA,MySQL和TinyInt(1)用于Boolean而不是bit或char
- JPA JoinColumn vs mappedBy
- 如何configurationSQL Server的hibernateconfiguration文件
- JPA“@JoinTable”注释
- javax.persistence.Table.indexes()中的NoSuchMethodError [Ljavax / persistence / Index
- 如何解决hibernate双向映射引起的JSON串行器中的循环引用?
- 如何连接到Hibernate中的多个数据库
- 在执行select和count查询的时候,有没有比Hibernate更高效的分页方式?