Hot questions for Using Joda-Time in hibernate

Question:

I have weird problem when storing DateTime in database using hibernate and joda time.

I have a bean like this :

import org.joda.time.DateTime;

public class RelationshipEntity  {

    @Column(name = "date_revision")
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime dateRevision;

    // other fields
}

I have set the timezone to Europe/Paris (GMT+1) in the application with TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));

If I save the entity with a revision date to 2017-01-19 13:24 into the database, I can see the date in the database has been set to 2017-01-19 12:24 and I don't understand why.

The database timezone also seems to be Europe/Paris because :

SELECT SYSDATETIME(); //2017-01-19 14:41

SELECT SYSUTCDATETIME(); // 2017-01-19 13:41

As I use spring-boot I tried to add theses properties in application.yml

jadira.usertype.autoRegisterUserTypes: true
jadira.usertype.databaseZone: jvm
jadira.usertype.javaZone: jvm  

and start the application with the argument -Duser.timezone=Europe/Paris but it still saves the date in UTC into the database.

To solve the problem I changed DateTime to LocalDateTime :

@Column(name = "date_revision")
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private DateLocalTime dateRevision;

With this change, the dateRevision in the database is the same I set in my java bean.

Can someone explain me why it converts the date to UTC when I use the type org.joda.time.DateTime ?

NOTE : I use Hibernate 4 and joda-time 2.5


Answer:

This is because zoda DateTime store the date in db in UTC and LocalDateTime stores the date as it is and should be used when you do not care about the time zone.

In case of DateTime when you need to consider time zones (day light savings etc) it handles it that way and stores the date in Universal time.

Please refer this answer for detailed info.

Question:

I have a problem with Joda Time and Hibernate, in my Spring application. I currently use the following settings:

def springVersion = '3.2.12.RELEASE'
def hibernateVersion = '4.2.16.Final'
def jodaTimeVersion = '2.6'
compile "org.hibernate:hibernate-core:$hibernateVersion"
compile "org.hibernate:hibernate-entitymanager:$hibernateVersion"
compile "org.hibernate:hibernate-envers:$hibernateVersion"
testCompile "org.hibernate.common:hibernate-commons-annotations:4.0.5.Final"
compile "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final"

compile "joda-time:joda-time:$jodaTimeVersion"
compile "org.jadira.usertype:usertype.jodatime:2.0.1"
testCompile "org.jadira.usertype:usertype.core:3.2.0.GA"
testCompile "org.jadira.usertype:usertype.spi:3.2.0.GA"

Everything runs smooth when compiling and deploying the app. However, when i try to execut jUnit tests, i got the following error:

java.lang.NoClassDefFoundError: Could not initialize class org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator

Full stack trace is below:

 java.lang.IllegalStateException: Failed to load ApplicationContext
        at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:103)
        at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
        at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
        at org.junit.runners.Suite.runChild(Suite.java:127)
        at org.junit.runners.Suite.runChild(Suite.java:26)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.junit.runners.Suite.runChild(Suite.java:127)
        at org.junit.runners.Suite.runChild(Suite.java:26)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:48)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
        at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at $Proxy2.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:105)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
        at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [test_applicationContext.xml]: Invocation of init method failed; nested exception is java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator could not be instantiated: java.lang.NoClassDefFoundError: Could not initialize class org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1514)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1119)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:924)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:120)
        at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
        at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:102)
        at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:246)
        at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:69)
        at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:95)
        ... 60 more
    Caused by: java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator could not be instantiated: java.lang.NoClassDefFoundError: Could not initialize class org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator
        at java.util.ServiceLoader.fail(ServiceLoader.java:207)
        at java.util.ServiceLoader.access$100(ServiceLoader.java:164)
        at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:360)
        at java.util.ServiceLoader$1.next(ServiceLoader.java:428)
        at org.hibernate.service.classloading.internal.ClassLoaderServiceImpl.loadJavaServices(ClassLoaderServiceImpl.java:246)
        at org.hibernate.integrator.internal.IntegratorServiceImpl.<init>(IntegratorServiceImpl.java:53)
        at org.hibernate.service.BootstrapServiceRegistryBuilder.build(BootstrapServiceRegistryBuilder.java:188)
        at org.hibernate.ejb.Ejb3Configuration.buildLifecycleControledServiceRegistry(Ejb3Configuration.java:935)
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914)
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:900)
        at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:76)
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:290)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1573)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)
        ... 75 more
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.jadira.usertype.dateandtime.joda.integrator.UserTypeJodaTimeHibernateIntegrator
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at java.lang.Class.newInstance0(Class.java:355)
        at java.lang.Class.newInstance(Class.java:308)
        at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:356)
        ... 87 more

Answer:

compile "org.jadira.usertype:usertype.jodatime:2.0.1"
testCompile "org.jadira.usertype:usertype.core:3.2.0.GA"
testCompile "org.jadira.usertype:usertype.spi:3.2.0.GA"

You have multiple versions of the jadira jodatime library, one is compile time the other testCompile. Which is strange to start with.

Remove the old one and change testCompile to compile.

compile "org.jadira.usertype:usertype.core:3.2.0.GA"
compile "org.jadira.usertype:usertype.spi:3.2.0.GA"

Question:

I want to apply multiple criteria query Operator to fetch the data according to the timestamp

public List<Notification> getNotificationByTime(long notificationTime) {

    return mongoTemplate.find(new Query(Criteria.where("createdAt").lte(notificationTime).
        orOperator(Criteria.where("updatedAt")
            .lte(notificationTime)).orOperator(Criteria.where("failureTime").gt(3))
            ), Notification.class);
  }

exception

org.quartz.SchedulerException: Job threw an unhandled exception.
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.2.3.jar:na]
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.3.jar:na]
Caused by: org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second '$or' expression specified as '$or : [ { "failureTime" : { "$gt" : 3}}]'. Criteria already contains '$or : [ { "updatedAt" : { "$lte" : 1549709060838}}]'.
    at org.springframework.data.mongodb.core.query.Criteria.setValue(Criteria.java:710) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.mongodb.core.query.Criteria.getCriteriaObject(Criteria.java:643) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.mongodb.core.query.Query.getQueryObject(Query.java:230) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:771) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:757) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at io.dzone.manager.repository.impl.NotificationRepositoryImpl.getNotificationByTime(NotificationRepositoryImpl.java:21) ~[classes/:na]
    at io.dzone.manager.repository.impl.NotificationRepositoryImpl$$FastClassBySpringCGLIB$$f3a229a6.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at io.dzone.manager.repository.impl.NotificationRepositoryImpl$$EnhancerBySpringCGLIB$$c3b0276d.getNotificationByTime(<generated>) ~[classes/:na]
    at io.dzone.manager.service.impl.NotificationServiceImpl.getNotificationDataByTime(NotificationServiceImpl.java:123) ~[classes/:na]
    at io.dzone.manager.job.NotificationJob.executeInternal(NotificationJob.java:36) ~[classes/:na]
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75) ~[spring-context-support-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.3.jar:na]
    ... 1 common frames omitted

Answer:

public List<Notification> getNotificationByTime(long notificationTime) {

    return mongoTemplate.find(new Query(Criteria.where("createdAt").lte(notificationTime),
        Criteria.where("updatedAt").lte(notificationTime)),Criteria.where("failureTime").gt(3)
            ), Notification.class);
  }

this must work. Everything inside the parenthesis is getting ored :)

Question:

Simplified examples

I run a native query with date in it:

SELECT id, start FROM event;

I did a SqlResultSetMapping like:

@SqlResultSetMapping(
        name="EventMapping",
        classes={
                @ConstructorResult(
                        targetClass=de.teamsystems.domain.OverviewEvent.class,
                        columns={
                                @ColumnResult(name="id", type = Long.class ),    
                                @ColumnResult(name="start", type = DateTime.class )

                        }
                )
        }
)

And my OverviewEvent class looks like:

@Entity
public class OverviewEvent  {

    @Id
    private Long id;

    private String name;


    private DateTime start;

    public Long getId() {
        return id;
    }

    public DateTime getStart() {
        return start;
    }

    public OverviewEvent(Long id, DateTime start) {
        this.id = id;
        this.start = start;
    }

}

When I execute this code in my controller, I get the following exception:

{
    "error": "Internal Server Error",
    "exception": "javax.persistence.PersistenceException",
    "message": "org.hibernate.type.SerializationException: could not deserialize",
    "path": "/event",
    "status": 500,
    "timestamp": "2017-03-13T22:22:30.527+0100"
}

The log files say:

2017-03-13 22:22:30.523 ERROR 23479 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.type.SerializationException: could not deserialize] with root cause

java.io.StreamCorruptedException: invalid stream header: 32303137
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:808) ~[na:1.8.0_111]

When I change the DateTime into String in the OverviewEvent class and in the SqlResultSetMapping, it works. But I would like to work with the datetime format.

Does anyone can help me with that exception. I tried different things such as:

@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private DateTime start;

But the exception stayed the same. Thanks for helping me out.


Answer:

Try using Date (java.util.Date) instead of DateTime:

  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
  private Date start;

or create a custom de/serializer for DateTime.

Question:

I am having issue storing a date while converting it from String to Date Time.

Below is the code,

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

String date1 = "2017-11-02";

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");

someHibernateMethod.setTransactionDate1(formatter.parseDateTime(date1));
someHibernateMethod.setTransactionDate2(DateTime.now());

date1 saved as - "2017-11-01 19:00:00.000", but when I save date with DateTime.Now() it saves correctly.

I am expecting "2017-11-02 00:00:00.000" for date1


Answer:

Found a solution as below,

String date1 = "2017-11-02";

DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
LocalDate localDate = formatter.parseLocalDate(date1);
DateTime newDate= localDate.toDateTime(new LocalTime());
someHibernateMethod.setTransactionDate1(newDate)