Как сохранить сущность generi c с использованием JPA? - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть объект Generi c, который я хочу сохранить с помощью JPA, чтобы его значение generi c сохранялось в одном столбце jsonb. Упрощенный класс сущности выглядит следующим образом:

@Entity
public class Generic<T> {

    @Id
    private String name;

    private Type type;

    private T value; // want to store it in jsonb column

    // ... constructros, getters
}

type однозначно идентифицирует класс значения generi c, и допускается несколько типов с одним и тем же классом:

public enum Type {

    TYPE1(Double.class),
    TYPE2(Double.class),
    TYPE3(Coordinate.class),
    ...
    TYPEN(Double.class);

    private Class<?> aClass;

    TelemetrySignal(Class<?> aClass) {
        this.aClass = aClass;
    }

    Class<?> getClass() {
        return aClass;
    }
}

Мне не удалось найти способ сохранения такого обобщенного класса c с использованием Hibernate как есть. Я нашел альтернативные способы и обходные пути, но они не выглядят идеальными для меня. Я рассмотрел варианты:

  1. Пометить Generic как абстрактный и аннотировать его @MappedSuperclass, использовать наследование одной таблицы и для каждого возможного класса значений создать производный класс, который сохраняет значения как json в тот же столбец jsonb и загружает в конкретный класс. Я бы выбрал этот вариант для простой иерархии, но я ожидаю много классов. А для дополнительного нового класса значения требуется новый производный класс.

  2. Установите тип значения как JsonNode и пометьте его класс типа как com.vladmihalcea.hibernate.type.json.JsonBinaryType. В этом случае требуется только один класс Java, но недостатком является то, что мне приходится взаимодействовать с JsonNode в остальной части моего кода. Я должен конвертировать туда и обратно, когда требуется информация о классе, например, чтобы передать ее соответствующему обработчику.

Также я рассмотрел варианты, но не смог реализовать:

Я попытался реализовать свой собственный org.hibernate.type.Type и использовал com.vladmihalcea.hibernate.type.ImmutableType, чтобы упростить его. Идея состоит в том, чтобы при обработке столбца value посмотреть столбец type и десериализовать значение в соответствующий класс. Но мне не удалось правильно реализовать T get(ResultSet rs, String[] names,...), поскольку я получаю только имя текущего столбца для значения и не могу получить значение столбца type из ResultSet (Hibernate создает псевдонимы для всех столбцов).

Я пытался использовать два поля: @Transient T value и JsonNode genericValue. Идея состояла в том, чтобы преобразовать значение из @Transient T value в JsonNode genericValue в методе @PrePersist и преобразовать JsonNode в @Transient T value, используя поле type с информацией о классе в методе @PostLoad. Но оказалось, что @Transient поля являются пустыми в @PrePersist методах.

В настоящее время я остановился на 2-м варианте, но я рассматриваю 5-й вариант: создать собственный репозиторий для этого и использовать JdbcTemplate вместо Hibernate только для этого класса. Это определенно возможно, потому что я могу получить столбец type из ResultSet и десериализовать значение в соответствующий класс. Но у меня все еще есть шанс, что кто-то предложит альтернативный вариант, используя Hibernate. Есть идеи?

1 Ответ

0 голосов
/ 18 апреля 2020

JPA предоставляет способ преобразования базы данных в сущности, но вам необходим дополнительный слой для преобразования объекта базы данных в нужный тип объекта.

Я думаю, что логика c этого неверна .. ... но в любом случае ...

@Entity
@Table(name ="generic_table") // put the correct name
public class Generic {

  @Id
  private String name;

  @Column(name = "generic_type")
  @Enumerated(EnumType.STRING)   // put here the correct conf for each field
  private Type type;

  @Column(name = "generic_value")
  private binary[] value; // want to store it in jsonb column then it's a binary array for us. 


}

Позже создайте метод, который сделает анализ:

public <T> T parseGeneric(class<T>, binary[] content){
  // parsing here
}

Надеюсь, это поможет вам!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...