mirror of https://github.com/apache/openjpa.git
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.
This commit is contained in:
parent
61b48040db
commit
e57fd518b3
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
@ -514,6 +516,51 @@ public abstract class AbstractResult
|
|||
return cal;
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
@ -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));
|
||||
|
|
|
@ -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,13 +1209,39 @@ 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.
|
||||
*/
|
||||
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
@ -337,6 +339,21 @@ public class MergedResult
|
|||
return _res[_idx].getCalendar(obj);
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -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;
|
||||
|
@ -282,6 +285,24 @@ public interface Result
|
|||
Calendar getCalendar(Object obj)
|
||||
throws SQLException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
@ -317,6 +320,25 @@ public class ResultSetResult
|
|||
return _dict.getCalendar(_rs, ((Number) obj).intValue());
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue