简体   繁体   English

Hibernate 4使用java.time.LocalDate和DATE()构造

[英]Hibernate 4 with java.time.LocalDate and DATE() construct

I'm trying to use LocalDate and LocalDateTime with Java 8 in my app. 我正在尝试在我的应用程序中使用LocalDate和LocalDateTime与Java 8。 I'm using Hibernate 4.3.5 and Spring. 我正在使用Hibernate 4.3.5和Spring。 I followed this interesting tutorial here and all works but I've a problem when I use DATE() construct. 在这里关注了这个有趣的教程,但是当我使用DATE()构造时,我遇到了一个问题。

When I try to do: 当我尝试做的时候:

SELECT * FROM TABLE WHERE DATE(data)=DATE(:data)

I've always an empty list also if the query I made manually (copy and past query Hibernate print) works fine. 如果我手动创建的查询(复制和过去查询Hibernate打印)工作正常,我总是一个空列表。 I think that the problem is the conversion that Hibernate do internally; 我认为问题是Hibernate在内部进行的转换; it try to convert LocalDate to java.util.Date. 它尝试将LocalDate转换为java.util.Date。 I tell this because if I change the query in this way: 我告诉这个,因为如果我以这种方式更改查询:

SELECT * FROM TABLE WHERE DATE(data)=:data

I've this exception: 我有这个例外:

java.lang.IllegalArgumentException: Parameter value [2014-05-27T00:00] did not match expected type [java.util.Date (n/a)]
at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:885)
at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:80)
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:248)
at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:631)
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:180)
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:49)
at it.AppuntamentoCustomRepositoryImpl.findAppuntamenti(AppuntamentoCustomRepositoryImpl.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:64)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy91.findAppuntamenti(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.granite.messaging.service.ServiceInvocationContext.invoke(ServiceInvocationContext.java:72)
at org.granite.messaging.service.security.AbstractSecurityService.endAuthorization(AbstractSecurityService.java:104)
at org.granite.spring.security.SpringSecurity3Service.authorize(SpringSecurity3Service.java:289)
at org.granite.messaging.service.ServiceInvoker.invoke(ServiceInvoker.java:220)
at org.granite.messaging.amf.process.AMF3MessageProcessor.processRemotingMessage(AMF3MessageProcessor.java:141)
at org.granite.messaging.amf.process.AMF3MessageProcessor.process(AMF3MessageProcessor.java:60)
at org.granite.messaging.amf.process.AMF0MessageProcessor.process(AMF0MessageProcessor.java:79)
at org.granite.messaging.webapp.AMFEndpoint.serviceJMFAMF(AMFEndpoint.java:151)
at org.granite.messaging.webapp.AMFEndpoint.service(AMFEndpoint.java:64)
at org.granite.spring.ServerFilter.handle(ServerFilter.java:322)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)

I made also this test: 我也做了这个测试:

TypedQuery<Date> test = manager.createQuery("select DATE(:test) FROM Appuntamento", Date.class);

    test.setParameter("test", LocalDate.now());
    for (Date t : test.getResultList()) {
        log.debug("T----------->" + t);
    }

And unfortunally DATE(:test) is always null!! 不幸的是DATE(:test)总是空的!

Any suggestion is appreciated 任何建议表示赞赏

Thanks very much 非常感谢

If you use JPA 2.1 this is simple to do. 如果您使用JPA 2.1,这很简单。 Converters allow your JPA entities to use the new java.time.LocalDate and java.time.LocalDateTime classes. 转换器允许JPA实体使用新的java.time.LocalDatejava.time.LocalDateTime类。 Simply define the needed converter classes: 只需定义所需的转换器类:

LocalDatePersistenceConverter.java LocalDatePersistenceConverter.java

import java.time.LocalDate;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class LocalDatePersistenceConverter implements AttributeConverter<LocalDate, java.sql.Date> {

  @Override
  public java.sql.Date convertToDatabaseColumn(LocalDate entityValue) {
    if (entityValue != null) {
      return java.sql.Date.valueOf(entityValue);
    }
    return null;
  }

  @Override
  public LocalDate convertToEntityAttribute(java.sql.Date databaseValue) {
    if (databaseValue != null) {
      return databaseValue.toLocalDate();
    }
    return null;
  }
}

LocalDateTimePersistenceConverter.java LocalDateTimePersistenceConverter.java

import java.time.LocalDateTime;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class LocalDateTimePersistenceConverter implements AttributeConverter<LocalDateTime, java.sql.Timestamp> {

  @Override
  public java.sql.Timestamp convertToDatabaseColumn(LocalDateTime entityValue) {
    if (entityValue != null) {
      return java.sql.Timestamp.valueOf(entityValue);
    }
    return null;
  }

  @Override
  public LocalDateTime convertToEntityAttribute(java.sql.Timestamp databaseValue) {
    if (databaseValue != null) {
      return databaseValue.toLocalDateTime();
    }
    return null;
  }
}

And then annotate the appropriate entity property with the @Converter annotation: 然后使用@Converter注释注释适当的实体属性:

@Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate completedDate;

Update September 2015 2015年9月更新
Hibernate 5 natively supports the java 8 Date/Time APIs. Hibernate 5本身支持java 8 Date / Time API。 Just ensure that the hibernate-java8 jar is on your class path. 只需确保hibernate-java8 jar在您的类路径上。

GOOD NEWS 好消息

There is no longer need for converters in the 5.0.0.CR2 development version. 5.0.0.CR2开发版中不再需要转换器。 According to the official site, it supports the java8 specific data types, including java.time.LocalDate. 根据官方网站,它支持java8特定的数据类型,包括java.time.LocalDate。

http://hibernate.org/orm/downloads/ http://hibernate.org/orm/downloads/

Improved bootstrapping, hibernate-java8 , hibernate-spatial, Karaf support 改进了bootstrapping, hibernate-java8 ,hibernate-spatial,Karaf支持

It appears that LocalTime, LocalDate, and LocalDateTime are not supported in Hibernate. Hibernate似乎不支持LocalTime,LocalDate和LocalDateTime。 You can, However add the functionality yourself. 但是,您可以自己添加功能。

See http://blog.progs.be/550/java-time-hibernate 请参见http://blog.progs.be/550/java-time-hibernate

What you've got to do is convert the date into String. 你要做的是将日期转换为String。 You may even use the java.time.LocalDate or java.time.LocalDateTime. 您甚至可以使用java.time.LocalDate或java.time.LocalDateTime。

LocalDateTime myDate = LocalDateTime.of(2015, 04, 30, 15, 43, 12);

int numberOfIdOfDate = ((Long) session.createQuery(
   "SELECT count(*) FROM domain.PromoCard WHERE CREATE_DATE= :my_date")
   .setParameter("my_date", myDate.toString())
   .uniqueResult()).intValue();

log.info("Count of records with date '{}' is {}", myDate, numberOfIdOfDate);

Output: 输出:

[main] INFO myhibernate.PromoCardTest - Count of records with date '2015-04-30 15:43:12' is 6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM