package com.github.marschall.threeten.jpa.jdbc42.hibernate; import static com.github.marschall.threeten.jpa.jdbc42.hibernate.Constants.PERSISTENCE_UNIT_NAME; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import java.math.BigInteger; import java.sql.Connection; import java.sql.SQLException; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Query; import javax.sql.DataSource; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MutablePropertySources; import org.springframework.jdbc.datasource.init.DatabasePopulator; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.support.TransactionTemplate; import com.github.marschall.threeten.jpa.jdbc42.hibernate.configuration.H2Configuration; import com.github.marschall.threeten.jpa.jdbc42.hibernate.configuration.HibernateConfiguration; import com.github.marschall.threeten.jpa.jdbc42.hibernate.configuration.HsqlConfiguration; import com.github.marschall.threeten.jpa.jdbc42.hibernate.configuration.PostgresConfiguration; @RunWith(Parameterized.class) public class ConverterWithTimeZoneTest { private final Class<?> datasourceConfiguration; private final Class<?> jpaConfiguration; private final String persistenceUnitName; private AnnotationConfigApplicationContext applicationContext; private TransactionTemplate template; public ConverterWithTimeZoneTest(Class<?> datasourceConfiguration, Class<?> jpaConfiguration, String persistenceUnitName) { this.datasourceConfiguration = datasourceConfiguration; this.jpaConfiguration = jpaConfiguration; this.persistenceUnitName = persistenceUnitName; } @Parameters(name = "{2}") public static Collection<Object[]> parameters() { return Arrays.asList( new Object[]{HsqlConfiguration.class, HibernateConfiguration.class, "threeten-jpa-hibernate-hsql"}, //new Object[]{SqlServerConfiguration.class, HibernateConfiguration.class, "threeten-jpa-hibernate-sqlserver"}, // new Object[]{DerbyConfiguration.class, HibernateConfiguration.class, "threeten-jpa-hibernate-derby"}, new Object[]{H2Configuration.class, HibernateConfiguration.class, "threeten-jpa-hibernate-h2"}, new Object[]{PostgresConfiguration.class, HibernateConfiguration.class, "threeten-jpa-hibernate-postgres"} ); } @Before public void setUp() { this.applicationContext = new AnnotationConfigApplicationContext(); this.applicationContext.register(this.datasourceConfiguration, TransactionManagerConfiguration.class, this.jpaConfiguration); ConfigurableEnvironment environment = this.applicationContext.getEnvironment(); MutablePropertySources propertySources = environment.getPropertySources(); Map<String, Object> source = singletonMap(PERSISTENCE_UNIT_NAME, this.persistenceUnitName); propertySources.addFirst(new MapPropertySource("persistence unit name", source)); this.applicationContext.refresh(); PlatformTransactionManager txManager = this.applicationContext.getBean(PlatformTransactionManager.class); this.template = new TransactionTemplate(txManager); this.template.execute(status -> { Map<String, DatabasePopulator> beans = this.applicationContext.getBeansOfType(DatabasePopulator.class); DataSource dataSource = this.applicationContext.getBean(DataSource.class); try (Connection connection = dataSource.getConnection()) { for (DatabasePopulator populator : beans.values()) { populator.populate(connection); } } catch (SQLException e) { throw new RuntimeException("could initialize database", e); } return null; }); } @After public void tearDown() { this.applicationContext.close(); } @Test public void read() { EntityManagerFactory factory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManager entityManager = factory.createEntityManager(); try { // read the entity inserted by SQL this.template.execute(status -> { Query query = entityManager.createQuery("SELECT t FROM JavaTime42WithZone t"); List<?> resultList = query.getResultList(); assertThat(resultList, hasSize(1)); // validate the entity inserted by SQL JavaTime42WithZone javaTime = (JavaTime42WithZone) resultList.get(0); OffsetDateTime inserted = OffsetDateTime.parse("1960-01-01T23:03:20+02:00"); if (persistenceUnitName.contains("postgres")) { // postgres stores in UTC OffsetDateTime inUtc = inserted.withOffsetSameInstant(ZoneOffset.UTC); assertEquals(inUtc, javaTime.getOffset()); } else { assertEquals(inserted, javaTime.getOffset()); } return null; }); } finally { entityManager.close(); // EntityManagerFactory should be closed by spring. } } @Test public void write() { EntityManagerFactory factory = this.applicationContext.getBean(EntityManagerFactory.class); EntityManager entityManager = factory.createEntityManager(); try { // insert a new entity into the database BigInteger newId = new BigInteger("2"); OffsetDateTime newOffset = OffsetDateTime.now(); this.template.execute(status -> { JavaTime42WithZone toInsert = new JavaTime42WithZone(); toInsert.setId(newId); toInsert.setOffset(newOffset); entityManager.persist(toInsert); // the transaction should trigger a flush and write to the database return null; }); // validate the new entity inserted into the database this.template.execute(status -> { JavaTime42WithZone readBack = entityManager.find(JavaTime42WithZone.class, newId); assertNotNull(readBack); assertEquals(newId, readBack.getId()); assertEquals(newOffset, readBack.getOffset()); entityManager.remove(readBack); return null; }); } finally { entityManager.close(); // EntityManagerFactory should be closed by spring. } } }