JPA 2.1:Java 8日期/时间API简介

MRa*_*ser 10 java hibernate jpa eclipselink jpa-2.1

我想在我的JPA应用程序中添加Java 8 Date/Time API(JSR-310)的支持.

很明显,JPA 2.1 不支持Java 8 Date/Time API.
作为一种解决方法,最常见的建议是使用AttributeConverter.

在我现有的应用程序中,我将实体更改为使用LocalDate/ LocalDateTimetypes作为列映射字段,并为其添加了旧的setter/getter java.util.Date.
我创建了相应的AttributeConverter类.

我的应用程序现在无法使用时,Query.setParameter()java.util.Date实例(它过渡到新的API工作之前).
似乎JPA期望新的日期类型并且不会动态转换它.

我希望如果将参数传递给已注册setParameter()的类型AttributeConverter,它将由转换器自动转换.但似乎并非如此,至少不使用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]
  [...]
Run Code Online (Sandbox Code Playgroud)


问题:

  1. 这种行为有望吗?我错过了什么?
  2. 有没有办法不破坏现有代码的情况下将新日期类型用作字段?
  3. 您是如何处理 JPA中新的Date/Time 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)
Run Code Online (Sandbox Code Playgroud)

我希望EclipseLink使用AttributeConverter将字段类型转换为java.sql类型.(另见此错误报告:https://bugs.eclipse.org/bugs/show_bug.cgi?id = 494999)

这引出了我们最重要的问题#4:

  1. 是否有解决方案/解决方案来支持使用java 8日期字段EclipseLink,包括在这样的字段上使用查询参数的可能性

附加信息

Rog*_*rio 4

前段时间,我将一个 Java EE 7 Web 应用程序从 Java 7 转换为 Java 8,并java.util.Date在实体中替换为LocalDateLocalDateTime

  1. 是的,这种行为是预期的,因为 anAttributeConverter只在实体字段使用的类型和数据库类型(即java.sql.Date等)之间进行转换;它不会在实体字段类型和java.util.Date查询参数中使用的字段类型之间进行转换。
  2. 据我所知,不,在将类型引入 JPA 实体后,无法继续java.util.Date在现有代码中使用。java.time
  3. 除了创建必要的AttributeConverter实现之外,我还将所有出现的 更改java.util.Date为适当的java.time类型,不仅在实体中,而且在 JPA-QL 查询和业务方法中。

对于第 2 项,您当然可以通过使用在java.util和之间转换的实用程序方法和 getter/setter 来实现某种目的java.time,但它不会一直有效java.time更重要的是,如果您不愿意转换使用这些属性的其余代码,我不太明白将类型引入JPA 实体属性的意义。在我在 Java EE 应用程序中完成转换工作之后,任何地方都没有使用java.util.Dateleft(尽管我还必须为 JSF 创建转换器)。