You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2019/01/25 18:11:56 UTC
[openjpa] 01/04: OPENJPA-2713 implement native java8 types
This is an automated email from the ASF dual-hosted git repository.
struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit e57fd518b32d1ebc85fbdb818b1ca818d1abe46a
Author: Mark Struberg <st...@apache.org>
AuthorDate: Sun Jan 20 23:51:10 2019 +0100
OPENJPA-2713 implement native java8 types
Since some DBs (e.g. PostgreSQL) do support LocalDate, etc
in their JDBC drivers, it's probably the best to support it
on a way deeper level.
---
.../openjpa/jdbc/meta/MappingDefaultsImpl.java | 6 -
.../openjpa/jdbc/meta/MappingRepository.java | 5 +
.../openjpa/jdbc/meta/strats/BlobValueHandler.java | 7 +-
.../jdbc/meta/strats/ImmutableValueHandler.java | 5 +
.../jdbc/meta/strats/LocalDateValueHandler.java | 81 ------------
.../apache/openjpa/jdbc/sql/AbstractResult.java | 57 ++++++++-
.../org/apache/openjpa/jdbc/sql/DBDictionary.java | 140 ++++++++++++++++-----
.../org/apache/openjpa/jdbc/sql/MergedResult.java | 21 +++-
.../java/org/apache/openjpa/jdbc/sql/Result.java | 21 ++++
.../apache/openjpa/jdbc/sql/ResultSetResult.java | 31 ++++-
.../org/apache/openjpa/kernel/AttachStrategy.java | 7 +-
.../java/org/apache/openjpa/meta/JavaTypes.java | 28 ++++-
.../openjpa/persistence/simple/Java8TimeTypes.java | 82 ++++++++++++
.../persistence/simple/TestBasicAnnotation.java | 4 +
.../persistence/simple/TestJava8TimeTypes.java | 65 ++++++++++
.../strategy/value/ValueStrategyHandler.java | 50 ++++----
.../persistence/PersistenceMetaDataDefaults.java | 5 +
.../persistence/meta/AbstractManagedType.java | 20 +++
18 files changed, 474 insertions(+), 161 deletions(-)
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingDefaultsImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingDefaultsImpl.java
index fe4f5bc..ca1bf38 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingDefaultsImpl.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingDefaultsImpl.java
@@ -27,7 +27,6 @@ import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.Normalizer;
import org.apache.openjpa.jdbc.meta.strats.EnumValueHandler;
-import org.apache.openjpa.jdbc.meta.strats.LocalDateValueHandler;
import org.apache.openjpa.jdbc.meta.strats.UntypedPCValueHandler;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ForeignKey;
@@ -537,11 +536,6 @@ public class MappingDefaultsImpl
return enumHandler;
}
- if (java.time.LocalDate.class == type) {
- // we can compare with == since LocalDate is final
- return new LocalDateValueHandler();
- }
-
return null;
}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
index 66f6970..b62cdbb 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
@@ -1356,6 +1356,11 @@ public class MappingRepository extends MetaDataRepository {
case JavaTypes.DATE:
case JavaTypes.CALENDAR:
case JavaTypes.LOCALE:
+ case JavaTypes.LOCAL_DATE:
+ case JavaTypes.LOCAL_TIME:
+ case JavaTypes.LOCAL_DATETIME:
+ case JavaTypes.OFFSET_TIME:
+ case JavaTypes.OFFSET_DATETIME:
return ImmutableValueHandler.getInstance();
case JavaTypes.STRING:
if (isClob(val, true))
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/BlobValueHandler.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/BlobValueHandler.java
index ed76deb..def2112 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/BlobValueHandler.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/BlobValueHandler.java
@@ -29,8 +29,7 @@ import org.apache.openjpa.meta.JavaTypes;
* Handler for blob values.
*
*/
-public class BlobValueHandler
- extends AbstractValueHandler {
+public class BlobValueHandler extends AbstractValueHandler {
private static final long serialVersionUID = 1L;
@@ -43,10 +42,6 @@ public class BlobValueHandler
return _instance;
}
- /**
- * @deprecated
- */
- @Deprecated
@Override
public Column[] map(ValueMapping vm, String name, ColumnIO io,
boolean adapt) {
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java
index e148963..362d18d 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java
@@ -87,6 +87,11 @@ public class ImmutableValueHandler extends AbstractValueHandler {
case JavaTypes.SHORT_OBJ:
case JavaTypes.STRING:
case JavaTypes.DATE:
+ case JavaTypes.LOCAL_DATE:
+ case JavaTypes.LOCAL_TIME:
+ case JavaTypes.LOCAL_DATETIME:
+ case JavaTypes.OFFSET_TIME:
+ case JavaTypes.OFFSET_DATETIME:
case JavaTypes.BIGINTEGER:
case JavaTypes.LOCALE:
return true;
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LocalDateValueHandler.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LocalDateValueHandler.java
deleted file mode 100644
index 1701dbf..0000000
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LocalDateValueHandler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.openjpa.jdbc.meta.strats;
-
-import java.sql.Types;
-import java.time.LocalDate;
-
-import org.apache.openjpa.jdbc.identifier.DBIdentifier;
-import org.apache.openjpa.jdbc.kernel.JDBCStore;
-import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
-import org.apache.openjpa.jdbc.meta.ValueMapping;
-import org.apache.openjpa.jdbc.schema.Column;
-import org.apache.openjpa.jdbc.schema.ColumnIO;
-import org.apache.openjpa.jdbc.sql.DBDictionary;
-import org.apache.openjpa.lib.util.Localizer;
-
-/**
- * Value handler for JDK8 java.time.LocalDate field types.
- *
- */
-public class LocalDateValueHandler extends AbstractValueHandler {
- private static final long serialVersionUID = 1L;
- private static final Localizer _loc = Localizer.forPackage(LocalDateValueHandler.class);
-
- /**
- * @deprecated
- */
- @Deprecated
- @Override
- public Column[] map(ValueMapping vm, String name, ColumnIO io,
- boolean adapt) {
- DBDictionary dict = vm.getMappingRepository().getDBDictionary();
- DBIdentifier colName = DBIdentifier.newColumn(name, dict != null ? dict.delimitAll() : false);
-
- Column column = new Column();
- column.setIdentifier(colName);
- column.setJavaType(JavaSQLTypes.SQL_DATE);
- column.setType(Types.DATE);
-
- return new Column[]{column};
- }
-
- @Override
- public boolean isVersionable(ValueMapping vm) {
- return true;
- }
-
- @Override
- public Object toDataStoreValue(ValueMapping vm, Object val, JDBCStore store) {
- if (val == null) {
- return null;
- }
-
- return java.sql.Date.valueOf((LocalDate) val);
- }
-
- @Override
- public Object toObjectValue(ValueMapping vm, Object val) {
- if (val == null) {
- return null;
- }
-
- return ((java.sql.Date) val).toLocalDate();
- }
-}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java
index 61f3143..ab925f1 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractResult.java
@@ -31,6 +31,9 @@ import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@@ -502,8 +505,7 @@ public abstract class AbstractResult
protected Calendar getCalendarInternal(Object obj, Joins joins)
throws SQLException {
- Object val = checkNull(getObjectInternal(obj, JavaTypes.CALENDAR,
- null, joins));
+ Object val = checkNull(getObjectInternal(obj, JavaTypes.CALENDAR, null, joins));
if (val == null)
return null;
if (val instanceof Calendar)
@@ -515,6 +517,51 @@ public abstract class AbstractResult
}
@Override
+ public LocalDate getLocalDate(Object obj) throws SQLException {
+ return getLocalDateInternal(translate(obj, null), null);
+ }
+
+ protected LocalDate getLocalDateInternal(Object obj, Joins joins) throws SQLException {
+ Object val = checkNull(getObjectInternal(obj, JavaTypes.LOCAL_DATE, null, joins));
+ if (val == null)
+ return null;
+ if (val instanceof LocalDate)
+ return (LocalDate) val;
+
+ return LocalDate.parse(val.toString());
+ }
+
+ @Override
+ public LocalTime getLocalTime(Object obj) throws SQLException {
+ return getLocalTimeInternal(translate(obj, null), null);
+ }
+
+ protected LocalTime getLocalTimeInternal(Object obj, Joins joins) throws SQLException {
+ Object val = checkNull(getObjectInternal(obj, JavaTypes.LOCAL_TIME, null, joins));
+ if (val == null)
+ return null;
+ if (val instanceof LocalTime)
+ return (LocalTime) val;
+
+ return LocalTime.parse(val.toString());
+ }
+
+ @Override
+ public LocalDateTime getLocalDateTime(Object obj) throws SQLException {
+ return getLocalDateTimeInternal(translate(obj, null), null);
+ }
+
+ protected LocalDateTime getLocalDateTimeInternal(Object obj, Joins joins) throws SQLException {
+ Object val = checkNull(getObjectInternal(obj, JavaTypes.LOCAL_DATETIME, null, joins));
+ if (val == null)
+ return null;
+ if (val instanceof LocalDateTime)
+ return (LocalDateTime) val;
+
+ return LocalDateTime.parse(val.toString());
+ }
+
+ @Override
public char getChar(Object obj)
throws SQLException {
return getCharInternal(translate(obj, null), null);
@@ -594,8 +641,7 @@ public abstract class AbstractResult
protected Date getDateInternal(Object obj, Joins joins)
throws SQLException {
- Object val = checkNull(getObjectInternal(obj, JavaTypes.DATE,
- null, joins));
+ Object val = checkNull(getObjectInternal(obj, JavaTypes.DATE, null, joins));
if (val == null)
return null;
if (val instanceof Date)
@@ -615,8 +661,7 @@ public abstract class AbstractResult
return getDateInternal(translate(col, joins), cal, joins);
}
- protected java.sql.Date getDateInternal(Object obj, Calendar cal,
- Joins joins)
+ protected java.sql.Date getDateInternal(Object obj, Calendar cal, Joins joins)
throws SQLException {
return (java.sql.Date) checkNull(getObjectInternal(obj,
JavaSQLTypes.SQL_DATE, cal, joins));
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
index 3f02899..81d249f 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
@@ -45,6 +45,9 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.MessageFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -775,6 +778,33 @@ public class DBDictionary
return cal;
}
+ /**
+ * Retrieve the specified column of the SQL ResultSet to the proper
+ * {@link LocalDate} java type.
+ */
+ public LocalDate getLocalDate(ResultSet rs, int column) throws SQLException {
+ java.sql.Date date = rs.getDate(column);
+ return date != null ? date.toLocalDate() : null;
+ }
+
+ /**
+ * Retrieve the specified column of the SQL ResultSet to the proper
+ * {@link LocalTime} java type.
+ */
+ public LocalTime getLocalTime(ResultSet rs, int column) throws SQLException {
+ java.sql.Time time = rs.getTime(column);
+ return time != null ? time.toLocalTime() : null;
+ }
+
+ /**
+ * Retrieve the specified column of the SQL ResultSet to the proper
+ * {@link LocalDateTime} java type.
+ */
+ public LocalDateTime getLocalDateTime(ResultSet rs, int column) throws SQLException {
+ Timestamp tst = rs.getTimestamp(column);
+ return tst != null ? tst.toLocalDateTime() : null;
+ }
+
private ProxyManager getProxyManager() {
if (_proxyManager == null) {
_proxyManager = conf.getProxyManagerInstance();
@@ -1006,8 +1036,7 @@ public class DBDictionary
/**
* Set the given value as a parameter to the statement.
*/
- public void setAsciiStream(PreparedStatement stmnt, int idx,
- InputStream val, int length, Column col)
+ public void setAsciiStream(PreparedStatement stmnt, int idx, InputStream val, int length, Column col)
throws SQLException {
stmnt.setAsciiStream(idx, val, length);
}
@@ -1015,47 +1044,48 @@ public class DBDictionary
/**
* Set the given value as a parameter to the statement.
*/
- public void setBigDecimal(PreparedStatement stmnt, int idx, BigDecimal val,
- Column col)
+ public void setBigDecimal(PreparedStatement stmnt, int idx, BigDecimal val, Column col)
throws SQLException {
if ((col != null && col.isCompatible(Types.VARCHAR, null, 0, 0))
- || (col == null && storeLargeNumbersAsStrings))
+ || (col == null && storeLargeNumbersAsStrings)) {
setString(stmnt, idx, val.toString(), col);
- else
+ }
+ else {
stmnt.setBigDecimal(idx, val);
+ }
}
/**
* Set the given value as a parameter to the statement.
*/
- public void setBigInteger(PreparedStatement stmnt, int idx, BigInteger val,
- Column col)
+ public void setBigInteger(PreparedStatement stmnt, int idx, BigInteger val, Column col)
throws SQLException {
if ((col != null && col.isCompatible(Types.VARCHAR, null, 0, 0))
- || (col == null && storeLargeNumbersAsStrings))
+ || (col == null && storeLargeNumbersAsStrings)) {
setString(stmnt, idx, val.toString(), col);
- else
+ }
+ else {
setBigDecimal(stmnt, idx, new BigDecimal(val), col);
+ }
}
/**
* Set the given value as a parameter to the statement.
*/
- public void setBinaryStream(PreparedStatement stmnt, int idx,
- InputStream val, int length, Column col)
+ public void setBinaryStream(PreparedStatement stmnt, int idx, InputStream val, int length, Column col)
throws SQLException {
- //OPENJPA-2067: If the user has set the 'useJDBC4SetBinaryStream' property
- //then lets use the JDBC 4.0 version of the setBinaryStream method.
- if (useJDBC4SetBinaryStream) {
- if (isJDBC4){
- stmnt.setBinaryStream(idx, val);
- return;
- }
- else {
- log.trace(_loc.get("jdbc4-setbinarystream-unsupported"));
- }
- }
+ //OPENJPA-2067: If the user has set the 'useJDBC4SetBinaryStream' property
+ //then lets use the JDBC 4.0 version of the setBinaryStream method.
+ if (useJDBC4SetBinaryStream) {
+ if (isJDBC4){
+ stmnt.setBinaryStream(idx, val);
+ return;
+ }
+ else {
+ log.trace(_loc.get("jdbc4-setbinarystream-unsupported"));
+ }
+ }
stmnt.setBinaryStream(idx, val, length);
}
@@ -1072,8 +1102,7 @@ public class DBDictionary
* Set the given value as a parameter to the statement. Uses the
* {@link #serialize} method to serialize the value.
*/
- public void setBlobObject(PreparedStatement stmnt, int idx, Object val,
- Column col, JDBCStore store)
+ public void setBlobObject(PreparedStatement stmnt, int idx, Object val, Column col, JDBCStore store)
throws SQLException {
setBytes(stmnt, idx, serialize(val, store), col);
}
@@ -1169,8 +1198,7 @@ public class DBDictionary
/**
* Set the given value as a parameter to the statement.
*/
- public void setDate(PreparedStatement stmnt, int idx, java.sql.Date val,
- Calendar cal, Column col)
+ public void setDate(PreparedStatement stmnt, int idx, java.sql.Date val, Calendar cal, Column col)
throws SQLException {
if (cal == null)
stmnt.setDate(idx, val);
@@ -1181,14 +1209,40 @@ public class DBDictionary
/**
* Set the given value as a parameter to the statement.
*/
- public void setCalendar(PreparedStatement stmnt, int idx, Calendar val,
- Column col)
+ public void setCalendar(PreparedStatement stmnt, int idx, Calendar val, Column col)
throws SQLException {
// by default we merely delegate to the Date parameter
setDate(stmnt, idx, val.getTime(), col);
}
/**
+ * Set the given LocalDate value as a parameter to the statement.
+ *
+ */
+ public void setLocalDate(PreparedStatement stmnt, int idx, LocalDate val, Column col)
+ throws SQLException {
+ setDate(stmnt, idx, java.sql.Date.valueOf(val), null, col);
+ }
+
+ /**
+ * Set the given LocalTime value as a parameter to the statement.
+ *
+ */
+ public void setLocalTime(PreparedStatement stmnt, int idx, LocalTime val, Column col)
+ throws SQLException {
+ setTime(stmnt, idx, java.sql.Time.valueOf(val), null, col);
+ }
+
+ /**
+ * Set the given LocalTime value as a parameter to the statement.
+ *
+ */
+ public void setLocalDateTime(PreparedStatement stmnt, int idx, LocalDateTime val, Column col)
+ throws SQLException {
+ setTimestamp(stmnt, idx, java.sql.Timestamp.valueOf(val), null, col);
+ }
+
+ /**
* Set the given value as a parameter to the statement.
*/
public void setDouble(PreparedStatement stmnt, int idx, double val,
@@ -1398,6 +1452,15 @@ public class DBDictionary
case JavaTypes.CALENDAR:
setCalendar(stmnt, idx, (Calendar) val, col);
break;
+ case JavaTypes.LOCAL_DATE:
+ setLocalDate(stmnt, idx, (LocalDate) val, col);
+ break;
+ case JavaTypes.LOCAL_TIME:
+ setLocalTime(stmnt, idx, (LocalTime) val, col);
+ break;
+ case JavaTypes.LOCAL_DATETIME:
+ setLocalDateTime(stmnt, idx, (LocalDateTime) val, col);
+ break;
case JavaTypes.BIGDECIMAL:
setBigDecimal(stmnt, idx, (BigDecimal) val, col);
break;
@@ -1547,6 +1610,15 @@ public class DBDictionary
setDate(stmnt, idx, (Date) val, col);
else if (val instanceof Calendar)
setDate(stmnt, idx, ((Calendar) val).getTime(), col);
+ else if (val instanceof LocalDate) {
+ setLocalDate(stmnt, idx, (LocalDate) val, col);
+ }
+ else if (val instanceof LocalTime) {
+ setLocalTime(stmnt, idx, (LocalTime) val, col);
+ }
+ else if (val instanceof LocalDateTime) {
+ setLocalDateTime(stmnt, idx, (LocalDateTime) val, col);
+ }
else if (val instanceof Reader)
setCharacterStream(stmnt, idx, (Reader) val,
(sized == null) ? 0 : sized.size, col);
@@ -1725,6 +1797,16 @@ public class DBDictionary
case JavaTypes.CALENDAR:
case JavaTypes.DATE:
return getPreferredType(Types.TIMESTAMP);
+ case JavaTypes.LOCAL_DATE:
+ return getPreferredType(Types.DATE);
+ case JavaTypes.LOCAL_TIME:
+ return getPreferredType(Types.TIME);
+ case JavaTypes.LOCAL_DATETIME:
+ return getPreferredType(Types.TIMESTAMP);
+ case JavaTypes.OFFSET_TIME:
+ return getPreferredType(Types.TIME);
+ case JavaTypes.OFFSET_DATETIME:
+ return getPreferredType(Types.TIMESTAMP);
case JavaSQLTypes.SQL_ARRAY:
return getPreferredType(Types.ARRAY);
case JavaSQLTypes.BINARY_STREAM:
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MergedResult.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MergedResult.java
index 3334399..c22539e 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MergedResult.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/MergedResult.java
@@ -29,6 +29,9 @@ import java.sql.Ref;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
@@ -49,8 +52,7 @@ import org.apache.openjpa.util.UnsupportedException;
*
* @author Abe White
*/
-public class MergedResult
- implements Result {
+public class MergedResult implements Result {
private static final byte NEXT = 0;
private static final byte CURRENT = 1;
@@ -338,6 +340,21 @@ public class MergedResult
}
@Override
+ public LocalDate getLocalDate(Object obj) throws SQLException {
+ return _res[_idx].getLocalDate(obj);
+ }
+
+ @Override
+ public LocalTime getLocalTime(Object obj) throws SQLException {
+ return _res[_idx].getLocalTime(obj);
+ }
+
+ @Override
+ public LocalDateTime getLocalDateTime(Object obj) throws SQLException {
+ return _res[_idx].getLocalDateTime(obj);
+ }
+
+ @Override
public char getChar(Object obj)
throws SQLException {
return _res[_idx].getChar(obj);
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Result.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Result.java
index f803e42..35abde7 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Result.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Result.java
@@ -29,6 +29,9 @@ import java.sql.Ref;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@@ -285,6 +288,24 @@ public interface Result
/**
* Return the value stored in the given column or id.
*/
+ LocalDate getLocalDate(Object obj)
+ throws SQLException;
+
+ /**
+ * Return the value stored in the given column or id.
+ */
+ LocalTime getLocalTime(Object obj)
+ throws SQLException;
+
+ /**
+ * Return the value stored in the given column or id.
+ */
+ LocalDateTime getLocalDateTime(Object obj)
+ throws SQLException;
+
+ /**
+ * Return the value stored in the given column or id.
+ */
char getChar(Object obj)
throws SQLException;
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
index 9b5a1aa..143c524 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ResultSetResult.java
@@ -33,6 +33,9 @@ import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
@@ -318,6 +321,25 @@ public class ResultSetResult
}
@Override
+ protected LocalDate getLocalDateInternal(Object obj, Joins joins)
+ throws SQLException {
+ return _dict.getLocalDate(_rs, ((Number) obj).intValue());
+ }
+
+ @Override
+ protected LocalTime getLocalTimeInternal(Object obj, Joins joins)
+ throws SQLException {
+ return _dict.getLocalTime(_rs, ((Number) obj).intValue());
+ }
+
+ @Override
+ protected LocalDateTime getLocalDateTimeInternal(Object obj, Joins joins)
+ throws SQLException {
+ return _dict.getLocalDateTime(_rs, ((Number) obj).intValue());
+ }
+
+
+ @Override
protected char getCharInternal(Object obj, Joins joins)
throws SQLException {
return _dict.getChar(_rs, ((Number) obj).intValue());
@@ -385,8 +407,7 @@ public class ResultSetResult
}
@Override
- protected Object getObjectInternal(Object obj, int metaTypeCode,
- Object arg, Joins joins)
+ protected Object getObjectInternal(Object obj, int metaTypeCode, Object arg, Joins joins)
throws SQLException {
if (metaTypeCode == -1 && obj instanceof Column)
metaTypeCode = ((Column) obj).getJavaType();
@@ -439,6 +460,12 @@ public class ResultSetResult
return getDateInternal(obj, joins);
case JavaTypes.CALENDAR:
return getCalendarInternal(obj, joins);
+ case JavaTypes.LOCAL_DATE:
+ return getLocalDateInternal(obj, joins);
+ case JavaTypes.LOCAL_TIME:
+ return getLocalTimeInternal(obj, joins);
+ case JavaTypes.LOCAL_DATETIME:
+ return getLocalDateTimeInternal(obj, joins);
case JavaTypes.BIGDECIMAL:
return getBigDecimalInternal(obj, joins);
case JavaTypes.NUMBER:
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java
index 4cefe80..349f244 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java
@@ -181,6 +181,11 @@ abstract class AttachStrategy
break;
case JavaTypes.DATE:
case JavaTypes.CALENDAR:
+ case JavaTypes.LOCAL_DATE:
+ case JavaTypes.LOCAL_TIME:
+ case JavaTypes.LOCAL_DATETIME:
+ case JavaTypes.OFFSET_TIME:
+ case JavaTypes.OFFSET_DATETIME:
case JavaTypes.NUMBER:
case JavaTypes.BOOLEAN_OBJ:
case JavaTypes.BYTE_OBJ:
@@ -219,7 +224,7 @@ abstract class AttachStrategy
if (cpy != null) {
frmpc = cpy;
} else {
- frmpc = getReference(manager, frmpc, sm, fmd);
+ frmpc = getReference(manager, frmpc, sm, fmd);
}
}
else {
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java
index c2ffd07..c1c9f8f 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/JavaTypes.java
@@ -24,6 +24,11 @@ import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -84,6 +89,15 @@ public class JavaTypes {
public static final int INPUT_READER = 31;
public static final int ENUM = 32;
+ // Java8 time API
+ public static final int LOCAL_DATE = 33;
+ public static final int LOCAL_TIME = 34;
+ public static final int LOCAL_DATETIME = 35;
+ public static final int OFFSET_TIME = 36;
+ public static final int OFFSET_DATETIME = 37;
+
+
+
private static final Localizer _loc = Localizer.forPackage(JavaTypes.class);
private static final Map<Class<?>, Integer> _typeCodes = new HashMap<>();
@@ -110,6 +124,13 @@ public class JavaTypes {
_typeCodes.put(PersistenceCapable.class, PC_UNTYPED);
_typeCodes.put(Properties.class, MAP);
_typeCodes.put(Calendar.class, CALENDAR);
+
+ // Java8 time API
+ _typeCodes.put(LocalDate.class, LOCAL_DATE);
+ _typeCodes.put(LocalTime.class, LOCAL_TIME);
+ _typeCodes.put(LocalDateTime.class, LOCAL_DATETIME);
+ _typeCodes.put(OffsetTime.class, OFFSET_TIME);
+ _typeCodes.put(OffsetDateTime.class, OFFSET_DATETIME);
}
/**
@@ -139,9 +160,10 @@ public class JavaTypes {
}
}
- Integer code = (Integer) _typeCodes.get(type);
- if (code != null)
+ Integer code = _typeCodes.get(type);
+ if (code != null) {
return code.intValue();
+ }
// have to do this first to catch custom collection and map types;
// on resolve we figure out if these custom types are
@@ -238,7 +260,7 @@ public class JavaTypes {
*/
private static Class<?> classForName(String name, ClassMetaData meta,
Class<?> dec, ValueMetaData vmd, ClassLoader loader) {
- return classForName(name, meta, dec, vmd, loader, true);
+ return classForName(name, meta, dec, vmd, loader, true);
}
/**
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/Java8TimeTypes.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/Java8TimeTypes.java
new file mode 100644
index 0000000..d5b1681
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/Java8TimeTypes.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.openjpa.persistence.simple;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Date;
+
+/**
+ * Java8 DateTime types which are required by the JPA-2.2 spec
+ */
+@Entity
+public class Java8TimeTypes {
+
+ @Id
+ private int id;
+
+ private java.util.Date oldDateField;
+
+ private LocalTime localTimeField;
+ private LocalDate localDateField;
+ private LocalDateTime localDateTimeField;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Date getOldDateField() {
+ return oldDateField;
+ }
+
+ public void setOldDateField(Date oldDateField) {
+ this.oldDateField = oldDateField;
+ }
+
+ public LocalTime getLocalTimeField() {
+ return localTimeField;
+ }
+
+ public void setLocalTimeField(LocalTime localTimeField) {
+ this.localTimeField = localTimeField;
+ }
+
+ public LocalDate getLocalDateField() {
+ return localDateField;
+ }
+
+ public void setLocalDateField(LocalDate localDateField) {
+ this.localDateField = localDateField;
+ }
+
+ public LocalDateTime getLocalDateTimeField() {
+ return localDateTimeField;
+ }
+
+ public void setLocalDateTimeField(LocalDateTime localDateTimeField) {
+ this.localDateTimeField = localDateTimeField;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestBasicAnnotation.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestBasicAnnotation.java
index 754e30c..c0f0d90 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestBasicAnnotation.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestBasicAnnotation.java
@@ -20,6 +20,7 @@ package org.apache.openjpa.persistence.simple;
import java.math.BigDecimal;
import java.time.LocalDate;
+import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
@@ -35,6 +36,7 @@ import org.apache.openjpa.persistence.test.SingleEMFTestCase;
*/
public class TestBasicAnnotation extends SingleEMFTestCase {
private static String VAL_LOCAL_DATE = "2019-01-01";
+ private static String VAL_LOCAL_TIME = "14:57:15";
@Override
public void setUp() {
@@ -61,6 +63,7 @@ public class TestBasicAnnotation extends SingleEMFTestCase {
aft.setWDoubleField(new Double(1));
aft.setLocalDateField(LocalDate.parse(VAL_LOCAL_DATE));
+ aft.setLocalTimeField(LocalTime.parse(VAL_LOCAL_TIME));
em.persist(aft);
@@ -87,6 +90,7 @@ public class TestBasicAnnotation extends SingleEMFTestCase {
assertNotNull(aftQuery.getWDoubleField());
assertEquals(LocalDate.parse(VAL_LOCAL_DATE), aftQuery.getLocalDateField());
+ assertEquals(LocalTime.parse(VAL_LOCAL_TIME), aftQuery.getLocalTimeField());
em.close();
}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestJava8TimeTypes.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestJava8TimeTypes.java
new file mode 100644
index 0000000..3de2258
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/simple/TestJava8TimeTypes.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.openjpa.persistence.simple;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+import javax.persistence.EntityManager;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Date;
+
+/**
+ * Test for JPA-2.2 java.time.* functionality
+ */
+public class TestJava8TimeTypes extends SingleEMFTestCase {
+ private static String VAL_LOCAL_DATE = "2019-01-01";
+ private static String VAL_LOCAL_TIME = "14:57:15";
+ private static String VAL_LOCAL_DATETIME = "2019-01-01T01:00:00";
+
+ @Override
+ public void setUp() {
+ setUp(CLEAR_TABLES, Java8TimeTypes.class);
+ }
+
+ public void testJava8Types() throws Exception {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ Java8TimeTypes e = new Java8TimeTypes();
+ e.setId(1);
+ e.setOldDateField(new Date());
+ e.setLocalTimeField(LocalTime.parse(VAL_LOCAL_TIME));
+ e.setLocalDateField(LocalDate.parse(VAL_LOCAL_DATE));
+ e.setLocalDateTimeField(LocalDateTime.parse(VAL_LOCAL_DATETIME));
+
+ em.persist(e);
+ em.getTransaction().commit();
+ em.close();
+
+ // now read it back.
+ em = emf.createEntityManager();
+ Java8TimeTypes eRead = em.find(Java8TimeTypes.class, 1);
+
+ assertEquals(LocalTime.parse(VAL_LOCAL_TIME), eRead.getLocalTimeField());
+ assertEquals(LocalDate.parse(VAL_LOCAL_DATE), eRead.getLocalDateField());
+ assertEquals(LocalDateTime.parse(VAL_LOCAL_DATETIME), eRead.getLocalDateTimeField());
+ }
+
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/strategy/value/ValueStrategyHandler.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/strategy/value/ValueStrategyHandler.java
index 26d2ea1..2017c24 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/strategy/value/ValueStrategyHandler.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/strategy/value/ValueStrategyHandler.java
@@ -27,42 +27,42 @@ import org.apache.openjpa.meta.JavaTypes;
public class ValueStrategyHandler extends AbstractValueHandler {
- private static final long serialVersionUID = 8371304701543038775L;
+ private static final long serialVersionUID = 8371304701543038775L;
- private static final ValueStrategyHandler _instance = new ValueStrategyHandler();
+ private static final ValueStrategyHandler _instance = new ValueStrategyHandler();
- public static ValueStrategyHandler getInstance(){
- return _instance;
- }
+ public static ValueStrategyHandler getInstance(){
+ return _instance;
+ }
- @Override
- public Column[] map(ValueMapping arg0, String name, ColumnIO arg2,
- boolean arg3) {
+ @Override
+ public Column[] map(ValueMapping arg0, String name, ColumnIO arg2,
+ boolean arg3) {
- Column col = new Column();
- col.setName(name);
- col.setJavaType(JavaTypes.STRING);
+ Column col = new Column();
+ col.setName(name);
+ col.setJavaType(JavaTypes.STRING);
- return new Column[]{col};
- }
+ return new Column[]{col};
+ }
- @Override
+ @Override
public Object toDataStoreValue(ValueMapping vm, Object val, JDBCStore store){
- if(val == null){
- return null;
- }
+ if(val == null){
+ return null;
+ }
- return val.toString();
- }
+ return val.toString();
+ }
- @Override
+ @Override
public Object toObjectValue(ValueMapping vm, Object val){
- if(val == null){
- return null;
- }
+ if(val == null){
+ return null;
+ }
- return val.toString();
- }
+ return val.toString();
+ }
}
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
index 21e9358..6953db7 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
@@ -227,6 +227,11 @@ public class PersistenceMetaDataDefaults
case JavaTypes.BIGDECIMAL:
case JavaTypes.BIGINTEGER:
case JavaTypes.DATE:
+ case JavaTypes.LOCAL_DATE:
+ case JavaTypes.LOCAL_TIME:
+ case JavaTypes.LOCAL_DATETIME:
+ case JavaTypes.OFFSET_TIME:
+ case JavaTypes.OFFSET_DATETIME:
return BASIC;
case JavaTypes.OBJECT:
if (Enum.class.isAssignableFrom(type))
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java
index 56b0a37..a3b0dee 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/meta/AbstractManagedType.java
@@ -20,6 +20,11 @@ package org.apache.openjpa.persistence.meta;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
@@ -137,6 +142,21 @@ public abstract class AbstractManagedType<X> extends Types.BaseType<X>
case JavaTypes.DATE:
attrs.add(new Members.SingularAttributeImpl<X, Date>(this, f));
break;
+ case JavaTypes.LOCAL_DATE:
+ attrs.add(new Members.SingularAttributeImpl<X, LocalDate>(this, f));
+ break;
+ case JavaTypes.LOCAL_TIME:
+ attrs.add(new Members.SingularAttributeImpl<X, LocalTime>(this, f));
+ break;
+ case JavaTypes.LOCAL_DATETIME:
+ attrs.add(new Members.SingularAttributeImpl<X, LocalDateTime>(this, f));
+ break;
+ case JavaTypes.OFFSET_TIME:
+ attrs.add(new Members.SingularAttributeImpl<X, OffsetTime>(this, f));
+ break;
+ case JavaTypes.OFFSET_DATETIME:
+ attrs.add(new Members.SingularAttributeImpl<X, OffsetDateTime>(this, f));
+ break;
case JavaTypes.CALENDAR:
attrs.add(new Members.SingularAttributeImpl<X, Calendar>(this, f));
break;