我无法使用Hibernate(5.3.7)UserType在Postgres数据库中正确存储日期(LocalDate)。它间歇性地无法存储正确的Dob。大多数日期(dob)具有无效的月份值,例如“ dob”:“ 1986-12-363”。
数据库存储调用在CompletableFuture.runAsync(()-> {...存储在数据库..})中进行
我无法找到问题所在。它间歇性地失败,这使它更加混乱。我不确定这里出什么问题了。非常感谢您为解决此问题提供的帮助。
我关注了this tutorial。
@Entity
@Table(name = "abc")
@TypeDef(name = "userJsonType", typeClass = UserJsonType.class)
public class ABC implements Serializable {
....
@Type(type = "userJsonType")
private final List<User> users;
....
}
public class User implements Serializable{
....
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private final LocalDate dob;
....
}
public class UserJsonType implements UserType {
@Override
public int[] sqlTypes() {
return new int[]{Types.JAVA_OBJECT};
}
@Override
public Class returnedClass() {
return new TypeReference<List<User>>() {
}.getClass();
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return false;
}
@Override
public int hashCode(Object x) throws HibernateException {
if (null == x) {
return 0;
}
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
final String cellContent = rs.getString(names[0]);
if (cellContent == null) {
return null;
}
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper.readValue(cellContent.getBytes("UTF-8"), returnedClass());
} catch (final Exception ex) {
throw new RuntimeException("Failed to convert String to CustomerDetails: " + ex.getMessage(), ex);
}
}
@Override
public void nullSafeSet(PreparedStatement ps, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value == null) {
ps.setNull(index, Types.OTHER);
return;
}
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
final StringWriter w = new StringWriter();
mapper.writeValue(w, value);
w.flush();
ps.setObject(index, w.toString(), Types.OTHER);
} catch (final Exception ex) {
throw new RuntimeException("Failed to convert CustomerDetails to String: " + ex.getMessage(), ex);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
try {
// use serialization to create a deep copy
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(value);
oos.flush();
oos.close();
bos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
return new ObjectInputStream(bais).readObject();
} catch (ClassNotFoundException | IOException ex) {
throw new HibernateException(ex);
}
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object copy = deepCopy(value);
if (copy instanceof Serializable) {
return (Serializable) copy;
}
throw new SerializationException(String.format("Cannot serialize '%s', %s is not Serializable.", value, value.getClass()), null);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return deepCopy(original);
}
}