我想为我的启用了JPA的应用程序 添加对Java 8日期/时间API(JSR-310)的支持。
很明显,JPA 2.1不支持Java 8日期/时间API。
作为一种解决方法,最常见的建议是使用AttributeConverter
。
在我的现有应用程序中,我更改了实体以使用LocalDate
/LocalDateTime
类型进行列映射,并为它们添加了用于java.util.Date
的旧setter/getters。
我创建了相应的AttributeConverter
类。
Query.setParameter()
时,传入java.util.Date
实例后失败了(在转换到新API之前是可以工作的)。看起来JPA期望新的日期类型,并且不会即时转换。我原本期望如果将一个已注册AttributeConverter
的类型作为参数传递给setParameter()
,它会被转换器自动转换。但这似乎并非如此,至少在使用EclipseLink 2.6.2
时不是这样的。java.lang.IllegalArgumentException: You have attempted to set a value of type class java.util.Date for parameter closeDate with expected type of class java.time.LocalDate from query string SELECT obj FROM [...]
at org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:937) ~[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:593) ~[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:1) ~[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
[...]
问题:
- 这种行为是否是预期的?我有遗漏什么吗?
- 有没有一种方法可以使用新日期类型作为字段,而不会破坏现有代码?
- 您如何处理在JPA中转换到新的日期/时间API?
更新:
然而,至少使用EclipseLink时,存在自定义类型的AttributeConverter,并不完全受支持:
在JPQL查询中,实际字段类型和转换后的数据库类型都不能用作参数。
当使用转换后的数据库类型时,会出现上述异常。
当使用实际字段类型(例如LocalDate
)时,它会直接传递给不知道此类型的jdbc驱动程序:
Caused by: java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:10495)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9974)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:10799)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:10776)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:241)
at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.setParameterValueInDatabaseCall(DatabasePlatform.java:2506)
我希望EclipseLink使用AttributeConverter将字段类型转换为java.sql类型。(请参见此错误报告: https://bugs.eclipse.org/bugs/show_bug.cgi?id=494999)
这导致了最重要的问题#4:
4.是否有解决方案来支持使用
EclipseLink
的java 8日期字段,包括在此类字段上使用查询参数的可能性?
附加信息
AttributeConverter
的目标类型需要是一个java.sql
类型(尽管java.util.Date
作为实体字段完美地工作)。现在简单的查询可以工作了。但是,当在查询中多次使用同一个参数时,EclipseLink 似乎不会在第一次出现后转换该值,从而导致上述异常。将您的查询调整为"SELECT p FROM MeasuringPoint p WHERE p.when = :custDate AND p.when = :custDate"
可以重现这个问题。 - MRalwasserSELECT p FROM MeasuringPoint p WHERE p.when = :custDate AND p.when -1 = :custDate
? - MRalwasser