JPA: сопоставить неверные значения базы данных с перечислениями - PullRequest
0 голосов
/ 17 января 2012

В моей модели данных есть много объектов, атрибуты которых сопоставляются с перечислениями следующим образом:

@Enumerated(EnumType.STRING)
private MySpecialEnum enumValue;

MySpecialEnum определяет некоторые фиксированные значения. Сопоставление работает нормально, и если база данных содержит NULL-значение для столбца, я получаю NULL и в атрибуте enumValue. Проблема в том, что мой внутренний модуль (на который я не имею никакого влияния) использует пробелы в CHAR-столбцах, чтобы определить, что значение не установлено. Поэтому я получаю IllegalArgumentException вместо NULL-значения.

Итак, мой вопрос: существует ли JPA-событие, где я могу изменить значение, считанное из базы данных, перед сопоставлением с атрибутом enum? Для доступа на запись есть @PrePersist, где я могу изменить пустые значения на пробелы. Я знаю, что есть событие @ PostLoad, но оно обрабатывается после сопоставления.

Кстати: я использую OpenJpa, поставляемый в составе WebSphere Application Server.

Ответы [ 2 ]

0 голосов
/ 31 мая 2013

OpenJPA предлагает @Externalizer и @Factory для обработки «специальных» значений базы данных.

Смотрите это: http://ci.apache.org/projects/openjpa/2.0.x/manual/manual.html#ref_guide_pc_extern_values

Возможно, вы получите что-то вроде этого: не проверено ...

@Factory("MyClass.mySpecialEnumFactory")
private MySpecialEnum special;

...

public static MySpecialEnum mySpecialEnumFactory(String external) {
   if(StringUtils.isBlank(external) return null; // or why not MySpecialEnum.NONE;
   return MySpecialEnum.valueOf(external);
}
0 голосов
/ 20 января 2012

Вы можете сопоставить поле типа enum как @Transient (оно не будет сохранено) и напрямую сопоставить другое поле как String, синхронизируя их в @PostLoad:

@Transient
private MyEnum fieldProxy;

private String fieldDB;

@PostLoad
public void postLoad() {
    if (" ".equals(fieldDB))
         fieldProxy = null;
    else
         fieldProxy = MyEnum.valueOf(fieldDB);
}

Использовать get/setFieldProxy()в вашем коде Java.

Что касается синхронизации другим способом, я бы сделал это в установщике, а не в @PreUpdate, поскольку изменения в полях @Transient, вероятно, не помечают сущность как измененную иоперация обновления может быть не запущена (я не уверен в этом):

public void setFieldProxy(MyEnum value) {
    fieldProxy = value;
    if (fieldProxy == null)
       fieldDB = " ";
    else
       fieldDB = value.name();
}
...