From 5a39dcb39c2ca8eefe6857b279d8e6b4b011b548 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Thu, 25 Jul 2019 21:25:38 +1200 Subject: [PATCH] #1775 - MySql 8 by default wants JDBC Date set and read with JVM Calendar (timezone) --- pom.xml | 7 +++---- .../server/core/InternalConfiguration.java | 10 +++++++++- .../core/timezone/LocalDataTimeZone.java | 20 +++++++++++++++++++ .../ebeaninternal/server/type/DataBind.java | 7 ++++++- .../server/type/RsetDataReader.java | 7 ++++++- .../server/type/ScalarTypeBaseDate.java | 2 +- src/test/java/main/StartMySql.java | 4 ++-- .../TestAggregateFormula.java | 2 +- .../tests/model/types/SomeNewTypesBean.java | 11 ++++++++++ .../java/org/tests/types/TestNewTypes.java | 5 +++++ .../org/tests/update/TestSqlUpdateUpsert.java | 2 +- src/test/resources/ebean.properties | 2 +- 12 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 src/main/java/io/ebeaninternal/server/core/timezone/LocalDataTimeZone.java diff --git a/pom.xml b/pom.xml index 7ae2fee66..b7d4ee693 100644 --- a/pom.xml +++ b/pom.xml @@ -141,7 +141,7 @@ io.ebean ebean-migration - 11.18.2 + 11.17.1 @@ -229,7 +229,7 @@ io.ebean.test ebean-test-docker - 2.5.1 + 2.8.1 test @@ -273,8 +273,7 @@ mysql mysql-connector-java - - 5.1.43 + 8.0.17 test diff --git a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java index 1139eede1..b755e8c3d 100644 --- a/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java +++ b/src/main/java/io/ebeaninternal/server/core/InternalConfiguration.java @@ -45,6 +45,7 @@ import io.ebeaninternal.server.cluster.ClusterManager; import io.ebeaninternal.server.core.bootup.BootupClasses; import io.ebeaninternal.server.core.timezone.CloneDataTimeZone; import io.ebeaninternal.server.core.timezone.DataTimeZone; +import io.ebeaninternal.server.core.timezone.LocalDataTimeZone; import io.ebeaninternal.server.core.timezone.NoDataTimeZone; import io.ebeaninternal.server.core.timezone.SimpleDataTimeZone; import io.ebeaninternal.server.deploy.BeanDescriptorManager; @@ -366,6 +367,10 @@ public class InternalConfiguration { return bootupClasses; } + private Platform getPlatform() { + return getDatabasePlatform().getPlatform(); + } + public DatabasePlatform getDatabasePlatform() { return serverConfig.getDatabasePlatform(); } @@ -509,9 +514,12 @@ public class InternalConfiguration { String tz = serverConfig.getDataTimeZone(); if (tz == null) { + if (getPlatform() == Platform.MYSQL) { + return new LocalDataTimeZone(); + } return new NoDataTimeZone(); } - if (getDatabasePlatform().getPlatform() == Platform.ORACLE) { + if (getPlatform() == Platform.ORACLE) { return new CloneDataTimeZone(tz); } else { return new SimpleDataTimeZone(tz); diff --git a/src/main/java/io/ebeaninternal/server/core/timezone/LocalDataTimeZone.java b/src/main/java/io/ebeaninternal/server/core/timezone/LocalDataTimeZone.java new file mode 100644 index 000000000..d67defd7f --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/core/timezone/LocalDataTimeZone.java @@ -0,0 +1,20 @@ +package io.ebeaninternal.server.core.timezone; + +import java.util.Calendar; + +/** + * Implementation of DataTimeZone when single Calendar instance is used with local timezone. + */ +public class LocalDataTimeZone implements DataTimeZone { + + protected final Calendar zone; + + public LocalDataTimeZone() { + this.zone = Calendar.getInstance(); + } + + @Override + public Calendar getTimeZone() { + return zone; + } +} diff --git a/src/main/java/io/ebeaninternal/server/type/DataBind.java b/src/main/java/io/ebeaninternal/server/type/DataBind.java index 6c81384af..8ae786e87 100644 --- a/src/main/java/io/ebeaninternal/server/type/DataBind.java +++ b/src/main/java/io/ebeaninternal/server/type/DataBind.java @@ -141,7 +141,12 @@ public class DataBind { } public void setDate(java.sql.Date v) throws SQLException { - pstmt.setDate(++pos, v); + Calendar timeZone = dataTimeZone.getTimeZone(); + if (timeZone != null) { + pstmt.setDate(++pos, v, timeZone); + } else { + pstmt.setDate(++pos, v); + } } public void setTimestamp(Timestamp v) throws SQLException { diff --git a/src/main/java/io/ebeaninternal/server/type/RsetDataReader.java b/src/main/java/io/ebeaninternal/server/type/RsetDataReader.java index 36cb9388d..a30d3ee49 100644 --- a/src/main/java/io/ebeaninternal/server/type/RsetDataReader.java +++ b/src/main/java/io/ebeaninternal/server/type/RsetDataReader.java @@ -106,7 +106,12 @@ public class RsetDataReader implements DataReader { @Override public Date getDate() throws SQLException { - return rset.getDate(pos()); + Calendar cal = dataTimeZone.getTimeZone(); + if (cal != null) { + return rset.getDate(pos(), cal); + } else { + return rset.getDate(pos()); + } } @Override diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java index 22184cad0..149e20830 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeBaseDate.java @@ -20,7 +20,7 @@ public abstract class ScalarTypeBaseDate extends ScalarTypeBase { protected final JsonConfig.Date mode; - public ScalarTypeBaseDate(JsonConfig.Date mode, Class type, boolean jdbcNative, int jdbcType) { + ScalarTypeBaseDate(JsonConfig.Date mode, Class type, boolean jdbcNative, int jdbcType) { super(type, jdbcNative, jdbcType); this.mode = mode; } diff --git a/src/test/java/main/StartMySql.java b/src/test/java/main/StartMySql.java index a93b2eacf..d7590c511 100644 --- a/src/test/java/main/StartMySql.java +++ b/src/test/java/main/StartMySql.java @@ -7,7 +7,7 @@ public class StartMySql { public static void main(String[] args) { - MySqlConfig config = new MySqlConfig("5.7"); + MySqlConfig config = new MySqlConfig("8.0"); config.setDbName("unit"); config.setUser("unit"); config.setPassword("unit"); @@ -23,6 +23,6 @@ public class StartMySql { // config.setCharacterSet("utf8mb4"); MySqlContainer container = new MySqlContainer(config); - container.start(); + container.startWithDropCreate(); } } diff --git a/src/test/java/org/tests/aggregateformula/TestAggregateFormula.java b/src/test/java/org/tests/aggregateformula/TestAggregateFormula.java index 46f723909..6bf12e1f6 100644 --- a/src/test/java/org/tests/aggregateformula/TestAggregateFormula.java +++ b/src/test/java/org/tests/aggregateformula/TestAggregateFormula.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertNotNull; public class TestAggregateFormula extends BaseTestCase { - @IgnorePlatform(Platform.SQLSERVER) + @IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL}) @Test public void minDistinctOrderByNulls() { diff --git a/src/test/java/org/tests/model/types/SomeNewTypesBean.java b/src/test/java/org/tests/model/types/SomeNewTypesBean.java index 35a133d8f..a3baf0074 100644 --- a/src/test/java/org/tests/model/types/SomeNewTypesBean.java +++ b/src/test/java/org/tests/model/types/SomeNewTypesBean.java @@ -5,6 +5,7 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Version; import java.nio.file.Path; +import java.sql.Date; import java.time.DayOfWeek; import java.time.Duration; import java.time.Instant; @@ -45,6 +46,8 @@ public class SomeNewTypesBean { @Column(name = "month_day") MonthDay monthDay; + java.sql.Date sqlDate; + LocalDate localDate; LocalDateTime localDateTime; @@ -123,6 +126,14 @@ public class SomeNewTypesBean { this.monthDay = monthDay; } + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + public LocalDate getLocalDate() { return localDate; } diff --git a/src/test/java/org/tests/types/TestNewTypes.java b/src/test/java/org/tests/types/TestNewTypes.java index dab52d5c2..900b2f470 100644 --- a/src/test/java/org/tests/types/TestNewTypes.java +++ b/src/test/java/org/tests/types/TestNewTypes.java @@ -42,6 +42,7 @@ public class TestNewTypes extends BaseTestCase { bean.setOffsetDateTime(OffsetDateTime.now()); bean.setZonedDateTime(ZonedDateTime.now()); bean.setLocalTime(LocalTime.now()); + bean.setSqlDate(java.sql.Date.valueOf("2019-07-21")); bean.setInstant(Instant.now()); bean.setYear(Year.now()); bean.setMonth(Month.APRIL); @@ -77,6 +78,9 @@ public class TestNewTypes extends BaseTestCase { list = DB.find(SomeNewTypesBean.class).where().lt("zonedDateTime", ZonedDateTime.now()).findList(); assertTrue(!list.isEmpty()); + list = DB.find(SomeNewTypesBean.class).where().eq("sqlDate", bean.getSqlDate()).findList(); + assertTrue(!list.isEmpty()); + list = DB.find(SomeNewTypesBean.class).where().le("localTime", LocalTime.now()).findList(); assertTrue(!list.isEmpty()); @@ -113,6 +117,7 @@ public class TestNewTypes extends BaseTestCase { assertEquals(bean.getZoneOffset(), fetched.getZoneOffset()); assertEquals(bean.getMonth(), fetched.getMonth()); assertEquals(bean.getYear(), fetched.getYear()); + assertEquals(bean.getSqlDate(), fetched.getSqlDate()); assertEquals(bean.getYearMonth(), fetched.getYearMonth()); assertEquals(bean.getMonthDay(), fetched.getMonthDay()); assertEquals(bean.getLocalDate(), fetched.getLocalDate()); diff --git a/src/test/java/org/tests/update/TestSqlUpdateUpsert.java b/src/test/java/org/tests/update/TestSqlUpdateUpsert.java index fe8669c82..7136541d2 100644 --- a/src/test/java/org/tests/update/TestSqlUpdateUpsert.java +++ b/src/test/java/org/tests/update/TestSqlUpdateUpsert.java @@ -121,7 +121,7 @@ public class TestSqlUpdateUpsert extends BaseTestCase { EPersonOnline found2 = Ebean.find(EPersonOnline.class, key2); assertThat(found2).isNotNull(); - assertThat(found2.getId()).isEqualTo(key); + assertThat(found2.getId().toString()).isEqualTo(key.toString()); assertThat(found2.getEmail()).isEqualTo("bar@one.com"); assertThat(found2.isOnlineStatus()).isFalse(); diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties index 43fd2954c..e5e709a90 100644 --- a/src/test/resources/ebean.properties +++ b/src/test/resources/ebean.properties @@ -138,7 +138,7 @@ datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/unit #datasource.mysql.username=test_ebean #datasource.mysql.password=test #datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/test_ebean -datasource.mysql.databaseDriver=com.mysql.jdbc.Driver +datasource.mysql.databaseDriver=com.mysql.cj.jdbc.Driver datasource.oracle.username=test_ebean