From 3ca07ab63eb940f31339e501dbc72d12d5c4e284 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 4 Jan 2015 20:04:49 +0100 Subject: [PATCH] DATAJPA-655 - Added AttributeConverters for ThreeTen backport library. We now ship JPA 2.1 AttributeConverters for the ThreeTen back port library [0] similarly to the one we provide for JSR-310. [0] http://www.threeten.org/threetenbp --- pom.xml | 7 ++ .../support/Jsr310BackPortJpaConverters.java | 103 ++++++++++++++++++ ...actAttributeConverterIntegrationTests.java | 73 +++++++++++++ .../jpa/domain/support/DateTimeSample.java | 5 + ...BackPortJpaConvertersIntegrationTests.java | 67 ++++++++++++ .../Jsr310JpaConvertersIntegrationTests.java | 48 +------- template.mf | 1 + 7 files changed, 257 insertions(+), 47 deletions(-) create mode 100644 src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java diff --git a/pom.xml b/pom.xml index 2bd2fcf18..bd4b95e11 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,13 @@ true + + org.threeten + threetenbp + ${threetenbp} + true + + diff --git a/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java b/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java new file mode 100644 index 000000000..4c73340d6 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConverters.java @@ -0,0 +1,103 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.domain.support; + +import java.util.Date; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +import org.springframework.data.convert.Jsr310BackPortConverters.DateToInstantConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalDateConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalDateTimeConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.DateToLocalTimeConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.InstantToDateConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.LocalDateTimeToDateConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.LocalDateToDateConverter; +import org.springframework.data.convert.Jsr310BackPortConverters.LocalTimeToDateConverter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.threeten.bp.Instant; +import org.threeten.bp.LocalDate; +import org.threeten.bp.LocalDateTime; +import org.threeten.bp.LocalTime; + +/** + * JPA 2.1 converters to turn ThreeTen back port types into legacy {@link Date}s. To activate these converters make sure + * your persistence provider detects them by including this class in the list of mapped classes. In Spring environments, + * you can simply register the package of this class (i.e. {@code org.springframework.data.jpa.domain.support}) as + * package to be scanned on e.g. the {@link LocalContainerEntityManagerFactoryBean}. + * + * @author Oliver Gierke + * @see http://www.threeten.org/threetenbp + */ +public class Jsr310BackPortJpaConverters { + + @Converter(autoApply = true) + public static class LocalDateConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(LocalDate date) { + return LocalDateToDateConverter.INSTANCE.convert(date); + } + + @Override + public LocalDate convertToEntityAttribute(Date date) { + return DateToLocalDateConverter.INSTANCE.convert(date); + } + } + + @Converter(autoApply = true) + public static class LocalTimeConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(LocalTime time) { + return LocalTimeToDateConverter.INSTANCE.convert(time); + } + + @Override + public LocalTime convertToEntityAttribute(Date date) { + return DateToLocalTimeConverter.INSTANCE.convert(date); + } + } + + @Converter(autoApply = true) + public static class LocalDateTimeConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(LocalDateTime date) { + return LocalDateTimeToDateConverter.INSTANCE.convert(date); + } + + @Override + public LocalDateTime convertToEntityAttribute(Date date) { + return DateToLocalDateTimeConverter.INSTANCE.convert(date); + } + } + + @Converter(autoApply = true) + public static class InstantConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(Instant instant) { + return InstantToDateConverter.INSTANCE.convert(instant); + } + + @Override + public Instant convertToEntityAttribute(Date date) { + return DateToInstantConverter.INSTANCE.convert(date); + } + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java new file mode 100644 index 000000000..b0be657a3 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/support/AbstractAttributeConverterIntegrationTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.domain.support; + +import javax.persistence.AttributeConverter; +import javax.sql.DataSource; + +import org.junit.runner.RunWith; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.domain.sample.User; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; +import org.springframework.orm.jpa.vendor.Database; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.Transactional; + +/** + * Base class for integration tests for JPA 2.1 {@link AttributeConverter} integration. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@Transactional +public abstract class AbstractAttributeConverterIntegrationTests { + + @Configuration + static class Config { + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + + AbstractJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setDatabase(Database.HSQL); + vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setDataSource(dataSource()); + factory.setPackagesToScan(getClass().getPackage().getName(), User.class.getPackage().getName()); + factory.setJpaVendorAdapter(vendorAdapter); + + return factory; + } + + public @Bean PlatformTransactionManager transactionManager() { + return new JpaTransactionManager(); + } + + public @Bean DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build(); + } + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java b/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java index 9d4fe31fc..32c695c42 100644 --- a/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java +++ b/src/test/java/org/springframework/data/jpa/domain/support/DateTimeSample.java @@ -35,4 +35,9 @@ public class DateTimeSample { LocalDate localDate; LocalTime localTime; LocalDateTime localDateTime; + + org.threeten.bp.Instant bpInstant; + org.threeten.bp.LocalDate bpLocalDate; + org.threeten.bp.LocalTime bpLocalTime; + org.threeten.bp.LocalDateTime bpLocalDateTime; } diff --git a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java new file mode 100644 index 000000000..96a1ab537 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310BackPortJpaConvertersIntegrationTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.domain.support; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; +import static org.springframework.data.jpa.support.EntityManagerTestUtils.*; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.junit.Test; +import org.threeten.bp.Instant; +import org.threeten.bp.LocalDate; +import org.threeten.bp.LocalDateTime; +import org.threeten.bp.LocalTime; + +/** + * Integration tests for {@link Jsr310BackPortJpaConverters}. + * + * @author Oliver Gierke + */ +public class Jsr310BackPortJpaConvertersIntegrationTests extends AbstractAttributeConverterIntegrationTests { + + @PersistenceContext EntityManager em; + + /** + * @see DATAJPA-650 + */ + @Test + public void usesJsr310BackPortJpaConverters() { + + assumeTrue(currentEntityManagerIsAJpa21EntityManager(em)); + + DateTimeSample sample = new DateTimeSample(); + + sample.bpInstant = Instant.now(); + sample.bpLocalDate = LocalDate.now(); + sample.bpLocalTime = LocalTime.now(); + sample.bpLocalDateTime = LocalDateTime.now(); + + em.persist(sample); + em.clear(); + + DateTimeSample result = em.find(DateTimeSample.class, sample.id); + + assertThat(result, is(notNullValue())); + assertThat(result.bpInstant, is(sample.bpInstant)); + assertThat(result.bpLocalDate, is(sample.bpLocalDate)); + assertThat(result.bpLocalTime, is(sample.bpLocalTime)); + assertThat(result.bpLocalDateTime, is(sample.bpLocalDateTime)); + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java index 462ca2266..1982a4e97 100644 --- a/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/domain/support/Jsr310JpaConvertersIntegrationTests.java @@ -27,61 +27,15 @@ import java.time.LocalTime; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; -import javax.sql.DataSource; import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.domain.sample.User; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; -import org.springframework.orm.jpa.vendor.Database; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.annotation.Transactional; /** * Integration tests for {@link Jsr310JpaConverters}. * * @author Oliver Gierke */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration -@Transactional -public class Jsr310JpaConvertersIntegrationTests { - - @Configuration - static class Config { - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - - AbstractJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - vendorAdapter.setDatabase(Database.HSQL); - vendorAdapter.setGenerateDdl(true); - - LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); - factory.setDataSource(dataSource()); - factory.setPackagesToScan(getClass().getPackage().getName(), User.class.getPackage().getName()); - factory.setJpaVendorAdapter(vendorAdapter); - - return factory; - } - - public @Bean PlatformTransactionManager transactionManager() { - return new JpaTransactionManager(); - } - - public @Bean DataSource dataSource() { - return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build(); - } - } +public class Jsr310JpaConvertersIntegrationTests extends AbstractAttributeConverterIntegrationTests { @PersistenceContext EntityManager em; diff --git a/template.mf b/template.mf index 95ee501d7..d7fa9eb82 100644 --- a/template.mf +++ b/template.mf @@ -21,6 +21,7 @@ Import-Template: org.springframework.*;version="${spring:[=.=.=.=,+1.1.0)}", org.springframework.beans.factory.aspectj;version="${spring:[=.=.=.=,+1.1.0)}";resolution:=optional, org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}", + org.threeten.bp.*;version="${threetenbp:[=.=.=,+1.0.0)}";resolution:=optional, org.w3c.*;version="0.0.0" Import-Package: org.aspectj.lang;version="${aspectj:[=.=.=,+1.0.0)}";resolution:=optional, org.aspectj.runtime.reflect;version="${aspectj:[=.=.=,+1.0.0)}";resolution:=optional,