JPA 2.1:引入Java 8日期/时间API [英] JPA 2.1: Introducing Java 8 Date/Time API

查看:187
本文介绍了JPA 2.1:引入Java 8日期/时间API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在支持JPA的应用程序中为 Java 8日期/时间API(JSR-310)添加支持

>

很明显, JPA 2.1 不支持Java 8日期/时间API

作为一种解决方法,最常见的建议是使用 AttributeConverter

应用程序中,我更改了我的实体为列映射字段使用 LocalDate / LocalDateTime 类型,并添加了旧版setter / getters java.util.Date 给它们。

我创建了相应的 AttributeConverter 类。



使用 Query.setParameter() > java.util.Date 实例(它在转换到t之前工作他新的API)。
JPA预计新的日期类型并不会即时转换它。


我期望如果传递参数 setParameter(),其中 AttributeConverter 已被注册,它会自动转换为转换器。
但是这似乎并非如此,至少没有使用 EclipseLink 2.6.2

  java.lang.IllegalArgumentException:您试图从查询字符串中为参数closeDate设置类java.util.Date的值,类型为java.time.LocalDate的期望类型SELECT obj FROM [ ...] 
在org.eclipse.persistence.internal.jpa.QueryImpl.setParameterInternal(QueryImpl.java:937)〜[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
在org.eclipse.persistence.internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:593)〜[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
在org.eclipse.persistence .internal.jpa.EJBQueryImpl.setParameter(EJBQueryImpl.java:1)〜[eclipselink-2.6.2.jar:2.6.2.v20151217-774c696]
[...]




问题


  1. 预期此行为 我错过了什么吗? 有没有方式可以使用新日期类型作为字段而不会破坏现有代码
  2. >
  3. 在JPA内转换为新的日期/时间API时,您是如何处理的?





UPDATE: 然而,至少使用EclipseLink,自定义类型为什么 AttributeConverter 不存在,不完全支持:


在JPQL查询中,既不是实际字段类型也不是转换后的数据库类型可以用作参数
使用转换后的数据库类型时,会发生上述异常。
当使用实际的字段类型(例如 LocalDate )时,它直接传递给不知道这种类型的jdbc驱动程序:

 原因:java.sql.SQLException:无效列类型
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将字段类型转换为th e使用AttributeConverter的java.sql类型。
(另请参阅此错误报告: https://bugs.eclipse .org / bugs / show_bug.cgi?id = 494999

这导致我们遇到了最重要的问题#4:


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

其他信息


解决方案

前段时间,我将Java EE 7 Web应用程序从Java 7转换为Java 8,在实体wi中替换 java.util.Date th LocalDate LocalDateTime


  1. 是的,因为 AttributeConverter 只会在用于实体字段的类型和数据库类型之间转换(即 java.sql.Date 等);它不会在查询参数中使用的实体字段类型和 java.util.Date 之间进行转换。

  2. 至于I知道,不,在介绍 java.time java.util.Date c>类型到JPA实体中。
  3. 除了创建必要的 AttributeConverter 实现之外,我更改了所有出现的 java .util.Date 添加到适当的 java.time 类型中,不仅在实体中,而且在JPA-QL查询和业务方法中。

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


I'd like to add support for the Java 8 Date/Time API (JSR-310) in my JPA-enabled application.

It's clear that JPA 2.1 does not support the Java 8 Date/Time API.
As a workaround, the most common advise is to use an AttributeConverter.

In my existing application, I changed my entities to use LocalDate/LocalDateTime types for the column mapping fields and added legacy setter/getters for java.util.Date to them.
I created corresponding AttributeConverter classes.

My application does now fail when using Query.setParameter() with java.util.Date instances (it worked before the transition to the new API).
It seems that JPA expects the new date types and does not convert it on the fly.

I expected that if passing an argument to setParameter() of a type for which an AttributeConverter has been registered, it would be automatically converted by the converter. But this seems to be not the case, at least not using 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]
  [...]


Questions:

  1. Is this behavior expected? Did I miss something?
  2. Is there a way to use the new date types as fields without breaking existing code?
  3. How did you deal with the transition to the new Date/Time API within JPA?


UPDATE:

However, It seems that at least using EclipseLink, custom types for which an AttributeConverter exists, are not fully supported:

Within JPQL queries, neither the actual field type nor the converted database type can be used as a parameter. When using the converted database type, the exception described above occurs. When using the actual field type (e.g. LocalDate), it's directly passed to the jdbc driver which doesn't know this type:

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)

I would expect that EclipseLink converts the field type to the java.sql type using the AttributeConverter. (see also this bug report: https://bugs.eclipse.org/bugs/show_bug.cgi?id=494999 )

Which leads us to the most important question #4:

  1. Is there a workaround/solution to support java 8 date fields using EclipseLink, including the possibility to use a query parameters on such a field?

ADDITIONAL INFO

解决方案

Some time ago, I converted a Java EE 7 web app from Java 7 to Java 8, and replaced java.util.Date in entities with LocalDate and LocalDateTime.

  1. Yes, that behavior is expected, because an AttributeConverter only converts between the type used for entity fields and the database type (ie, java.sql.Date, etc.); it does not convert between an entity field type and a java.util.Date used in a query parameter.
  2. As far as I know, no, there is no way to continue using java.util.Date in existing code, after introducing the java.time types into JPA entities.
  3. Besides creating the necessary AttributeConverter implementations, I changed all occurrences of java.util.Date to the appropriate java.time types, not only in entities but also in JPA-QL queries and in business methods.

For item 2, of course you can go some way by using utility methods and getters/setters that convert between java.util and java.time, but it's not going to go all the way. More importantly, I don't quite see the point of introducing java.time types into JPA entity attributes, if you are not willing to convert the remaining code that uses these attributes. After the conversion work I did in that Java EE app, there were no uses of java.util.Date left anywhere (though I also had to create converters for JSF).

这篇关于JPA 2.1:引入Java 8日期/时间API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆