diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java index 8a6d570f6..d46f6dd37 100644 --- a/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java +++ b/ebean-api/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java @@ -15,6 +15,7 @@ import javax.persistence.PersistenceException; import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -54,6 +55,15 @@ public class DatabasePlatform { protected boolean supportsSavepointId = true; protected boolean useMigrationStoredProcedures = false; + + /** + * Can we use native java time API objects in + * {@link ResultSet#getObject(int, Class)} and + * {@link PreparedStatement#setObject(int, Object)}. + * + * Not all drivers (DB2 e.g.) will support this. + */ + protected boolean supportsNativeJavaTime = true; /** * The behaviour used when ending a read only transaction at read committed isolation level. @@ -827,4 +837,8 @@ public class DatabasePlatform { protected void escapeLikeCharacter(char ch, StringBuilder sb) { sb.append(likeEscapeChar).append(ch); } + + public boolean supportsNativeJavaTime() { + return supportsNativeJavaTime; + } } diff --git a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java b/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java index 61d14f4a6..5f2e44df9 100644 --- a/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java +++ b/ebean-api/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java @@ -24,6 +24,7 @@ public class DB2Platform extends DatabasePlatform { // TOOD: Check if we need to introduce a new platform (DB2_LUW_11 ?) this.maxTableNameLength = 18; this.maxConstraintNameLength = 18; + this.supportsNativeJavaTime = false; this.truncateTable = "truncate table %s reuse storage ignore delete triggers immediate"; this.sqlLimiter = new Db2SqlLimiter(); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java index 81d6a1ea2..94ebb0572 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java @@ -755,7 +755,11 @@ public final class DefaultTypeManager implements TypeManager { typeMap.put(java.nio.file.Path.class, new ScalarTypePath()); addType(java.time.Period.class, new ScalarTypePeriod()); - addType(java.time.LocalDate.class, new ScalarTypeLocalDate(jsonDate)); + if (config.getDatabasePlatform().supportsNativeJavaTime()) { + addType(java.time.LocalDate.class, new ScalarTypeLocalDateNative(jsonDate)); + } else { + addType(java.time.LocalDate.class, new ScalarTypeLocalDate(jsonDate)); + } addType(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(jsonDateTime)); addType(OffsetDateTime.class, new ScalarTypeOffsetDateTime(jsonDateTime, zoneId)); addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(jsonDateTime, zoneId)); @@ -795,7 +799,11 @@ public final class DefaultTypeManager implements TypeManager { log.debug("Registering Joda data types"); addType(LocalDateTime.class, new ScalarTypeJodaLocalDateTime(jsonDateTime)); addType(DateTime.class, new ScalarTypeJodaDateTime(jsonDateTime)); - addType(LocalDate.class, new ScalarTypeJodaLocalDate(jsonDate)); + if (config.getDatabasePlatform().supportsNativeJavaTime()) { + addType(LocalDate.class, new ScalarTypeJodaLocalDateNative(jsonDate)); + } else { + addType(LocalDate.class, new ScalarTypeJodaLocalDate(jsonDate)); + } addType(org.joda.time.DateMidnight.class, new ScalarTypeJodaDateMidnight(jsonDate)); addType(org.joda.time.Period.class, new ScalarTypeJodaPeriod()); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java index eb10a80bb..dd84612a8 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDate.java @@ -14,7 +14,7 @@ import java.sql.Types; /** * ScalarType for Joda LocalDate. This maps to a JDBC Date. */ -final class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate { +class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate { ScalarTypeJodaLocalDate(JsonConfig.Date mode) { super(mode, LocalDate.class, false, Types.DATE); @@ -61,19 +61,4 @@ final class ScalarTypeJodaLocalDate extends ScalarTypeBaseDate { } return (LocalDate) value; } - - @Override - public void bind(DataBinder binder, LocalDate value) throws SQLException { - if (value == null) { - binder.setNull(Types.DATE); - } else { - binder.setObject(java.time.LocalDate.of(value.getYear(), value.getMonthOfYear(), value.getDayOfMonth())); - } - } - - @Override - public LocalDate read(DataReader reader) throws SQLException { - java.time.LocalDate jtDate = reader.getObject(java.time.LocalDate.class); - return jtDate == null ? null : new org.joda.time.LocalDate(jtDate.getYear(), jtDate.getMonthValue(), jtDate.getDayOfMonth()); - } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateNative.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateNative.java new file mode 100644 index 000000000..d591fd300 --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJodaLocalDateNative.java @@ -0,0 +1,37 @@ +package io.ebeaninternal.server.type; + +import io.ebean.config.JsonConfig; +import io.ebean.core.type.DataBinder; +import io.ebean.core.type.DataReader; +import io.ebeaninternal.server.core.BasicTypeConverter; +import org.joda.time.DateTimeZone; +import org.joda.time.LocalDate; + +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Types; + +/** + * ScalarType for Joda LocalDate. This maps to a LocalDate. Not all drivers/platforms may support this. + */ +final class ScalarTypeJodaLocalDateNative extends ScalarTypeJodaLocalDate{ + + ScalarTypeJodaLocalDateNative(JsonConfig.Date mode) { + super(mode); + } + + @Override + public void bind(DataBinder binder, LocalDate value) throws SQLException { + if (value == null) { + binder.setNull(Types.DATE); + } else { + binder.setObject(java.time.LocalDate.of(value.getYear(), value.getMonthOfYear(), value.getDayOfMonth())); + } + } + + @Override + public LocalDate read(DataReader reader) throws SQLException { + java.time.LocalDate jtDate = reader.getObject(java.time.LocalDate.class); + return jtDate == null ? null : new org.joda.time.LocalDate(jtDate.getYear(), jtDate.getMonthValue(), jtDate.getDayOfMonth()); + } +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java index 1e298ecac..1cfcda150 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDate.java @@ -16,7 +16,7 @@ import java.time.ZonedDateTime; /** * ScalarType for java.time.LocalDate. This maps to a JDBC Date. */ -final class ScalarTypeLocalDate extends ScalarTypeBaseDate { +class ScalarTypeLocalDate extends ScalarTypeBaseDate { ScalarTypeLocalDate(JsonConfig.Date mode) { super(mode, LocalDate.class, false, Types.DATE); @@ -63,19 +63,4 @@ final class ScalarTypeLocalDate extends ScalarTypeBaseDate { } return (LocalDate) value; } - - @Override - public void bind(DataBinder binder, LocalDate value) throws SQLException { - if (value == null) { - binder.setNull(Types.DATE); - } else { - binder.setObject(value); - } - } - - @Override - public LocalDate read(DataReader reader) throws SQLException { - return reader.getObject(LocalDate.class); - } - } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateNative.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateNative.java new file mode 100644 index 000000000..67da39e1e --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeLocalDateNative.java @@ -0,0 +1,39 @@ +package io.ebeaninternal.server.type; + +import io.ebean.config.JsonConfig; +import io.ebean.core.type.DataBinder; +import io.ebean.core.type.DataReader; +import io.ebeaninternal.server.core.BasicTypeConverter; + +import java.sql.Date; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.sql.Types; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; + +/** + * ScalarType for java.time.LocalDate. This maps to a LocalDate. Not all drivers/platforms may support this. + */ +final class ScalarTypeLocalDateNative extends ScalarTypeLocalDate { + + ScalarTypeLocalDateNative(JsonConfig.Date mode) { + super(mode); + } + + @Override + public void bind(DataBinder binder, LocalDate value) throws SQLException { + if (value == null) { + binder.setNull(Types.DATE); + } else { + binder.setObject(value); + } + } + + @Override + public LocalDate read(DataReader reader) throws SQLException { + return reader.getObject(LocalDate.class); + } + +}