Я обновляю наше приложение до версии платформы, поддерживающей Java 8 Date / Time API.Я обновил наши модели сущностей, чтобы отразить правильное преобразование типов (дата -> LocalDate, отметка времени -> LocalDateTime).
Сейчас я сталкиваюсь с проблемой запуска моих модульных тестов, когда конвертеры пытаются преобразовать java.sql.Date в java.sql.Timestamp.Это сбивает с толку, потому что временная метка не должна использоваться для этих объектов.Сценарий тестирования SQL использует TO_DATE () для установки дат, например так:
INSERT INTO note (id, content, date, owner_id) VALUES (1, 'test content', TO_DATE('17/12/2017', 'DD/MM/YYYY'), 1);
И возвращаемое исключение:
Caused by: java.lang.ClassCastException: java.sql.Timestamp cannot be cast to java.sql.Date
at com.<redacted>.model.jpa.LocalDateAttributeConverter.convertToEntityAttribute(LocalDateAttributeConverter.java:8)
at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45)
at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.doConversion(AttributeConverterSqlTypeDescriptorAdapter.java:140)
... 64 more
из простого AttributeConverter <>:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.sql.Date;
import java.time.LocalDate;
@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate locDate) {
return (locDate == null ? null : Date.valueOf(locDate));
}
@Override
public LocalDate convertToEntityAttribute(Date sqlDate) {
return (sqlDate == null ? null : sqlDate.toLocalDate());
}
}
Я могу понять, что возникла проблема с приведением метки времени к дате, но метка времени здесь вообще не нужна.
Объект для полноты:
@XmlRootElement
@Entity(name = "notes")
public class Note implements ModelObject {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "owner_id", referencedColumnName = "id")
private User user;
private String content;
private LocalDate date;
// getters/setters omitted for brevity
}
Не уверенесли это влияет на это, но я также создал AttributeConverters для LocalTime и LocalDateTime.
@Converter(autoApply = true)
public class LocalTimeAttributeConverter implements AttributeConverter<LocalTime, Time> {
@Override
public Time convertToDatabaseColumn(LocalTime localTime) {
return (localTime == null ? null : Time.valueOf(localTime));
}
@Override
public LocalTime convertToEntityAttribute(Time sqlTime) {
return (sqlTime == null ? null : sqlTime.toLocalTime());
}
}
@Converter(autoApply = true)
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) {
return (locDateTime == null ? null : Timestamp.valueOf(locDateTime));
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
}
}
Использование Hibernate 5.3.0.Final и H2 1.4.197 с библиотекой hibernate-java8.