Подтвердить что ты не робот

Hibernate 4 с конструкцией java.time.LocalDate и DATE()

Я пытаюсь использовать LocalDate и LocalDateTime с Java 8 в своем приложении. Я использую Hibernate 4.3.5 и Spring. Я выполнил этот интересный учебник здесь, и все работает, но у меня проблема, когда я использую конструкцию DATE().

Когда я пытаюсь сделать:

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

У меня всегда есть пустой список, также если запрос, который я сделал вручную (копирование и прошлый запрос Hibernate print), отлично работает. Я думаю, что проблема заключается в том, что преобразование, которое Hibernate делает внутренне; он пытается преобразовать LocalDate в java.util.Date. Я говорю это, потому что если я изменяю запрос таким образом:

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

У меня есть это исключение:

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)

Я также сделал этот тест:

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);
    }

И к сожалению, DATE (: test) всегда null!!

Любое предложение оценено

Большое спасибо

4b9b3361

Ответ 1

Если вы используете JPA 2.1, это просто сделать. Конвертеры позволяют вашим субъектам JPA использовать новые классы java.time.LocalDate и java.time.LocalDateTime. Просто определите необходимые классы преобразователей:

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

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;
  }
}

И затем аннотируйте соответствующее свойство объекта с аннотацией @Converter:

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

Обновление сентябрь 2015 г.
Hibernate 5 изначально поддерживает API-интерфейс java 8 Date/Time. Просто убедитесь, что hibernate-java8 jar находится на пути вашего класса.

Ответ 2

ХОРОШИЕ НОВОСТИ

Больше нет необходимости в конвертерах в версии 5.0.0.CR2. Согласно официальному сайту, он поддерживает специфические типы данных java8, включая java.time.LocalDate.

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

Улучшена загрузка, hibernate-java8, hibernate-пространственная, поддержка Karaf

Ответ 3

Похоже, что в Hibernate не поддерживаются LocalTime, LocalDate и LocalDateTime. Вы можете, однако добавьте функциональность самостоятельно.

См. http://blog.progs.be/550/java-time-hibernate

Ответ 4

Что вам нужно сделать, так это преобразовать дату в String. Вы даже можете использовать 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);

Вывод:

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