jadiraorg / jadira Goto Github PK
View Code? Open in Web Editor NEWJadira Framework
License: Apache License 2.0
Jadira Framework
License: Apache License 2.0
PersistentDateTimeAndZone
throws org.joda.time.IllegalInstantException
during daylight davings time 'gap'. It seems the logic to convert the instant from specified timezone to system timezone to UTC is incorrect in such cases.
This has been discussed before, it seems this need fixing for DateTime
as well:
Thanks for the new version.
In my opinion the conversion from Date to LocalDate in 3.0.0CR1 (and also older versions) is incorrect.
The current implementation takes timezones in account but a LocalDate has no timezone. DateColumnLocalDateMapper converts a date to a string and then convert this to a DateTime:DateTimeZone.setDefault(DateTimeZone.forID("Europe/Amsterdam")); new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd").toFormatter().parseDateTime("1916-05-01")
This results in java.lang.IllegalArgumentException: Cannot parse "1916-05-01": Illegal instant due to time zone offset transition (Europe/Amsterdam).
Correct code should be: new LocalDate("1916-05-01"). LocalDate is aware that timezones should not be accounted for and correctly transforms the date.
March 15, 2012 | Paul Middelkoop
Thanks for the feedback. I have tested and can reproduce the issue. It seems to apply only to certain historical dates (I think where the timezone offset has changed), although it could arise in the future. The fix is in svn and will go into the next release.March 17, 2012 | Chris (@chrisphe)
The DateTime
property:
@Basic()
@Columns(columns = { @Column(name = "creationtime", nullable = false),
@Column(name = "creationtime_zone", nullable = false) })
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeAndZone")
private DateTime creationTime = null;
Test case:
creationTime
property value that triggers bug: 2014-03-09T09:59:18.628+07:00
2014-03-09T02:59:18.628Z
2014-03-08T20:59:18.628-06:00
Tue Jul 15 03:16:59 CDT 2014
using System timezone: America/Winnipeg
SQL:
/* insert id.co.bippo.schema.inventorybalance._1.StockReservationLine
*/ insert
into
StockReservationLine
(creationtime, creationtime_zone, modificationtime, modificationtime_zone, origin_id, positioner, product_currency, product_description, product_id, product_listingimageid, product_localsku, product_name, product_price, product_primaryimageid, product_qtyunit, product_shop_id, product_shop_name, product_shop_photoid, product_shop_slug, product_sideimageid, product_sku, product_slug, product_type, qty, qtyunit, stockreservation_id, variant_barcode, variant_currency, variant_description, variant_id, variant_key1, variant_key2, variant_key3, variant_key4, variant_key5, variant_listingimageid, variant_localsku, variant_name, variant_price, variant_primaryimageid, variant_qtyunit, variant_sideimageid, variant_sku, variant_slug, variant_value1, variant_value2, variant_value3, variant_value4, variant_value5, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Error:
org.springframework.dao.InvalidDataAccessApiUsageException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2014-03-09T08:59:18.628 (America/Winnipeg); nested exception is org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2014-03-09T08:59:18.628 (America/Winnipeg)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:157) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:519) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at com.sun.proxy.$Proxy137.add(Unknown Source) ~[$Proxy137.class:na]
at id.co.bippo.inventory.shell.InsertStockReservationTestCommand.doExecute(InsertStockReservationTestCommand.java:88) ~[classes/:na]
at org.apache.karaf.shell.console.AbstractAction.execute(AbstractAction.java:33) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at org.soluvas.commons.shell.ExtCommandSupport.execute(ExtCommandSupport.java:86) ~[classes/:na]
at org.apache.felix.gogo.commands.basic.AbstractCommand.execute(AbstractCommand.java:35) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:477) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:403) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.karaf.shell.console.jline.Console.run(Console.java:172) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
at blast.shell.karaf.ssh.BlastShellFactoryImpl$ShellImpl$2.doRun(BlastShellFactoryImpl.java:130) [blast-shell-karaf-ssh-0.13.jar:na]
at blast.shell.karaf.ssh.BlastShellFactoryImpl$ShellImpl$2.run(BlastShellFactoryImpl.java:125) [blast-shell-karaf-ssh-0.13.jar:na]
Caused by: org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2014-03-09T08:59:18.628 (America/Winnipeg)
at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:142) ~[joda-time-2.3.jar:2.3]
at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:118) ~[joda-time-2.3.jar:2.3]
at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133) ~[joda-time-2.3.jar:2.3]
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:254) ~[joda-time-2.3.jar:2.3]
at org.joda.time.DateTime.<init>(DateTime.java:516) ~[joda-time-2.3.jar:2.3]
at org.joda.time.LocalDateTime.toDateTime(LocalDateTime.java:742) ~[joda-time-2.3.jar:2.3]
at org.joda.time.LocalDateTime.toDateTime(LocalDateTime.java:727) ~[joda-time-2.3.jar:2.3]
at org.jadira.usertype.dateandtime.joda.columnmapper.TimestampColumnLocalDateTimeMapper.toNonNullValue(TimestampColumnLocalDateTimeMapper.java:64) ~[usertype.core-3.1.0.GA.jar:na]
at org.jadira.usertype.dateandtime.joda.columnmapper.TimestampColumnLocalDateTimeMapper.toNonNullValue(TimestampColumnLocalDateTimeMapper.java:29) ~[usertype.core-3.1.0.GA.jar:na]
at org.jadira.usertype.spi.shared.AbstractMultiColumnUserType.nullSafeSet(AbstractMultiColumnUserType.java:160) ~[usertype.spi-3.1.0.GA.jar:na]
at org.hibernate.type.CompositeCustomType.nullSafeSet(CompositeCustomType.java:234) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3121) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at com.sun.proxy.$Proxy137.add(Unknown Source) ~[$Proxy137.class:na]
at id.co.bippo.inventory.shell.InsertStockReservationTestCommand.doExecute(InsertStockReservationTestCommand.java:88) ~[classes/:na]
at org.apache.karaf.shell.console.AbstractAction.execute(AbstractAction.java:33) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at org.soluvas.commons.shell.ExtCommandSupport.execute(ExtCommandSupport.java:86) ~[classes/:na]
at org.apache.felix.gogo.commands.basic.AbstractCommand.execute(AbstractCommand.java:35) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:477) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:403) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89) ~[org.apache.felix.gogo.runtime-0.10.0.jar:na]
at org.apache.karaf.shell.console.jline.Console.run(Console.java:172) ~[org.apache.karaf.shell.console-2.2.9.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
at blast.shell.karaf.ssh.BlastShellFactoryImpl$ShellImpl$2.doRun(BlastShellFactoryImpl.java:130) [blast-shell-karaf-ssh-0.13.jar:na]
at blast.shell.karaf.ssh.BlastShellFactoryImpl$ShellImpl$2.run(BlastShellFactoryImpl.java:125) [blast-shell-karaf-ssh-0.13.jar:na]
... 22 more
Tag @ceefour
Entity:
@Entity
public class Promo {
@Type(type = "org.jadira.usertype.corejava.PersistentEnum", parameters = @Parameter(name = "enumClass", value = "id.co.bippo.common.PromoKind"))
private PromoKind kind = null;
@Type(type = "org.jadira.usertype.corejava.PersistentEnum", parameters = @Parameter(name = "enumClass", value = "id.co.bippo.promotion.jpa.PromoScope"))
private PromoScope scope = null;
To use NEW with the following class:
public class PromoWithPositioner {
public PromoWithPositioner(UUID id, PromoKind kind, @Nullable PromoScope scope, Integer positioner) {
super();
this.id = id;
this.kind = kind;
this.scope = scope;
this.positioner = positioner;
}
and the following query:
final String query = "SELECT NEW id.co.bippo.promotion.impl.PromoWithPositioner(p.id, p.kind, p.scope, p.positioner)"
+ " FROM Promo p";
final List<PromoWithPositioner> unsorted = em.createQuery(query, PromoWithPositioner.class).getResultList();
Hibernate complains:
org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [id.co.bippo.promotion.impl.PromoWithPositioner]. Expected arguments are: java.util.UUID, java.lang.Enum, java.lang.Enum, int [SELECT NEW id.co.bippo.promotion.impl.PromoWithPositioner(p.id, p.kind, p.scope, p.positioner) FROM id.co.bippo.promotion.jpa.Promo p]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:91)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:109)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:284)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1800)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:342)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291)
at com.sun.proxy.$Proxy141.createQuery(Unknown Source)
at id.co.bippo.promotion.impl.JpaPromoRepository.findAllWithPositioner(JpaPromoRepository.java:426)
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.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:267)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy149.findAllWithPositioner(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:435)
at com.sun.proxy.$Proxy191.findAllWithPositioner(Unknown Source)
at id.co.bippo.promotion.web.ActionPromoLinkPanel$2.onClick(ActionPromoLinkPanel.java:90)
IMHO this is not correct, as when getting e.g. p.kind
Hibernate knows that it is using user type PersistentEnum[enumClass=id.co.bippo.promotion.jpa.PromoKind]
, and getMappedClass()
returns id.co.bippo.promotion.jpa.PromoKind
.
However, returnedClass()
should return getMappedClass()
instead:
@Override
public Class<Enum<?>> returnedClass() {
return (Class<Enum<?>>) getMappedClass();
}
There is a workaround, which uses Hibernate's expected signature:
public PromoWithPositioner(UUID id, Enum<PromoKind> kind, @Nullable Enum<PromoScope> scope, Integer positioner) {
super();
this.id = id;
this.kind = (PromoKind) kind;
this.scope = (PromoScope) scope;
this.positioner = positioner;
}
Tag @ceefour
Running project with Spring 4.0.5 + Hibernate 4.3.5 + UserType 3.2.0 on Tomcat 7.0 + Oracle JDK 1.8.0_05 throws the following error:
16:35:57.658 ERROR | | | | host-startStop-1 | o.a.c.c.C.[.[.[/] | Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'commercePU' defined in class id.co.bippo.common.BippoJpaConfig: Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:482) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) ~[spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797) [catalina.jar:7.0.37]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291) [catalina.jar:7.0.37]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.37]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [catalina.jar:7.0.37]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [catalina.jar:7.0.37]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_05]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
Caused by: java.lang.NullPointerException: null
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.use42Api(AbstractUserTypeHibernateIntegrator.java:80) ~[usertype.spi-3.2.0.GA.jar:na]
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.integrate(AbstractUserTypeHibernateIntegrator.java:61) ~[usertype.spi-3.2.0.GA.jar:na]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:312) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
... 22 common frames omitted
Project runs fine with UserType 3.1.0.
Probably related to https://jadira.atlassian.net/browse/JDF-81
Tag @ceefour
This issue could be considered a reopen of a JDF-71 since I was unable to reopen it or report anything in JIRA.
Versions prior to the commit below do not have this issue:
[https://github.com/JadiraOrg/jadira/commit/a9bd21f]
Following libs and software are in use in project, where issue is reproducible:
joda-time 2.3
spring-data-jpa 1.4.2.RELEASE
hibernate-entitymanager, hibernate-core 4.2.1.Final
mysql-connector-java 5.1.29 (most recent available, there is no such version as 6.1.6 in repos anywhere)
JVM ( "1.7.0_45" Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)) is running in UTC+2
MySQL DB (5.5.35) is running in UTC+2
DDL of a table where data is to be stored looks like this:
ALTER TABLE `something` ADD COLUMN (`date_created_utc` DATETIME DEFAULT NULL, `date_updated_utc` DATETIME DEFAULT NULL);
Mapping for entities looks like this:
@Column(name = "date_created_utc")
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime",
parameters = {
@Parameter(name = "databaseZone", value = "UTC"),
@Parameter(name = "javaZone", value = "UTC")
})
protected DateTime dateCreatedUtc = DateTime.now(DateTimeZone.forID("UTC"));
@Column(name = "date_updated_utc")
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime",
parameters = {
@Parameter(name = "databaseZone", value = "UTC"),
@Parameter(name = "javaZone", value = "UTC")
})
protected DateTime dateUpdatedUtc;
@PreUpdate
public void preUpdate() {
dateUpdatedUtc = DateTime.now(DateTimeZone.forID("UTC"));
}
is that DB wil have timestamps in UTC stored when such entities get created/updated.
I.e. I execute create and update at 13:10 (UTC+2) and the value I expect to see in the database is 11:10(which I know is correct UTC equivalent of that moment of time).
However value 13:10 is inserted. Which is supported by logs and could be checked via performing select from console.
In other words attempts to save or update such entities result in wrong timestamps written into the database (according to the DB log of incoming requests).
The strange thing is that reading such a timestamp back from the entity via spring-data-jpa repositories still produces correct DateTime, which is 11:10 with the TZ set to UTC.
Using version of jadira prior to [https://github.com/JadiraOrg/jadira/commit/a9bd21f] results in expected behaviour and does not produce issue described.
First, thank you so much for the amazing framework.
After our project upgrade jadira from 3.1.0.CR8 to 3.2.0.GA, we have issue of convert localDate to Date. We have both Sql Server database and Java Applicatoin running on 'NZ' timezone, and we set both 'jadira.usertype.databaseZone' and 'jadira.usertype.javaZone' to 'UTC'. After upgrade to 3.2.0.GA we found the date type column will be the localDate value minus one day. e.g. try to update one date column with localDate '2015-03-27' then the value insert into database is actually '2015-03-26'
After I checked the source code of jadira, I found the fromNonNullValue and toNonNullValue methods of DateColumnLocalDateMapper don't really respect the databaseZone. e.g. fromNonNullValue method is
@OverRide
public Date toNonNullValue(LocalDate value) {
if (databaseZone == null) {
return Date.valueOf(LOCAL_DATE_FORMATTER.print((LocalDate) value));
}
DateTime zonedValue = value.toDateTime(value.toDateTimeAtStartOfDay());
final Date date = new Date(zonedValue.getMillis());
return date;
}
it is not a problem if jadira does the same as 3.1.0.CR8 that using 'PreparedStatement.setDate(index, javaTypeDescriptor.unwrap...)' to set date value. However new version jadira using 'PreparedStatement.setDate(index, javaTypeDescriptor.unwrap...,Calendar), and here the Calendar holds the TZ information which is 'jadira.usertype.databaseZone' setting.
I am not sure whether I explain the problem correctly, or I understand jadira correctly. It would be great if someone could give some feedback. Thanks.
Failed to instantiate org.jadira.usertype.json.jackson.PersistentJsonObjectAsString
as it seems identifierType
of AbstractHeuristicUserType
has to be set.
Running under Jadira 6.0.1.GA.
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: athena] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:967)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at [...]
at dagger.internal.ScopedProvider.get(ScopedProvider.java:46)
at [...]
Caused by: org.hibernate.MappingException: Unable to instantiate custom type: org.jadira.usertype.json.jackson.PersistentJsonObjectAsString
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:207)
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:193)
at org.hibernate.type.TypeFactory.byClass(TypeFactory.java:107)
at org.hibernate.type.TypeResolver.heuristicType(TypeResolver.java:112)
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:440)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:422)
at org.hibernate.mapping.Property.isValid(Property.java:226)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:597)
at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:451)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:889)
... 9 more
Caused by: java.lang.NullPointerException
at org.jadira.usertype.spi.shared.AbstractHeuristicUserType.setParameterValues(AbstractHeuristicUserType.java:59)
at org.jadira.usertype.spi.shared.AbstractKnownClassHeuristicUserType.setParameterValues(AbstractKnownClassHeuristicUserType.java:45)
at org.jadira.usertype.json.jackson.PersistentJsonObjectAsString.setParameterValues(PersistentJsonObjectAsString.java:74)
at org.hibernate.type.TypeFactory.injectParameters(TypeFactory.java:142)
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:203)
The current implementation, as of the 2014-07-15, returns Enum.class as discovered by AbstractReflectionUserType using TypeHelper.getTypeArguments.
That breaks some of hibernate use cases, namely calling a constructor that uses the enumeration from a query.
For example, imagine we had a class similar to:
class UsingEnum {
@Column
@Type(type = "org.jadira.usertype.corejava.PersistentEnum", parameters = {
@Parameter(name = "enumClass", value = "specifically.MyEnum"),
@Parameter(name = "identifierMethod", value = "getCode"),
@Parameter(name = "valueOfMethod", value = "getEnum") })
private MyEnum value;
public UsingEnum(MyEnum value) {...}
}
If I now used a query similar to "select new UsingEnum(u.value) from UsingEnum u", that would not work because PersistentEnum would fail to return the specific enum type and hibernate could not match the constructor.
PeristentEnum should override returnedClass() method as follow:
@Override
@SuppressWarnings("unchecked")
public Class<Enum<?>> returnedClass() {
Class<?> mappedClass = getMappedClass();
if (mappedClass == null) {
throw new IllegalStateException("No mapped class was defined for " + this.getClass().getName());
}
return (Class<Enum<?>>) mappedClass;
}
or similar, according to your coding style/standards.
As @chrisphe was also in the JSR 354 EG, this JSR now Final at 1.0 seems like a good time to consider support for it here. Unlike Date/Time where nearly a dozen alternatives are offered (JodaTime, java.time, ThreeTenBP plus several others from the JDK;-) JodaMoney just is not accepted by the community. I see DateTime usage in projects by financial service providers usually backed by JodaTime, but they prefer BigDecimal and see no use in JodaMoney. Having an official Java standard now this could likely change for JSR 354, so supporting it sounds appealing to Jadira.
The existing PersistentInterval
type requires that you create Hibernate queries using java.util.Date
. It would be nice if we could query using DataTime
instead.
I was going to create a pull request for this but had issues getting master
to build.
Related to #14 .
Additional check is required, at least when using Hibernate 4.2, PostgreSQL82Dialect, tested with PostgreSQL 9.1 and PostgreSQL 9.3:
} else if (identifier instanceof String) { // quirk of PostgreSQL82Dialect? to write we must use PGobject, but to read it returns String??
return Enum.valueOf((Class) getMappedClass(), (String) identifier);
In TimestampColumnDateTimeMapper#toNonNullValue the following adjustment calculation can be found:
int adjustment = TimeZone.getDefault().getOffset(value.getMillis()) - currentDatabaseZone.getOffset(null);
I would expect the adjustment to be 0 if TimeZone.getDefault() and currentDatabaseZone are "Europe/Berlin". But:
DateTimeFormatter dateStringFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm");
DateTime value = dateStringFormat.parseDateTime("2013-09-17 16:00");
System.out.println("value.zone: " + value.getZone());
DateTimeZone currentDatabaseZone = ZoneHelper.getDefault();
System.out.println("db.zone: " + currentDatabaseZone);
TimeZone timeZone = TimeZone.getDefault();
System.out.println("java.zone: " + timeZone.getID() + " dstSavings: " + timeZone.getDSTSavings());
int adjustment = timeZone.getOffset(value.getMillis()) - currentDatabaseZone.getOffset(null);
System.out.println("java.zone.offset: " + timeZone.getOffset(value.getMillis()));
System.out.println("db.zone.offset.null: " + currentDatabaseZone.getOffset(null));
System.out.println("db.zone.offset.value: " + currentDatabaseZone.getOffset(value.getMillis()));
System.out.println("adjustment: " + adjustment);
prints:
value.zone: Europe/Berlin
db.zone: Europe/Berlin
java.zone: Europe/Berlin dstSavings: 3600000
java.zone.offset: 7200000
db.zone.offset.null: 3600000
db.zone.offset.value: 7200000
adjustment: 3600000
If I change the initial date to November, the adjustment is 0 (as expected)
DateTime value = dateStringFormat.parseDateTime("2013-11-17 16:00");
I think the problem is caused by the initial date being before the daylight savings time switch and today is after the daylight savings time switch. If I replace null
with value.getMillis()
I always get a 0 Milliseconds adjustment:
int adjustment = timeZone.getOffset(value.getMillis()) - currentDatabaseZone.getOffset(value.getMillis());
Or am I missing something?
There is a bug in TimestampColumnDateTimeMapper class when dealing with Daylight saving and a non-UTC time zone.
See the unit test below. It should pass, but it fails.
// fixture
final DateTimeZone AMERICA_SAOPAULO_ZONE = DateTimeZone.forID("America/Sao_Paulo");
TimestampColumnDateTimeMapper mapper = new TimestampColumnDateTimeMapper();
mapper.setJavaZone(AMERICA_SAOPAULO_ZONE);
mapper.setDatabaseZone(AMERICA_SAOPAULO_ZONE);
// exercise SUT
Timestamp timestamp = mapper.toNonNullValue(new DateTime(2013, 10, 22, 0, 0, 0, 0, AMERICA_SAOPAULO_ZONE));
// verify
assertThat(timestamp.getTime(), is(new DateTime(2013, 10, 22, 0, 0, 0, 0, AMERICA_SAOPAULO_ZONE).getMillis()));
AbstractUserTypeHibernateIntegrator
in usertype.spi
version 3.2.0.GA causes a connection leak on startup if the jadira.usertype.useJdbc42Apis
property is not explicitly configured. The problem occurs on line 80:
if (JavaVersion.getMajorVersion() >= 1 && JavaVersion.getMinorVersion() >= 8) {
try {
DatabaseMetaData dmd = sessionFactory.getJdbcServices().getConnectionProvider().getConnection().getMetaData();
int driverMajorVersion = dmd.getDriverMajorVersion();
...
}
As you can see, ConnectionProvider.getConnection()
is called, but Connection.close()
is not called after the connection metadata is retrieved.
I use a very small connection pool in development, and I noticed this because the pool would exhaust during startup, causing a connection timeout the third or fourth time this method is called. It was not easy to track down.
I believe everything should be fine if the code is modified to close the connection.
Until the problem is fixed, it can be worked around by explicitly setting jadira.usertype.useJdbc42Apis
to true
or false
so that the metadata interrogation does not occur.
OS: OSX
Java 1.7
TimeZone: "Europe/Berlin"
The third iteration with 2010-10-31T02:00:00.000+01:00
fails.
I think this may be caused by H2, because it seems H2 is converting the Timestamp to TimeZone.getDefault() in org.h2.util.DateTimeUtils#convertDateValueToTimestamp thereby adjusting the milliseconds itself.
In the previous two iterations the millis written to the DB and retrieved from the DB are the same. In the third iteration the millis differ
In line 90 we are losing information in expression myValue.toLocalDateTime();
Method toLocalDateTime()
cause adding/subtututing local TZ offset from milliseconds.
As a result we save wrong date in first column. This can cause different troubles. For example, if mutiple application connect to the same database but they have different TZ settings, each application will get different date.
The offset is difference between local time zone offset and database time zone offset (by default is UTC).
The same issue was in PersistentDateTime class in 3.1.0.CR1 and it has been fixed already.
Code to analyze:
DateTime now = DateTime.now();
System.out.println(now.toLocalDateTime().toDateTime().getMillis() - now.withZone(DateTimeZone.UTC).toLocalDateTime().toDateTime().getMillis());
Your local time zone shouldn't be UTC.
Looks like there is Hibernate 5-compatible code available. Wondering if it's going to be released to Maven Central soon.
Thanks!
I believe the code on line 83 should be
final Date date = new Date(zoneValue.toInstant().toEpochMilli());
I'll test this out locally and submit a patch.
It also appears that the org.jadira.usertype.dateandtime.threetenbp.columnmapper class has the same problem.
With validation on my app crashes at startup. Given the code
@Column
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount",
parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "USD")})
private Money requiredAmount;
I get a stack trace
Caused by: java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava/util/Map;
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.integrate(AbstractUserTypeHibernateIntegrator.java:192) ~[usertype.spi-6.0.1.GA.jar:?]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:280) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
Hi,
Came through this problem while i upgraded my hibernate version to 5.0+ it keeps throwing the java.lang.AbstractMethodError. After a little R&D I came to know it'e because of incompatibility issues. Any ideas of making the jadira usertype compatible with hibernate 5 in the near future. Thanks
Caused by: java.lang.AbstractMethodError
at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:278) ~[hibernate-core-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.1.Final.jar:5.0.1.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:802) ~[hibernate-entitymanager-5.0.1.Final.jar:5.0.1.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343) ~[spring-orm-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[spring-orm-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE]
I get an exception using jadira clone. See MutabilityDetector/MutabilityDetector#82. All info you need is in that thread.
The problem is probably due to you using an old version of MutabilityDetector.
Thanks
Mรฅrten
The ConfigurationHelper stores each SessionFactory in a HashMap to track the "JDBC42" compatibility. Entries are not removed from this map when the SessionFactory is shut down. This causes memory to leak.
This is problematic when running unit/integration tests and setting up a new Hibernate instance per test case. A test suite can quickly create dozens or hundreds of Hibernate instances, which will never be reclaimed.
With the following field:
@Basic()
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeAndZone")
@Columns(columns = { @Column(name = "creationtime", nullable = false),
@Column(name = "creationtimezone", nullable = false) })
private DateTime creationTime = null;
and the column definitions:
creationtime timestamp with time zone,
// note: with time zonecreationtime_zone varchar(255)
PersistentDateTimeAndZone
saves the DateTime
2015-05-28 14:43:24.209+07:00
incorrectly as:
2015-05-28 12:43:24.209-00:00
(2015-05-28 17:43:24.209+07:00
)Asia/Jakarta
While PersistentDateTimeAndZone
works fine with timestamp
type, it's sometimes preferred to always use timestamp with timezone
, therefore in which case PersistentDateTimeAndZone
should save it as:
2015-05-28 07:43:24.209-00:00
(2015-05-28 14:43:24.209+07:00
)Asia/Jakarta
Tag @ceefour
We ran into a problem recently caused by the combination of:
The problem arose from the fact that in toNonNullValue(Date)
, DateTimeZone.getOffset()
is called with a null value. This causes Joda time to calculate the offset based on DateTimeUtils.currentTimeMillis()
. In our case, the LocalDate being written was Oct 31 2013, before the DST transition. The code was executing post-DST transition, and the offset is now one hour less than it was on Oct 31.
As a result, adjustment
was 3600000 - exactly one hour. The resulting java.sql.Date instance was therefore computed as October 30 2013 -- one day before the argument date.
I believe the best way to correct this to pass the Date argument to DateTimeZone.getOffset()
. This seems to have fixed the problem for us.
PR coming shortly.
Proposed implementation :
Dependency:
<dependency>
<groupId>org.jscience</groupId>
<artifactId>jscience</artifactId>
<version>4.3.1</version>
<optional>true</optional>
</dependency>
Optional dependency so that projects not requiring jscience do not need to depend on it.
There is a connection leak here:
AbstractUserTypeHibernateIntegrator:80
DatabaseMetaData dmd = sessionFactory.getJdbcServices().getConnectionProvider().getConnection().getMetaData();
The Connection
returned by getConnection()
needs to be assigned to a local variable and closed property in a finally.
Exactly here
ย ย ย ย ย ย ย ย ifย (zone ==ย null) {
ย ย ย ย ย ย ย ย ย ย ย ย zone = ZoneOffset.of(java.util.TimeZone.getDefault().getID());
ย ย ย ย ย ย ย ย }
ย ย ย ย }ย catchย (RuntimeException ex) {
ย ย ย ย ย ย ย ย zone =ย null;
java.util.TimeZone.getDefault().getID() is a time zone like Europe/Berlin and never can be parsed as offset, therefore it always throws an exception
please refer also #42 here should be timezone instead of offset!
Maybe move the docs from Sourceforge to this repository?
Defining the database's timezone as an offset, e.g. jadira.usertype.databaseZone=+1
(or with +01:00
) in the properties file, is not supported by AbstractTimestampThreeTenBPColumnMapper
and results in the following exception being thrown:
java.lang.IllegalStateException: Could not map Zone +01:00 to Calendar
at org.jadira.usertype.dateandtime.threetenbp.columnmapper.AbstractTimestampThreeTenBPColumnMapper.getHibernateType(AbstractTimestampThreeTenBPColumnMapper.java:59)
at org.jadira.usertype.dateandtime.threetenbp.columnmapper.AbstractTimestampThreeTenBPColumnMapper.getHibernateType(AbstractTimestampThreeTenBPColumnMapper.java:27)
at org.jadira.usertype.spi.shared.AbstractSingleColumnUserType.doNullSafeGet(AbstractSingleColumnUserType.java:85)
The corresponding code is:
public final DstSafeTimestampType getHibernateType() {
if (databaseZone == null) {
return DstSafeTimestampType.INSTANCE;
}
Calendar cal = resolveCalendar(databaseZone);
if (cal == null) {
throw new IllegalStateException("Could not map Zone " + databaseZone + " to Calendar");
}
return new DstSafeTimestampType(cal);
}
private Calendar resolveCalendar(ZoneOffset databaseZone) {
String id = databaseZone.getId();
if (Arrays.binarySearch(TimeZone.getAvailableIDs(), id) != -1) {
return Calendar.getInstance(TimeZone.getTimeZone(id));
} else {
return null;
}
}
The method resolveCalendar
is called with id
= +01:00
, but TimeZone.getAvailableIDs()
only contains timezone IDs such as Europe/Paris
or CET
.
It seems the Core Library is missing JSR 354 support.
Sometimes misunderstood, but JSR 354 API and RI (Moneta) exist for Java 7 and 8.
So while including the version that requires Java 8 seems fine in a library like "ext" those parts having a minimum version of Java 6 or 7 would do good supporting the Java 6/7 variant of Moneta, too
Since a few days ThreeTen BP 1.0 is available and provides support for JDK 6, which we need.
I compiled Jadira on my own and it seems trivial to support JDK 6, as the only reason it doesn't compile right now is the usage of integer literals using underscores (1_000 instead of 1000) and two switch-statements using Strings.
Best regards
Christian
I used JPA2.1 converters for my LocalDateTime fields to convert them to java.sql.Timestamp before save. All working fine until I decided to use hibernate-envers which is not support JPA2.1 converters. Then I switched to hibernate @Type
annotation using jadira-usertypes extension.
First it seems working fine but then I notice then all my localdatetimes stored in DB with offset (+3h). When it retrieved it of course converted back (-3) and all seems to working fine. But it is not. It is wrong because LocalDateTime is designed to represent not instant in time but some local datetime for current place (whichever place you located at the moment). So when it saved to DB it must not use any timezone information. It must just be saved AS IS.
For example if I read my DB from another PHP application it must apply (-3) offset to all dates. Or if my database already filled with some data - all local dates will be wrong when read by this jadira mapper.
My DB isq Mysql with date type is DATETIME and the field represent exactly what LocalDateTime was designed for - start of working day - it is timezone agnostic. If Bob starts working at 8:00 it starts working at 8:00 in place where it working even if I observe he's working graphic from another timezone.
This bug also was found on this stackoverflow (not mine): http://stackoverflow.com/questions/31826867/how-to-setup-jadira-persistentlocaldatetime-with-java-time-localdatetime
Maven artifact POM for org.jadira.usertype:usertype.core:5.0.0.GA specifies org.hibernate:hibernate-entitymanager as required. It is possible to to use Hibernate directly without JPA entity manager, so this dependency is not required. Optional attribute is most likely omitted by mistake since org.hibernate:hibernate-core is marked as optional.
With following:
@Embeddable()
public class PostalAddress implements Describable, Serializable {
...
@Basic()
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeAndZone")
private DateTime validationTime = null;
and AttributeOverride(s) in the entity :
@Entity(name = "GoodsShipment")
public class GoodsShipment implements Serializable, JpaEntity<UUID> {
...
@Embedded()
@AttributeOverrides({
@AttributeOverride(name="validationTime.datetime", column=@Column(name="validationtime")),
@AttributeOverride(name="validationTime.offset", column=@Column(name="validationtime_zone"))
})
private PostalAddress customerAddress = null;
Hibernate 4.3.5 + UserType 3.1.0 gives this error:
18:39:22.009 ERROR | | | | host-startStop-1 | o.s.w.c.ContextLoader | Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'commercePU' defined in class id.co.bippo.common.BippoJpaConfig: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: commerce] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:482) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java) ~[spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) ~[spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797) [catalina.jar:7.0.37]
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291) [catalina.jar:7.0.37]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.37]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [catalina.jar:7.0.37]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [catalina.jar:7.0.37]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_05]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: commerce] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1225) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:119) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:853) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549) ~[spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
... 22 common frames omitted
Caused by: org.hibernate.MappingException: property mapping has wrong number of columns: id.co.bippo.schema.inventorybalance._1.GoodsShipment.customerAddress type: component[city,country,countryCode,description,emails,homePhones,mobiles,organization,phones,postalCode,primary,primaryBilling,primaryEmail,primaryHomePhone,primaryMobile,primaryPhone,primaryShipping,primaryWorkPhone,province,street,validationTime,workPhones]
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:497) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.mapping.RootClass.validate(RootClass.java:270) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.cfg.Configuration.validate(Configuration.java:1358) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
... 30 common frames omitted
If the @Columns
are set inside @Embeddable
, then column names are fixed for all entities (which are undesirable).
Similar issue, not related to Jadira but related to using Hibernate @Columns
: https://forum.hibernate.org/viewtopic.php?f=1&t=998458
Please support PostgreSQL ENUM user type Hibernate mapping.
This is my implementation (soluvas/soluvas-framework@010516c), tested with PostgreSQL 9.1 and 9.3:
package org.soluvas.jpa;
import java.lang.reflect.InvocationTargetException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.postgresql.util.PGobject;
/**
* Map <a href="http://www.postgresql.org/">Postgres</a> <a href="http://wiki.postgresql.org/wiki/Enum">Enum</a>
* onto <a href="http://download.oracle.com/javase/tutorial/java/javaOO/enum.html">Java Enum</a> using <a href="http://www.hibernate.org/">Hibernate</a>.
*
* @author Rudi Wijaya <[email protected]>
* @see http://anismiles.wordpress.com/2010/08/04/postgres-enum-with-hibernate/
*/
public class PersistentEnum extends org.jadira.usertype.corejava.PersistentEnum {
@Override
public Object doNullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Object identifier = rs.getObject(names[0]);
if (rs.wasNull()) {
return null;
}
// Notice how Object is mapped to PGobject. This makes this implementation Postgres specific
if (identifier instanceof PGobject) {
PGobject pg = (PGobject) identifier;
return Enum.valueOf((Class) getMappedClass(), pg.getValue());
} else {
throw new IllegalArgumentException("PersistentEnum type expects PGobject, got " + identifier.getClass().getName() + " for value '" + identifier + "'");
}
}
@Override
public void doNullSafeSet(PreparedStatement preparedStatement,
Object value, int index, SessionImplementor session)
throws SQLException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
if (value == null) {
preparedStatement.setNull(index, Types.VARCHAR);
// UPDATE: To support NULL insertion, change to: st.setNull(index, 1111);
} else {
// Notice 1111 which java.sql.Type for Postgres Enum
preparedStatement.setObject(index, ((Enum) value).name(), 1111);
}
}
}
Usage is similar to Jadira UserType's PersistentEnum
:
@Basic()
@Column(nullable = false)
@Type(type="org.soluvas.jpa.PersistentEnum",
parameters=@Parameter(name="enumClass", value="id.co.bippo.schema.inventorybalance._1.GeneralInventoryStatus"))
private GeneralInventoryStatus status = null;
I cannot add a feature request on Jadira JIRA because it seems it's read only for regular users, so I add it here.
Tag @ceefour
As per this stackoverflow article it appears UserType is incompatible with the newest Hibernate release (5.0.1).
Any idea if this is something that will be added?
This bug:
https://jadira.atlassian.net/browse/JDF-71
is still present. (also in 3.2.0.GA).
And this solution:
"It looks like your issue may be due to the MySQL Driver and can be resolved by updating to driver version 6.1.6 or later."
mentioned in the comments don't work because....Most recent version of mysql-connector-java is 5.1.31 as of now. How come you were able to use 6.1.6??!!!
My dependencies:
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>3.2.0.GA</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.8.Final</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
My persistence.xml:
<persistence-unit name="devastappPersistenceUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
<property name="hibernate.max_fetch_depth" value="3" />
<!-- Register Joda DateTime support - http://www.joda.org/joda-time-hibernate/ -->
<property name="jadira.usertype.autoRegisterUserTypes" value="true" />
<!-- Hibernate ignore these configuration -->
<property name="jadira.usertype.javaZone" value="UTC" />
<property name="jadira.usertype.databaseZone" value="UTC" />
</properties>
</persistence-unit>
Hibernate convert ever all the dateTime in jvm Timezone regardless of the value set in "jadira.usertype.javaZone" and "jadira.usertype.databaseZone"
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.3:run (default) on project btc-market-entities: An Ant BuildException has occured: org.hibernate.MappingException: Unable to instantiate custom type: org.jadira.usertype.corejava.PersistentEnum
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:317)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:152)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:555)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
at org.codehaus.classworlds.Launcher.main(Launcher.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.apache.maven.plugin.MojoExecutionException: An Ant BuildException has occured: org.hibernate.MappingException: Unable to instantiate custom type: org.jadira.usertype.corejava.PersistentEnum
at org.apache.maven.plugin.antrun.AbstractAntMojo.executeTasks(AbstractAntMojo.java:131)
at org.apache.maven.plugin.antrun.AntRunMojo.execute(AntRunMojo.java:98)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:106)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
... 25 more
Caused by: org.hibernate.MappingException: Unable to instantiate custom type: org.jadira.usertype.corejava.PersistentEnum
at org.hibernate.tool.ant.HibernateToolTask.reportException(HibernateToolTask.java:226)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:189)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
at org.apache.tools.ant.Task.perform(Task.java:364)
at org.apache.tools.ant.Target.execute(Target.java:341)
at org.apache.maven.plugin.antrun.AbstractAntMojo.executeTasks(AbstractAntMojo.java:118)
... 28 more
Caused by: org.hibernate.MappingException: Unable to instantiate custom type: org.jadira.usertype.corejava.PersistentEnum
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:193)
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:179)
at org.hibernate.type.TypeFactory.byClass(TypeFactory.java:103)
at org.hibernate.type.TypeResolver.heuristicType(TypeResolver.java:130)
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:295)
at org.hibernate.mapping.Column.getSqlTypeCode(Column.java:187)
at org.hibernate.mapping.Column.getSqlType(Column.java:227)
at org.hibernate.mapping.Table.sqlCreateString(Table.java:417)
at org.hibernate.cfg.Configuration.generateSchemaCreationScript(Configuration.java:1024)
at org.hibernate.tool.hbm2ddl.SchemaExport.(SchemaExport.java:126)
at org.hibernate.tool.hbm2x.Hbm2DDLExporter.doStart(Hbm2DDLExporter.java:165)
at org.hibernate.tool.hbm2x.AbstractExporter.start(AbstractExporter.java:95)
at org.hibernate.tool.ant.ExporterTask.execute(ExporterTask.java:40)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:186)
... 32 more
Caused by: java.lang.NullPointerException
at org.jadira.usertype.corejava.PersistentEnum.setParameterValues(PersistentEnum.java:35)
at org.hibernate.type.TypeFactory.injectParameters(TypeFactory.java:131)
at org.hibernate.type.TypeFactory.custom(TypeFactory.java:189)
... 45 more
export="false"
outputfilename="database.ddl"
delimiter=";"
format="true"/>
</hibernatetool>
</tasks>
<detail>true</detail>
</configuration>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-tools</artifactId>
<version>4.0.0-CR1</version>
<!--<exclusions>-->
<!--<exclusion>-->
<!--<artifactId>hibernate-commons-annotations</artifactId>-->
<!--<groupId>org.hibernate</groupId>-->
<!--</exclusion>-->
<!--</exclusions>-->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda.time.version}</version>
</dependency>
<dependency>
<groupId>org.joda</groupId>
<artifactId>joda-money</artifactId>
<version>${joda-money.version}</version>
</dependency>
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>3.1.0.CR10</version>
</dependency>
<dependency>
<groupId>org.jadira.cdt</groupId>
<artifactId>cdt</artifactId>
<version>3.1.0.CR10</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.driver.version}</version>
</dependency>
</dependencies>
</plugin>
I upgraded to Version 5.0.0.GA from 3.2.0.GA to use the new java.time.ZonedDateTime.
Because I'm still using Hibernate 3.6, I mvn clean install
ed usertype.spi-hibernate36-5.0.0.GA.
All works fine, but it seems to me that the javaZone and databaseZone parameters are ignored. The databaseZone is always UTC and the javaZone always the current System timezone. In the 3.2.0 Version and using joda DateTime the parameters were not ignored. SessionFactory is configured like this:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>hibernate.mapping.ncg.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<!--
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl">true</prop>
-->
<prop key="jadira.usertype.javaZone">America/New_York</prop>
<prop key="jadira.usertype.databaseZone">America/New_York</prop>
</props>
</property>
</bean>
These compile dependencies on junit are transitively inherited by projects that depend on Jadira usertype:
https://github.com/JadiraOrg/jadira/blob/master/usertype.core/pom.xml#L83
https://github.com/JadiraOrg/jadira/blob/master/usertype.spi/pom.xml#L99
If possible, these dependencies should be changed to scope test, or if they're used for compilation, they could be changed to provided.
I cannot use any timezone like Europe/Berlin here because used
org.jadira.usertype.dateandtime.threeten.columnmapper.TimestampColumnZonedDateTimeMapper#parseZone() calls ZoneOffset.of(zoneString) instead of DateTimeZone.forID(zoneString) or something else and it causes exception listed below.
Offset has another meaning and cannot replace timezone. For instance for Zone Europe/Berlin there are two possible offsets +0200 in summer and +0100 in winter.
Usage:
@Type(type = "org.jadira.usertype.dateandtime.threeten.PersistentZonedDateTime",
parameters = { @org.hibernate.annotations.Parameter(name = "databaseZone", value = "Europe/Berlin"),
@org.hibernate.annotations.Parameter(name = "javaZone", value = "Europe/Berlin")})
public ZonedDateTime get......() {
return ...;
}
StackTrace:
Caused by: java.time.DateTimeException: Invalid ID for ZoneOffset, invalid format: Europe/Berlin
at java.time.ZoneOffset.of(ZoneOffset.java:241)
at org.jadira.usertype.dateandtime.threeten.columnmapper.TimestampColumnZonedDateTimeMapper.parseZone(TimestampColumnZonedDateTimeMapper.java:90)
at org.jadira.usertype.dateandtime.threeten.columnmapper.TimestampColumnZonedDateTimeMapper.parseZone(TimestampColumnZonedDateTimeMapper.java:34)
at org.jadira.usertype.spi.shared.AbstractParameterizedUserType.performDatabaseZoneConfiguration(AbstractParameterizedUserType.java:97)
at org.jadira.usertype.spi.shared.AbstractParameterizedUserType.doApplyConfiguration(AbstractParameterizedUserType.java:71)
at org.jadira.usertype.spi.shared.AbstractParameterizedUserType.applyConfiguration(AbstractParameterizedUserType.java:42)
at org.jadira.usertype.spi.shared.AbstractVersionableUserType.applyConfiguration(AbstractVersionableUserType.java:36)
at org.jadira.usertype.spi.shared.AbstractUserType.beforeNullSafeOperation(AbstractUserType.java:87)
at org.jadira.usertype.spi.shared.AbstractSingleColumnUserType.nullSafeGet(AbstractSingleColumnUserType.java:67)
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:127)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:106)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2924)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1695)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1627)
at org.hibernate.loader.Loader.getRow(Loader.java:1509)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:719)
at org.hibernate.loader.Loader.processResultSet(Loader.java:949)
at org.hibernate.loader.Loader.doQuery(Loader.java:917)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:348)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:318)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2145)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3939)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:462)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:431)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:264)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1017)
at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:173)
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2413)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:913)
at
...................common.tools.dao.hibernate.Hibernate4FindDAOImpl.findById(Hibernate4FindDAOImpl.java:89)
In my app I have timestamps corresponding to multiple timezones.
Due to historical reasons, they are all stored in a PostgreSQL TIMESTAMP WITHOUT TIMEZONE column, and the actual timezone is stored somewhere else.
Because of this, I've decided to use the Joda LocalDateTime type for these objects - not to worry about the actual timezone (besides, whatever is stored in the DB is usually what the user wants to see).
But now I've started using Jadira 3.2 which internally creates a Joda DateTime object out of the LocalDateTime object and fails when it hits the DST gap in the server timezone:
org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-29T02:30:00.000 (Europe/Berlin)
at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:143)
at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:118)
at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:258)
at org.joda.time.DateTime.<init>(DateTime.java:532)
at org.joda.time.LocalDateTime.toDateTime(LocalDateTime.java:750)
at org.joda.time.LocalDateTime.toDateTime(LocalDateTime.java:731)
at org.jadira.usertype.dateandtime.joda.columnmapper.TimestampColumnLocalDateTimeMapper.toNonNullValue(TimestampColumnLocalDateTimeMapper.java:64)
at org.jadira.usertype.dateandtime.joda.columnmapper.TimestampColumnLocalDateTimeMapper.toNonNullValue(TimestampColumnLocalDateTimeMapper.java:29)
at org.jadira.usertype.spi.shared.AbstractSingleColumnUserType.nullSafeSet(AbstractSingleColumnUserType.java:100)
at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:158)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3121)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
Since both my DB column (TIMESTAMP WITHOUT TIMEZONE) and my Java object (LocalDateTime) are timezone-agnostic I would expect the corresponding Jadira mapping to also be timezone-agnostic.
It _looks_ to me like an issue in Jadira. Could you suggest some workaround I could apply to get through this problem right away?
Thank you very much in advance.
Jadira does not support in multitenant environment ?
Getting the below exception, while run application in multi tenant environment (using Hibernate multitenancy support)
Caused by: java.lang.NullPointerException
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.use42Api(AbstractUserTypeHibernateIntegrator.java:85)
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.integrate(AbstractUserTypeHibernateIntegrator.java:63)
at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:312)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
at org.egov.infra.config.persistence.JpaConfiguration.entityManagerFactory(JpaConfiguration.java:106)
This example snippet will throw a method not found exception in the fromNonNullValue method as it attempts to invoke MonetaryCurrencies.getCurrency(...).
However if I copy StringColumnCurrencyUnitMapper as it is and use my copy of the class instead it will work so I'm guessing there's something going on during the packaging. My environment: java 1.8.
import org.jadira.usertype.moneyandcurrency.moneta.columnmapper.StringColumnCurrencyUnitMapper;
import javax.money.MonetaryCurrencies;
public class FooBar {
public static void main(String[] args) {
MonetaryCurrencies.getCurrency("USD"); // this works so class and method are in place
// throws method not found exception
new StringColumnCurrencyUnitMapper().fromNonNullValue("EUR");
}
}
When the session factory is closed, the integrator calls the ConfigurationHelper configureDefaultProperties() with a null set of properties. This causes the session factory to be removed from the DEFAULT_PROPERTIES hash, but not from the JDBC 42 hash. Repeated invocations of the Configuration Helper (as in unit tests that recreate the database and the session factory) will continue to add new session factories to the JDBC 42 hash - thus running large unit test suites out of memory.
Background
In Java 9 the JEP223 has changed the format of java.version and now breaking the functionality of org.jadira.usertype.spi.utils.runtime.JavaVersion class.
The representation of java.version will return as "9", "9.x.y", "9-ea", instead of the earlier format of 1.9.*
For early access release returns the string "9-ea", and therefore JavaVersion class throws an exception:
Caused by: java.lang.NumberFormatException: For input string: "9-ea"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at org.jadira.usertype.spi.utils.runtime.JavaVersion.<clinit>(JavaVersion.java:15)
AC
PostgreSQL has typed array data type (Oracle has VARARRAY too), that can be used with any data type: varchar
, boolean
, numeric
, type
(enum), etc.
It can then be mapped to a @Entity
or `@Embeddable' attribute using:
Object[]
, String[]
, Boolean[]
, ...int[]
, boolean[]
, ...Collection<>
: Set<>
, List<>
. Some people might want to use Deque<>
too.Vector<>
/ Stack<>
is probably an edge case that no one uses.
Note the element type may be an Enum
that in turn is mappable to either String
, numeric, or a custom data type (CREATE TYPE ... AS ENUM
in PostgreSQL).
References:
In your documentation you have:
@Column
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount",
parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "USD")})
private DateTime dateTime;
is this correct that Money is represented by DateTime?
Based on the description of BigMoney, I'm able to store a number with unrestricted decimal place precision or at least with 5 decimal places. Using BigMoney with Jadira and PostgreSQL still creates column with type decimal(19, 2).
@Entity
@Table(name = "sensors")
@TypeDef(name = "MoneyAmountWithCurrencyType", typeClass = PersistentBigMoneyAmountAndCurrency.class)
public class Factory
{
@Columns(columns = { @Column(name = "electricity_cost_currency", nullable = false), @Column(name = "electricity_cost", nullable = false) })
@org.hibernate.annotations.Type(type = "MoneyAmountWithCurrencyType")
public BigMoney electricityCost;
}
This is my entity. Should I use some other Persistant..? or should I alter @column(columnDefinition)?
Assuming the following:
We have defined:
created_on
column of type DATETIME
createdOn
defined as follows:@Column(name = "created_on")
@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime",
parameters = {
@Parameter(name = "databaseZone", value = "UTC"),
@Parameter(name = "javaZone", value = "UTC")
}
)
private DateTime createdOn;
The databaseZone
and javaZone
parameters don't seem to work correctly when using PersistentDateTime
and a DATETIME
column.
We used to use usertype.jodatime:2.0.1
and had to switch to usertype.core:6.0.1
after upgrading to Hibernate 5.2. But now our createdOn
values are being stored and retrieved based on the JVM's time zone, not the one specified by the parameters.
I think the problem lies in TimestampColumnDateTimeMapper
.
For example this is what happens with its implementation of fromNonNullValue()
:
public DateTime fromNonNullValue(Timestamp value) { // value: "2016-11-09 04:30:10.0"
DateTimeZone currentJavaZone = javaZone == null ? ZoneHelper.getDefault() : javaZone; // currentJavaZone: "UTC"
DateTime dateTime = new DateTime(value.getTime()); // dateTime: "2016-11-09T04:30:10.000-08:00"
DateTime dateTimeWithZone = dateTime.withZone(currentJavaZone); // dateTimeWithZone: "2016-11-09T12:30:10.000Z"
return dateTimeWithZone;
}
Expected result: "2016-11-09T04:30:10.000Z"
Actual result: "2016-11-09T12:30:10.000Z"
In usertype.jodatime:2.0.1
, which works as expected, the implementation of TimestampColumnDateTimeMapper
is a bit different:
public DateTime fromNonNullValue(Timestamp value) { // value: "2016-11-09 04:30:10.0"
DateTimeZone currentDatabaseZone = databaseZone == null ? ZoneHelper.getDefault() : databaseZone; // currentDatabaseZone: "UTC"
DateTimeZone currentJavaZone = javaZone == null ? ZoneHelper.getDefault() : javaZone; // currentJavaZone: "UTC"
DateTime dateTime = DATETIME_FORMATTER.withZone(currentDatabaseZone).parseDateTime(value.toString()); // dateTime: "2016-11-09T04:30:10.000Z"
return dateTime.withZone(currentJavaZone);
// return: "2016-11-09T04:30:10.000Z"
}
The same similar issue happens with the implementation of toNonNullValue()
.
usertype.core:6.0.1
public Timestamp toNonNullValue(DateTime value) { // value: "2016-11-08T21:58:24.864-08:00"
final Timestamp timestamp = new Timestamp(value.getMillis()); // timestamp: "2016-11-09 21:58:24.864"
return timestamp;
}
Expected result: "2016-11-09 05:58:24.864"
Actual result: "2016-11-09 21:58:24.864"
usertype.jodatime:2.0.1
public Timestamp toNonNullValue(DateTime value) { // value: "2016-11-08T21:58:24.864-08:00"
DateTimeZone currentDatabaseZone = databaseZone == null ? ZoneHelper.getDefault() : databaseZone; // currentDatabaseZone: "UTC"
value = value.withZone(currentDatabaseZone); // value: "2016-11-09T05:58:24.864Z"
String formattedTimestamp = DATETIME_FORMATTER.print(value); // formattedTimestamp: "2016-11-09 05:58:24.864"
if (formattedTimestamp.endsWith(".")) {
formattedTimestamp = formattedTimestamp.substring(0, formattedTimestamp.length() - 1);
}
final Timestamp timestamp = Timestamp.valueOf(formattedTimestamp); // timestamp: "2016-11-09 05:58:24.864"
return timestamp;
}
When trying to use UserTypeJodaTimeHibernateIntegrator
with Hibernate 5.2 I get the following exception:
Caused by: java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava/util/Properties;
at org.jadira.usertype.spi.shared.AbstractUserTypeHibernateIntegrator.integrate(AbstractUserTypeHibernateIntegrator.java:192)
SessionFactoryImplementor
has been altered in the latest Hibernate release and no longer contains Properties getProperies()
. Could Jadira AbstractUserTypeHibernateIntegrator
be patched to support the changes in the Hibernate API ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.