我正在迁移到quarkus 3,我找不到一种方法来正确序列化(如在hibernate 5中)我的OffsetDateTime,用于实体中用jsonb注解的字段:
这是我的一个实体,OffsetDateTime在持久化时不会有问题,因为我在配置中添加了参数hibernate-mapping.timezone.default-storage=“NORMALIZE”,因此我可以使用时区正确获取日期
package myPackage;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.orange.erable.ohp.common.quarkus.rest.internal.identifier.models.IdentifierCharacteristicNameDTO;
import com.orange.erable.ohp.persistence.entities.enums.EIdentifierCategory;
import com.orange.erable.ohp.persistence.entities.enums.EIdentifierStatus;
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import lombok.Data;
import org.hibernate.annotations.Type;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import jakarta.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.time.OffsetDateTime;
import java.util.UUID;
@Data
@Entity
@Table(name = "t_identifier")
public class IdentifierEntity extends PanacheEntityBase {
@Id
private String idohp;
private String msisdn;
private String idAdv;
private String contractAid;
private String countryCode;
@NotNull
@Enumerated(EnumType.STRING)
@Type(PostgreSQLEnumType.class)
@Column(columnDefinition = "status")
private EIdentifierStatus status;
@Enumerated(EnumType.STRING)
@Type(PostgreSQLEnumType.class)
@Column(columnDefinition = "category")
private EIdentifierCategory category;
@Column(updatable = false)
private OffsetDateTime creationDate = OffsetDateTime.now();
private OffsetDateTime updateDate = OffsetDateTime.now();
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private boolean updated = false;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private boolean created = false;
}
但是对于这个包含先前实体的实体,OffsetDateTime内部标识符没有以正确的格式持久化,它是以UTC格式持久化的,我错过了我的时区:
package myPackage;
import io.hypersistence.utils.hibernate.type.json.JsonBinaryType;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.*;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.time.OffsetDateTime;
@Data
@NoArgsConstructor
@Entity
@Table(name = "t_identifier_history")
public class IdentifierHistoryEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String idohp;
@Type(JsonBinaryType.class)
@Column(columnDefinition = "jsonb")
private IdentifierEntity identifier;
@Column(insertable = false, updatable = false)
private OffsetDateTime creationDate = OffsetDateTime.now();
@Column(insertable = false)
private OffsetDateTime updateDate = OffsetDateTime.now();
private String historyVersion;
public IdentifierHistoryEntity(IdentifierEntity identifierEntity, String historyVersion) {
this.idohp = identifierEntity.getIdohp();
this.identifier = identifierEntity;
this.historyVersion = historyVersion;
}
}
我尝试在标识符字段上设置@JdbcTypeCode(SqlTypes.JSON)
我尝试创建自己的格式Map器,并使用quarkus. hibernate-mapping. unauthorized-properties.“hibernate.type.json_format_mapper”=“myCustommapper”引用它:
public class RegisterJacksonCustomizer implements FormatMapper {
private final FormatMapper delegate = new JacksonJsonFormatMapper(createObjectMapper());
private static ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.disable(SerializationFeature.WRAP_ROOT_VALUE);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(OffsetDateTime.class, new CustomOffsetDateTimeSerializer(DATE_TIME_FORMATTER));
javaTimeModule.addDeserializer(OffsetDateTime.class, new CustomOffsetDateTimeDeserializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
objectMapper.registerModule(javaTimeModule);
return objectMapper;
}
@Override
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
return delegate.fromString(charSequence, javaType, wrapperOptions);
}
@Override
public <T> String toString(T t, JavaType<T> javaType, WrapperOptions wrapperOptions) {
return delegate.toString(t, javaType, wrapperOptions);
}
}
结合此配置:
quarkus:
hibernate-orm:
mapping:
timezone:
default-storage: "NORMALIZE"
jdbc:
timezone: "Europe/Paris"
unsupported-properties:
- "hibernate.type.json_format_mapper": "pathToMyMapper"
1条答案
按热度按时间laximzn51#
我看到你的问题中有几个令人困惑的地方,所以我将分别回答它们。
JSONMap很可能忽略对象/关系Map!
当您将属性Map为JSON/XML时,您避开了任何关系Map,因此
jsonb
标识符中的日期忽略quarkus.hibernate-orm.mapping.timezone.default-storage
也就不足为奇了。如果IdentifierEntity
中的Integer
列被Map为数据库中的字符串,也会发生同样的情况:JSON序列化仍然会将其Map为整数。如果你想改变你的实体被序列化为JSON的方式,你将不得不使用一个自定义的
FormatMapper
,doesn't have first-class support in Quarkus yet有一个不支持的解决方案。你声称你试过了,但如果你想得到帮助,你应该解释什么不起作用。NORMALIZE
不会保留时区!OffsetDateTime内部标识符没有以正确的格式持久化,它以UTC格式持久化,我丢失了我的时区
您使用的是
hibernate-orm.mapping.timezone.default-storage=NORMALIZE
,因此您得到的正是预期的行为:日期/时间标准化为UTC。请参阅文档的此部分:
NORMALIZE
不存储时区信息,只是将时间戳转换为UTC如果你想保留时区,我建议你使用
AUTO
,它将使用一个原生的DB类型,如果可能的话,它将保留时区,否则将使用一个单独的时区列。编辑后更新
您的配置缺少
quarkus
前缀?我实际上有我的日期的权利,因为时区是插入时,阅读从数据库感谢配置,但它不是持久的时区
好吧,这将是一个问题,因为你会失去更新的时区。
我重申一下:
如果你想保留时区,我建议你使用
AUTO
,它将使用一个原生的DB类型来保留时区,如果可能的话,或者一个单独的时区列。关于你的格式Map器,对不起,但是我们离我的专业领域太远了,让我们回家有人插话告诉你你的实现中有什么问题。您可能需要显示
CustomOffsetDateTimeSerializer
的代码。