java - DAO 单元测试的日期转换
问题描述
我正在将我们的应用程序升级到支持 Java 8 日期/时间 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());
}
}
我可以理解从 Timestamp 到 Date 的转换有问题,但 Timestamp 在这里根本不应该涉及。
完整性实体:
@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
}
不确定这是否会影响它,但我还为 LocalTime 和 LocalDateTime 创建了 AttributeConverters。
@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 库一起使用。
解决方案
推荐阅读
- python - 用唯一列表中的后续值替换列值
- ios - 如何禁用 ScrollView 项目上的多个按钮颜色选择?
- sql - 在 Yii2 中查询多个表时违反完整性约束
- java - Scanner.nextLine() 抛出 java.util.InputMismatchException
- apache-spark - 如何在 Spark SQL 中重用 jdbc 连接?
- react-native - 如何将反应本机TextInput设置为由屏幕阅读器读取为手机号码输入
- android - 如何在 Kotlin 中以编程方式设置 EditText 的 maxLength 属性?
- mysql - 如何将日志文件增量插入mysql表?
- node.js - Node js的回调队列排序
- kotlin - Kotlin 中的 HashMap 和 MutableMap 有什么区别