Рубрики
Без рубрики

Как сопоставить коллекцию JSON с помощью JPA и гибернации

Как сопоставить коллекцию JSON с помощью JPA и гибернации и сохранить ее в виде столбца типа JSON или JSONB в MySQL, PostgreSQL.

Автор оригинала: Vlad Mihalcea.

Вступление

Проект с открытым исходным кодом типы гибернации позволяет отображать объекты Java или Jackson JsonNode как свойства объектов JPA или гибернации, и благодаря нашим замечательным участникам мы добавили поддержку для хранения типобезопасных коллекций JSON.

В этой статье вы увидите, как достичь этой цели.

Слава @vlad_mihalcea , библиотека типов гибернации вчера сэкономила мне массу работы, автоматически сопоставив столбец PostgreSQL jsonb с POJO. Блестящая работа 💪

Зависимость от Maven

Прежде всего, вам необходимо настроить следующую зависимость Maven в вашем проекте pom.xml файл конфигурации:


    com.vladmihalcea
    hibernate-types-55
    ${hibernate-types.version}

Если вы используете более старые версии Hibernate, ознакомьтесь с репозиторием hibernate-types GitHub для получения дополнительной информации о соответствующей зависимости для вашей текущей версии Hibernate.

Модель предметной области

Давайте предположим, что у нас есть следующий тип объекта Location Java.

public class Location implements Serializable {

    private String country;

    private String city;

    //Getters and setters omitted for brevity

    @Override
    public String toString() {
        return "Location{" +
                "country='" + country + ''' +
                ", city='" + city + ''' +
                '}';
    }
}

И, одно Событие сущность:

@Entity(name = "Event")
@Table(name = "event")
public class Event extends BaseEntity {

    @Type(type = "json")
    @Column(columnDefinition = "jsonb")
    private Location location;

    @Type(type = "json")
    @Column(columnDefinition = "jsonb")
    private List alternativeLocations = new ArrayList();

    //Getters and setters omitted for brevity
}

BaseEntity определяет некоторые базовые свойства (например, @Id , @Версия ) и несколько пользовательских типов гибернации, среди которых нас интересует JsonType .

@TypeDefs({
    @TypeDef(name = "string-array", typeClass = StringArrayType.class),
    @TypeDef(name = "int-array", typeClass = IntArrayType.class),
    @TypeDef(name = "json", typeClass = JsonType.class)
})
@MappedSuperclass
public class BaseEntity {

    @Id
    private Long id;

    @Version
    private Integer version;

    //Getters and setters omitted for brevity
}

Для получения более подробной информации об использовании @MappedSuperclass ознакомьтесь с этой статьей .

Чтобы сохранить как объект Местоположение , так и Список<Местоположение> в столбце jsonb PostgreSQL, нам просто нужно аннотировать свойство местоположение с помощью @Type(тип) .

Вот и все!

Время тестирования

При сохранении следующего События объекта:

Location cluj = new Location();
cluj.setCountry("Romania");
cluj.setCity("Cluj-Napoca");

Location newYork = new Location();
newYork.setCountry("US");
newYork.setCity("New-York");

Location london = new Location();
london.setCountry("UK");
london.setCity("London");

Event event = new Event();
event.setId(1L);
event.setLocation(cluj);
event.setAlternativeLocations(
    Arrays.asList(newYork, london)
);

entityManager.persist(event);

Hibernate создаст следующую инструкцию SQL INSERT:

INSERT INTO event (
    version, 
    alternativeLocations, 
    location, 
    id
) 
VALUES (
    0, 
    [
        {"country":"US","city":"New-York"},
        {"country":"UK","city":"London"}
    ], 
    {"country":"Romania","city":"Cluj-Napoca"}, 
    1
)

Кроме того, при возврате объекта Событие свойства местоположения и | альтернативных местоположений извлекаются правильно:

Событие.найдите(Event.class, вечер);

assertEquals(
    "Cluj-Napoca", 
    event.getLocation().getCity()
);

assertEquals(2, event.getAlternativeLocations().size());

assertEquals(
    "New-York", 
    event.getAlternativeLocations().get(0).getCity()
);
assertEquals(
    "London", 
    event.getAlternativeLocations().get(1).getCity()
);

Круто, правда?

Вывод

Проект hibernate-types поддерживает не только типы JSON. Вы можете сопоставить типы массивов PostgreSQL или перечисления, относящиеся к PostgreSQL , с возможностью обнуления Символов или даже предоставить свои собственные неизменяемые пользовательские Типы для гибернации .