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:
Mark Struberg 2019-01-20 23:51:10 +01:00
parent 61b48040db
commit e57fd518b3
18 changed files with 474 additions and 161 deletions

View File

@ -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;
}

View File

@ -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))

View File

@ -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) {

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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));

View File

@ -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:

View File

@ -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 {

View File

@ -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.
*/

View File

@ -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:

View File

@ -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 {

View File

@ -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);
}
/**

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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))

View File

@ -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;