Автор оригинала: 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 , но новый механизм конфигурации позволит настраивать и другие варианты поведения.
Так что оставайтесь с нами, чтобы узнать больше!