Автор оригинала: Vlad Mihalcea.
Вступление
Как уже объяснялось , проект hibernate-типы
с открытым исходным кодом позволяет сопоставлять JSON, МАССИВ при использовании JPA и Hibernate.
С тех пор как я запустил этот проект, одной из самых востребованных функций было добавление поддержки настройки базового приложения Jackson ObjectMapper
, и начиная с версии 2.1.1
, это может быть сделано либо декларативно, либо программно.
В этой статье вы увидите, как настроить ObjectMapper
при использовании проекта hibernate-типов.
Как настроить отображение объектов Джексона, используемое #Hibernate -Типы – @vlad_mihalcea https://t.co/nF1CcLVL7I pic.twitter.com/lBIMsw0Hh7
Декларативная конфигурация
Самый простой способ достичь этой цели-установить свойство hibernate.types.jackson.object.mapper
конфигурации в файле hibernate.properties
:
hibernate.types.jackson.object.mapper=com.vladmihalcea.hibernate.type.json.loader.CustomObjectMapperSupplier
Это свойство принимает полное имя класса реализации ObjectMapper поставщика
интерфейса:
Что хорошо в настройке проекта hibernate-types
, так это то, что вы можете использовать либо специфичный для Hibernate hibernate.properties
, либо вы можете предоставить файл hibernate-types.properties
, если вы не можете изменить hibernate.properties
.
Вы даже можете предоставить другой файл свойств Java через hibernate-types.properties.путь
Системное свойство.
Поставщик пользовательских объектов
может выглядеть следующим образом:
public class CustomObjectMapperSupplier implements ObjectMapperSupplier { @Override public ObjectMapper get() { ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules(); objectMapper.setTimeZone( TimeZone.getTimeZone("GMT") ); SimpleModule simpleModule = new SimpleModule( "SimpleModule", new Version(1, 0, 0, null, null, null) ); simpleModule.addSerializer(new MoneySerializer()); objectMapper.registerModule(simpleModule); return objectMapper; } }
Здесь мы используем пользовательский ObjectMapper
, который использует наш собственный Сериализатор денег
для обработки BigDecimal
Типов объектов Java:
public class MoneySerializer extends JsonSerializer{ @Override public void serialize( BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException { jsonGenerator.writeString( value.setScale(2, BigDecimal.ROUND_HALF_UP).toString() ); } @Override public Class handledType() { return BigDecimal.class; } }
Итак, если вы сохраняете следующую Книгу
сущность, которая имеет атрибут JSON свойства
:
Book book = new Book(); book.setIsbn("978-9730228236"); book.setProperties( JacksonUtil.toJsonNode( "{" + " \"title\": \"High-Performance Java Persistence\"," + " \"author\": \"Vlad Mihalcea\"," + " \"publisher\": \"Amazon\"," + " \"price\": 44.991234567" + "}" ) ); entityManager.persist(book);
При извлечении сущности Book
мы видим, что BigDecimal
принимает только два десятичных знака:
Book book = entityManager .unwrap(Session.class) .bySimpleNaturalId(Book.class) .load("978-9730228236"); assertEquals( "44.99", book.getProperties().get("price").asText() );
Программная конфигурация
Для еще большей гибкости вы можете использовать программную конфигурацию.
Предполагая, что у нас есть следующий тип объекта, который мы хотим сериализовать как JSON:
public class Location implements Serializable { private String country; private String city; private BigDecimal reference; //Getters and setters omitted for brevity }
И у нас есть Событие
сущность, которая сопоставляет объект Location
Java с типом столбца jsonb
PostgreSQL:
@Entity(name = "Event") @Table(name = "event") public class Event { @Id private Long id; @Type(type = "location") @Column(columnDefinition = "jsonb") private Location location; //Getters and setters omitted for brevity }
Мы можем использовать пользовательский ObjectMapper
следующим образом:
JsonType jsonType = new JsonType( new CustomObjectMapperSupplier().get(), Location.class ); properties.put("hibernate.type_contributors", (TypeContributorList) () -> Collections.singletonList( (typeContributions, serviceRegistry) -> typeContributions.contributeType( jsonType, "location" ) ) );
Свойство конфигурации hibernate.type_contributors
позволяет регистрировать пользовательские типы гибернации, и мы можем использовать эту функцию для предоставления нашего собственного пользовательского объектного
в JsonType
, предоставляемого проектом hibernate-types
.
Итак, если мы сохраняем следующее Событие
сущность:
Location location = new Location(); location.setCountry("Romania"); location.setCity("Cluj-Napoca"); location.setReference( BigDecimal.valueOf(2.25262562526626D) ); Event event = new Event(); event.setId(1L); event.setLocation(location); entityManager.persist(event);
При извлечении События
сущности мы видим, что BigDecimal
принимает только два десятичных знака:
Event event = entityManager.find(Event.class, 1L); assertEquals("2.25", event.getLocation().getReference().toString());
Круто, правда?
Вывод
Мало того, что вы можете настроить ObjectMapper
при использовании проекта hibernate-types
, но новый механизм конфигурации позволит настраивать и другие варианты поведения.
Так что оставайтесь с нами, чтобы узнать больше!