7 ответов:
единственный способ, которым я понял, как это сделать, это иметь два свойства для моего класса. Один как логическое значение для API программирования, которое не включено в сопоставление. Это геттер и сеттер ссылаются на частную переменную char, которая является Y / N. затем у меня есть другое защищенное свойство, которое включено в отображение hibernate, и это геттеры и сеттеры ссылаются на частную переменную char напрямую.
Hibernate имеет встроенный тип "yes_no", который будет делать то, что вы хотите. Он сопоставляется с столбцом CHAR(1) в базе данных.
базовое картографирование:
<property name="some_flag" type="yes_no"/>отображение аннотаций (Hibernate extensions):
@Type(type="yes_no") public boolean getFlag();
это чистый 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); } }Edit:
реализация выше рассматривает все, что отличается от символа "Y", в том числе
null, аfalse. Это правильно? Некоторые люди здесь считайте это неправильным, и верьте, чтоnullв базе данных должна бытьnullв Java.но если вы вернетесь
nullв Java, это даст вамNullPointerExceptionесли ваше поле примитива boolean. Другими словами, если некоторые из ваших полей на самом деле не используют класс Boolean лучше всего рассмотретьnullкакfalse, и использовать вышеуказанную реализацию. Тогда 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); }и еще один вариант, если вы хотите разрешить для
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); }
я использовал концепцию из ответа, опубликованного @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, добавьте в свою конфигурацию hibernate:
<!-- 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"
сделать это в универсальном СПД способом, используя аннотации добытчик, пример ниже работает для меня с Hibernate 3.5.4 и Oracle 11г. Обратите внимание, что подключенный геттер и сеттер (
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; }вот класс util со статическими методами
toYesNoи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); } }
использование конвертеров JPA 2.1 является лучшим решением, однако если вы используете более раннюю версию JPA, я могу порекомендовать еще одно решение (или обходной путь). Создайте перечисление с именем BooleanWrapper с 2 значениями T и F и добавьте к нему следующий метод, чтобы получить завернутое значение:
public Boolean getValue() { return this == T; }, сопоставьте его с @Enumerated (EnumType.СТРОКА.)
Comments