From 458b2dc772ce2298316f0cc0aba253f48b501110 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 10 Jan 2014 09:35:27 -0600 Subject: [PATCH] HHH-8842 - Hibernate can't handle JodaTime Converters result (possible bug) (cherry picked from commit 6fb5a899bdc81f720ec01fe506bfc25c4d8759d1) --- .../sql/JdbcTypeJavaClassMappings.java | 5 +- .../hibernate-entitymanager.gradle | 2 + .../convert/BasicJodaTimeConversionTest.java | 136 ++++++++++++++++++ 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java index 6bfa05e97e..2794b49572 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/JdbcTypeJavaClassMappings.java @@ -26,7 +26,6 @@ package org.hibernate.type.descriptor.sql; import java.math.BigDecimal; import java.sql.Blob; import java.sql.Clob; -import java.sql.Date; import java.sql.Ref; import java.sql.Struct; import java.sql.Time; @@ -108,7 +107,7 @@ public class JdbcTypeJavaClassMappings { jdbcJavaClassMappings.put( Float.class, Types.REAL ); jdbcJavaClassMappings.put( Double.class, Types.DOUBLE ); jdbcJavaClassMappings.put( byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( Date.class, Types.DATE ); + jdbcJavaClassMappings.put( java.sql.Date.class, Types.DATE ); jdbcJavaClassMappings.put( Time.class, Types.TIME ); jdbcJavaClassMappings.put( Timestamp.class, Types.TIMESTAMP ); jdbcJavaClassMappings.put( Blob.class, Types.BLOB ); @@ -123,7 +122,7 @@ public class JdbcTypeJavaClassMappings { jdbcJavaClassMappings.put( char[].class, Types.VARCHAR ); jdbcJavaClassMappings.put( Character[].class, Types.VARCHAR ); jdbcJavaClassMappings.put( Byte[].class, Types.LONGVARBINARY ); - jdbcJavaClassMappings.put( Date.class, Types.TIMESTAMP ); + jdbcJavaClassMappings.put( java.util.Date.class, Types.TIMESTAMP ); jdbcJavaClassMappings.put( Calendar.class, Types.TIMESTAMP ); return jdbcJavaClassMappings; diff --git a/hibernate-entitymanager/hibernate-entitymanager.gradle b/hibernate-entitymanager/hibernate-entitymanager.gradle index 989291e4db..86ab4c52c9 100644 --- a/hibernate-entitymanager/hibernate-entitymanager.gradle +++ b/hibernate-entitymanager/hibernate-entitymanager.gradle @@ -32,6 +32,8 @@ dependencies { // for testing stored procedure support testCompile( libraries.derby ) + testCompile( 'joda-time:joda-time:2.3' ) + hibernateJpaModelGenTool( project( ':hibernate-jpamodelgen' ) ) } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java new file mode 100644 index 0000000000..e34110ad8a --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/convert/BasicJodaTimeConversionTest.java @@ -0,0 +1,136 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.convert; + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.persistence.AttributeConverter; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.jpa.boot.spi.Bootstrap; +import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.type.Type; +import org.hibernate.type.descriptor.converter.AttributeConverterTypeAdapter; + +import org.hibernate.testing.TestForIssue; + +import org.junit.Test; + +import org.joda.time.LocalDate; +import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; +import static org.junit.Assert.assertEquals; + +/** + * @author Steve Ebersole + */ +@TestForIssue( jiraKey = "HHH-8842" ) +public class BasicJodaTimeConversionTest { + static int callsToConverter = 0; + + public static class JodaLocalDateConverter implements AttributeConverter { + public Date convertToDatabaseColumn(LocalDate localDate) { + callsToConverter++; + return localDate.toDate(); + } + + public LocalDate convertToEntityAttribute(Date date) { + callsToConverter++; + return LocalDate.fromDateFields( date ); + } + } + + @Entity( name = "TheEntity" ) + public static class TheEntity { + @Id + public Integer id; + @Convert( converter = JodaLocalDateConverter.class ) + public LocalDate theDate; + + public TheEntity() { + } + + public TheEntity(Integer id, LocalDate theDate) { + this.id = id; + this.theDate = theDate; + } + } + + @Test + public void testSimpleConvertUsage() throws MalformedURLException { + final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() { + @Override + public List getManagedClassNames() { + return Arrays.asList( TheEntity.class.getName() ); + } + }; + + final Map settings = new HashMap(); + settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" ); + + EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build(); + final EntityPersister ep = emf.unwrap( SessionFactoryImplementor.class ).getEntityPersister( TheEntity.class.getName() ); + final Type theDatePropertyType = ep.getPropertyType( "theDate" ); + final AttributeConverterTypeAdapter type = assertTyping( AttributeConverterTypeAdapter.class, theDatePropertyType ); + assertTyping( JodaLocalDateConverter.class, type.getAttributeConverter() ); + + try { + EntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist( new TheEntity( 1, new LocalDate() ) ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 1, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.find( TheEntity.class, 1 ); + em.getTransaction().commit(); + em.close(); + + assertEquals( 2, callsToConverter ); + + em = emf.createEntityManager(); + em.getTransaction().begin(); + em.createQuery( "delete TheEntity" ).executeUpdate(); + em.getTransaction().commit(); + em.close(); + } + finally { + emf.close(); + } + } +}