I'm trying to use LocalDate and LocalDateTime with Java 8 in my app. I'm using Hibernate 4.3.5 and Spring. I followed this interesting tutorial here and all works but I've a problem when I use DATE() construct.
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. I think that the problem is the conversion that Hibernate do internally; it try to convert LocalDate to 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!!
Any suggestion is appreciated
Thanks very much
If you use JPA 2.1 this is simple to do. Converters allow your JPA entities to use the new java.time.LocalDate
and java.time.LocalDateTime
classes. Simply define the needed converter classes:
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;
}
}
And then annotate the appropriate entity property with the @Converter annotation:
@Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate completedDate;
Update September 2015
Hibernate 5 natively supports the java 8 Date/Time APIs. Just ensure that the hibernate-java8 jar is on your class path.
GOOD NEWS
There is no longer need for converters in the 5.0.0.CR2 development version. According to the official site, it supports the java8 specific data types, including java.time.LocalDate.
http://hibernate.org/orm/downloads/
Improved bootstrapping, hibernate-java8, hibernate-spatial, Karaf support
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With