You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by ab...@apache.org on 2019/06/10 13:53:12 UTC

[cayenne] 03/04: CAY-2557 Create duration extended type

This is an automated email from the ASF dual-hosted git repository.

abulatski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit c4c29ecbcba83718b2339a3ecf28cf6ad37b57b5
Author: Arseni Bulatski <an...@gmail.com>
AuthorDate: Thu May 2 13:46:06 2019 +0300

    CAY-2557 Create duration extended type
---
 .../apache/cayenne/access/types/DurationType.java  | 139 ++++++++++++++++++
 .../cayenne/access/types/DurationValueType.java    |  53 -------
 .../cayenne/configuration/server/ServerModule.java |   8 +-
 .../apache/cayenne/access/types/Java8TimeIT.java   |  43 +++++-
 .../testdo/java8/auto/_DurationTestEntity.java     | 161 +++++++++++++++++++--
 .../cayenne/unit/di/server/ServerCaseModule.java   |   6 +-
 cayenne-server/src/test/resources/java8.map.xml    |  18 ++-
 .../org/apache/cayenne/modeler/Application.java    |  16 +-
 8 files changed, 357 insertions(+), 87 deletions(-)

diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationType.java
new file mode 100644
index 0000000..ab2da3c
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationType.java
@@ -0,0 +1,139 @@
+package org.apache.cayenne.access.types;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.time.Duration;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.dba.TypesMapping;
+
+public class DurationType implements ExtendedType<Duration> {
+
+    @Override
+    public String getClassName() {
+        return Duration.class.getName();
+    }
+
+    protected Object convertToJdbcObject(Duration val, int type) {
+        if(type == Types.INTEGER) {
+            return new Long(val.toMillis()).intValue();
+        } else if(type == Types.NUMERIC) {
+            return val.toMillis();
+        } else if(type == Types.DECIMAL) {
+            return val.toMillis();
+        } else if (type == Types.BIGINT) {
+            return val.toMillis();
+        } else if (type == Types.VARCHAR) {
+            return val.toString();
+        } else if(type == Types.LONGVARCHAR) {
+            return val.toString();
+        } else if(type == Types.NVARCHAR) {
+            return val.toString();
+        } else if(type == Types.LONGNVARCHAR) {
+            return val.toString();
+        } else {
+            throw new IllegalArgumentException(
+                    "Only INTEGER, NUMERIC, DECIMAL, BIGINT, VARCHAR, LONGVARCHAR, NVARCHAR, LONGNVARCHAR " +
+                            "can be mapped as '" + getClassName()
+                            + "', got " + TypesMapping.getSqlNameByType(type));
+        }
+    }
+
+    @Override
+    public void setJdbcObject(PreparedStatement statement, Duration value, int pos, int type, int scale) throws Exception {
+        if(value == null) {
+            statement.setNull(pos, type);
+        } else {
+            statement.setObject(pos, convertToJdbcObject(value, type), type);
+        }
+    }
+
+    @Override
+    public Duration materializeObject(ResultSet rs, int index, int type) throws Exception {
+        Duration val = null;
+        switch(type) {
+            case Types.INTEGER:
+                val = Duration.ofMillis(rs.getInt(index));
+                break;
+            case Types.NUMERIC:
+                val = Duration.ofMillis(rs.getBigDecimal(index).longValue());
+                break;
+            case Types.DECIMAL:
+                val = Duration.ofMillis(rs.getBigDecimal(index).longValue());
+                break;
+            case Types.BIGINT:
+                val = Duration.ofMillis(rs.getLong(index));
+                break;
+            case Types.VARCHAR:
+                val = Duration.parse(rs.getString(index));
+                break;
+            case Types.LONGVARCHAR:
+                val = Duration.parse(rs.getString(index));
+                break;
+            case Types.NVARCHAR:
+                val = Duration.parse(rs.getNString(index));
+                break;
+            case Types.LONGNVARCHAR:
+                val = Duration.parse(rs.getNString(index));
+                break;
+        }
+
+        if(rs.wasNull()) {
+            return null;
+        } else if(val != null) {
+            return val;
+        } else {
+            throw new CayenneRuntimeException("Can't materialize " + rs.getObject(index) + " of type: " + type);
+        }
+    }
+
+    @Override
+    public Duration materializeObject(CallableStatement rs, int index, int type) throws Exception {
+        Duration val = null;
+        switch(type) {
+            case Types.INTEGER:
+                val = Duration.ofMillis(rs.getInt(index));
+                break;
+            case Types.NUMERIC:
+                val = Duration.ofMillis(rs.getBigDecimal(index).longValue());
+                break;
+            case Types.DECIMAL:
+                val = Duration.ofMillis(rs.getBigDecimal(index).longValue());
+                break;
+            case Types.BIGINT:
+                val = Duration.ofMillis(rs.getLong(index));
+                break;
+            case Types.VARCHAR:
+                val = Duration.parse(rs.getString(index));
+                break;
+            case Types.LONGVARCHAR:
+                val = Duration.parse(rs.getString(index));
+                break;
+            case Types.NVARCHAR:
+                val = Duration.parse(rs.getNString(index));
+                break;
+            case Types.LONGNVARCHAR:
+                val = Duration.parse(rs.getNString(index));
+                break;
+        }
+
+        if(rs.wasNull()) {
+            return null;
+        } else if(val != null) {
+            return val;
+        } else {
+            throw new CayenneRuntimeException("Can't materialize " + rs.getObject(index) + " of type: " + type);
+        }
+    }
+
+    @Override
+    public String toString(Duration value) {
+        if(value == null) {
+            return "NULL";
+        }
+
+        return "\'" + value.toString() + "\'";
+    }
+}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationValueType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationValueType.java
deleted file mode 100644
index 1d2b0f4..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/DurationValueType.java
+++ /dev/null
@@ -1,53 +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.cayenne.access.types;
-
-import java.time.Duration;
-
-/**
- * @since 4.2
- */
-public class DurationValueType implements ValueObjectType<Duration, String> {
-
-    @Override
-    public Class<String> getTargetType() {
-        return String.class;
-    }
-
-    @Override
-    public Class<Duration> getValueType() {
-        return Duration.class;
-    }
-
-    @Override
-    public Duration toJavaObject(String value) {
-        return Duration.parse(value);
-    }
-
-    @Override
-    public String fromJavaObject(Duration object) {
-        return object.toString();
-    }
-
-    @Override
-    public String toCacheKey(Duration object) {
-        return object.toString();
-    }
-}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 92fadaa..5c14a21 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -50,7 +50,7 @@ import org.apache.cayenne.access.types.CharacterValueType;
 import org.apache.cayenne.access.types.DateType;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.DoubleType;
-import org.apache.cayenne.access.types.DurationValueType;
+import org.apache.cayenne.access.types.DurationType;
 import org.apache.cayenne.access.types.ExtendedType;
 import org.apache.cayenne.access.types.ExtendedTypeFactory;
 import org.apache.cayenne.access.types.FloatType;
@@ -413,8 +413,11 @@ public class ServerModule implements Module {
                 .add(new DateType())
                 .add(new TimeType())
                 .add(new TimestampType())
+                .add(new DurationType())
                 // should be converted from ExtendedType to ValueType
-                .add(new UtilDateType()).add(new CalendarType<>(GregorianCalendar.class)).add(new CalendarType<>(Calendar.class));
+                .add(new UtilDateType())
+                .add(new CalendarType<>(GregorianCalendar.class))
+                .add(new CalendarType<>(Calendar.class));
         contributeUserTypes(binder);
         contributeTypeFactories(binder);
 
@@ -425,7 +428,6 @@ public class ServerModule implements Module {
                 .add(LocalDateValueType.class)
                 .add(LocalTimeValueType.class)
                 .add(LocalDateTimeValueType.class)
-                .add(DurationValueType.class)
                 .add(PeriodValueType.class)
                 .add(CharacterValueType.class);
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/types/Java8TimeIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/types/Java8TimeIT.java
index 632b2be..2c51576 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/types/Java8TimeIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/types/Java8TimeIT.java
@@ -151,15 +151,50 @@ public class Java8TimeIT extends ServerCase {
 	public void testJava8Duration() {
 		DurationTestEntity durationTestEntity = context.newObject(DurationTestEntity.class);
 		Duration duration = Duration.ofDays(10);
-		durationTestEntity.setDurationField(duration);
+		durationTestEntity.setDurationBigInt(duration);
+		durationTestEntity.setDurationDecimal(duration);
+		durationTestEntity.setDurationInt(duration);
+		durationTestEntity.setDurationLongNVarchar(duration);
+		durationTestEntity.setDurationLongVarchar(duration);
+		durationTestEntity.setDurationNumeric(duration);
+		durationTestEntity.setDurationVarchar(duration);
+		durationTestEntity.setDurationNVarchar(duration);
 
 		context.commitChanges();
 
 		DurationTestEntity testRead = ObjectSelect.query(DurationTestEntity.class).selectOne(context);
 
-		assertNotNull(testRead.getDurationField());
-		assertEquals(Duration.class, testRead.getDurationField().getClass());
-		assertEquals(duration, testRead.getDurationField());
+		assertNotNull(testRead.getDurationBigInt());
+		assertEquals(Duration.class, testRead.getDurationBigInt().getClass());
+		assertEquals(duration, testRead.getDurationBigInt());
+
+		assertNotNull(testRead.getDurationDecimal());
+		assertEquals(Duration.class, testRead.getDurationDecimal().getClass());
+		assertEquals(duration, testRead.getDurationDecimal());
+
+		assertNotNull(testRead.getDurationInt());
+		assertEquals(Duration.class, testRead.getDurationInt().getClass());
+		assertEquals(duration, testRead.getDurationInt());
+
+		assertNotNull(testRead.getDurationLongNVarchar());
+		assertEquals(Duration.class, testRead.getDurationLongNVarchar().getClass());
+		assertEquals(duration, testRead.getDurationLongNVarchar());
+
+		assertNotNull(testRead.getDurationLongVarchar());
+		assertEquals(Duration.class, testRead.getDurationLongVarchar().getClass());
+		assertEquals(duration, testRead.getDurationLongVarchar());
+
+		assertNotNull(testRead.getDurationNumeric());
+		assertEquals(Duration.class, testRead.getDurationNumeric().getClass());
+		assertEquals(duration, testRead.getDurationNumeric());
+
+		assertNotNull(testRead.getDurationVarchar());
+		assertEquals(Duration.class, testRead.getDurationVarchar().getClass());
+		assertEquals(duration, testRead.getDurationVarchar());
+
+		assertNotNull(testRead.getDurationNVarchar());
+		assertEquals(Duration.class, testRead.getDurationNVarchar().getClass());
+		assertEquals(duration, testRead.getDurationNVarchar());
 	}
 
 	@Test
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/java8/auto/_DurationTestEntity.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/java8/auto/_DurationTestEntity.java
index d0b1fd0..3b9d018 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/testdo/java8/auto/_DurationTestEntity.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/java8/auto/_DurationTestEntity.java
@@ -21,19 +21,103 @@ public abstract class _DurationTestEntity extends BaseDataObject {
 
     public static final String ID_PK_COLUMN = "ID";
 
-    public static final BaseProperty<Duration> DURATION_FIELD = PropertyFactory.createBase("durationField", Duration.class);
+    public static final BaseProperty<Duration> DURATION_VARCHAR = PropertyFactory.createBase("durationVarchar", Duration.class);
+    public static final BaseProperty<Duration> DURATION_BIG_INT = PropertyFactory.createBase("durationBigInt", Duration.class);
+    public static final BaseProperty<Duration> DURATION_NUMERIC = PropertyFactory.createBase("durationNumeric", Duration.class);
+    public static final BaseProperty<Duration> DURATION_DECIMAL = PropertyFactory.createBase("durationDecimal", Duration.class);
+    public static final BaseProperty<Duration> DURATION_LONG_VARCHAR = PropertyFactory.createBase("durationLongVarchar", Duration.class);
+    public static final BaseProperty<Duration> DURATION_NVARCHAR = PropertyFactory.createBase("durationNVarchar", Duration.class);
+    public static final BaseProperty<Duration> DURATION_LONG_NVARCHAR = PropertyFactory.createBase("durationLongNVarchar", Duration.class);
+    public static final BaseProperty<Duration> DURATION_INT = PropertyFactory.createBase("durationInt", Duration.class);
+
+    protected Duration durationVarchar;
+    protected Duration durationBigInt;
+    protected Duration durationNumeric;
+    protected Duration durationDecimal;
+    protected Duration durationLongVarchar;
+    protected Duration durationNVarchar;
+    protected Duration durationLongNVarchar;
+    protected Duration durationInt;
+
+
+    public void setDurationVarchar(Duration durationVarchar) {
+        beforePropertyWrite("durationVarchar", this.durationVarchar, durationVarchar);
+        this.durationVarchar = durationVarchar;
+    }
+
+    public Duration getDurationVarchar() {
+        beforePropertyRead("durationVarchar");
+        return this.durationVarchar;
+    }
+
+    public void setDurationBigInt(Duration durationBigInt) {
+        beforePropertyWrite("durationBigInt", this.durationBigInt, durationBigInt);
+        this.durationBigInt = durationBigInt;
+    }
+
+    public Duration getDurationBigInt() {
+        beforePropertyRead("durationBigInt");
+        return this.durationBigInt;
+    }
+
+    public void setDurationNumeric(Duration durationNumeric) {
+        beforePropertyWrite("durationNumeric", this.durationNumeric, durationNumeric);
+        this.durationNumeric = durationNumeric;
+    }
+
+    public Duration getDurationNumeric() {
+        beforePropertyRead("durationNumeric");
+        return this.durationNumeric;
+    }
+
+    public void setDurationDecimal(Duration durationDecimal) {
+        beforePropertyWrite("durationDecimal", this.durationDecimal, durationDecimal);
+        this.durationDecimal = durationDecimal;
+    }
+
+    public Duration getDurationDecimal() {
+        beforePropertyRead("durationDecimal");
+        return this.durationDecimal;
+    }
+
+    public void setDurationLongVarchar(Duration durationLongVarchar) {
+        beforePropertyWrite("durationLongVarchar", this.durationLongVarchar, durationLongVarchar);
+        this.durationLongVarchar = durationLongVarchar;
+    }
+
+    public Duration getDurationLongVarchar() {
+        beforePropertyRead("durationLongVarchar");
+        return this.durationLongVarchar;
+    }
+
+    public void setDurationNVarchar(Duration durationNVarchar) {
+        beforePropertyWrite("durationNVarchar", this.durationNVarchar, durationNVarchar);
+        this.durationNVarchar = durationNVarchar;
+    }
+
+    public Duration getDurationNVarchar() {
+        beforePropertyRead("durationNVarchar");
+        return this.durationNVarchar;
+    }
 
-    protected Duration durationField;
+    public void setDurationLongNVarchar(Duration durationLongNVarchar) {
+        beforePropertyWrite("durationLongNVarchar", this.durationLongNVarchar, durationLongNVarchar);
+        this.durationLongNVarchar = durationLongNVarchar;
+    }
 
+    public Duration getDurationLongNVarchar() {
+        beforePropertyRead("durationLongNVarchar");
+        return this.durationLongNVarchar;
+    }
 
-    public void setDurationField(Duration durationField) {
-        beforePropertyWrite("durationField", this.durationField, durationField);
-        this.durationField = durationField;
+    public void setDurationInt(Duration durationInt) {
+        beforePropertyWrite("durationInt", this.durationInt, durationInt);
+        this.durationInt = durationInt;
     }
 
-    public Duration getDurationField() {
-        beforePropertyRead("durationField");
-        return this.durationField;
+    public Duration getDurationInt() {
+        beforePropertyRead("durationInt");
+        return this.durationInt;
     }
 
     @Override
@@ -43,8 +127,22 @@ public abstract class _DurationTestEntity extends BaseDataObject {
         }
 
         switch(propName) {
-            case "durationField":
-                return this.durationField;
+            case "durationVarchar":
+                return this.durationVarchar;
+            case "durationBigInt":
+                return this.durationBigInt;
+            case "durationNumeric":
+                return this.durationNumeric;
+            case "durationDecimal":
+                return this.durationDecimal;
+            case "durationLongVarchar":
+                return this.durationLongVarchar;
+            case "durationNVarchar":
+                return this.durationNVarchar;
+            case "durationLongNVarchar":
+                return this.durationLongNVarchar;
+            case "durationInt":
+                return this.durationInt;
             default:
                 return super.readPropertyDirectly(propName);
         }
@@ -57,8 +155,29 @@ public abstract class _DurationTestEntity extends BaseDataObject {
         }
 
         switch (propName) {
-            case "durationField":
-                this.durationField = (Duration)val;
+            case "durationVarchar":
+                this.durationVarchar = (Duration)val;
+                break;
+            case "durationBigInt":
+                this.durationBigInt = (Duration)val;
+                break;
+            case "durationNumeric":
+                this.durationNumeric = (Duration)val;
+                break;
+            case "durationDecimal":
+                this.durationDecimal = (Duration)val;
+                break;
+            case "durationLongVarchar":
+                this.durationLongVarchar = (Duration)val;
+                break;
+            case "durationNVarchar":
+                this.durationNVarchar = (Duration)val;
+                break;
+            case "durationLongNVarchar":
+                this.durationLongNVarchar = (Duration)val;
+                break;
+            case "durationInt":
+                this.durationInt = (Duration)val;
                 break;
             default:
                 super.writePropertyDirectly(propName, val);
@@ -76,13 +195,27 @@ public abstract class _DurationTestEntity extends BaseDataObject {
     @Override
     protected void writeState(ObjectOutputStream out) throws IOException {
         super.writeState(out);
-        out.writeObject(this.durationField);
+        out.writeObject(this.durationVarchar);
+        out.writeObject(this.durationBigInt);
+        out.writeObject(this.durationNumeric);
+        out.writeObject(this.durationDecimal);
+        out.writeObject(this.durationLongVarchar);
+        out.writeObject(this.durationNVarchar);
+        out.writeObject(this.durationLongNVarchar);
+        out.writeObject(this.durationInt);
     }
 
     @Override
     protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
         super.readState(in);
-        this.durationField = (Duration)in.readObject();
+        this.durationVarchar = (Duration)in.readObject();
+        this.durationBigInt = (Duration)in.readObject();
+        this.durationNumeric = (Duration)in.readObject();
+        this.durationDecimal = (Duration)in.readObject();
+        this.durationLongVarchar = (Duration)in.readObject();
+        this.durationNVarchar = (Duration)in.readObject();
+        this.durationLongNVarchar = (Duration)in.readObject();
+        this.durationInt = (Duration)in.readObject();
     }
 
 }
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
index 2080b0b..674ebda 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
@@ -38,7 +38,7 @@ import org.apache.cayenne.access.types.CharacterValueType;
 import org.apache.cayenne.access.types.DateType;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.DoubleType;
-import org.apache.cayenne.access.types.DurationValueType;
+import org.apache.cayenne.access.types.DurationType;
 import org.apache.cayenne.access.types.FloatType;
 import org.apache.cayenne.access.types.IntegerType;
 import org.apache.cayenne.access.types.LocalDateTimeValueType;
@@ -210,7 +210,8 @@ public class ServerCaseModule implements Module {
                 .add(new TimestampType())
                 .add(new UtilDateType())
                 .add(new CalendarType<>(GregorianCalendar.class))
-                .add(new CalendarType<>(Calendar.class));
+                .add(new CalendarType<>(Calendar.class))
+                .add(new DurationType());
         ServerModule.contributeUserTypes(binder);
         ServerModule.contributeTypeFactories(binder);
         ServerModule.contributeValueObjectTypes(binder)
@@ -219,7 +220,6 @@ public class ServerCaseModule implements Module {
                 .add(LocalDateValueType.class)
                 .add(LocalTimeValueType.class)
                 .add(LocalDateTimeValueType.class)
-                .add(DurationValueType.class)
                 .add(PeriodValueType.class)
                 .add(CharacterValueType.class);
         binder.bind(ValueObjectTypeRegistry.class).to(DefaultValueObjectTypeRegistry.class);
diff --git a/cayenne-server/src/test/resources/java8.map.xml b/cayenne-server/src/test/resources/java8.map.xml
index f96f7ef..692cc77 100644
--- a/cayenne-server/src/test/resources/java8.map.xml
+++ b/cayenne-server/src/test/resources/java8.map.xml
@@ -5,7 +5,14 @@
 	 project-version="10">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.java8"/>
 	<db-entity name="DURATION_TEST">
-		<db-attribute name="DurationField" type="VARCHAR" length="100"/>
+		<db-attribute name="DurationBigInt" type="BIGINT"/>
+		<db-attribute name="DurationDecimal" type="DECIMAL"/>
+		<db-attribute name="DurationInt" type="INTEGER" length="100"/>
+		<db-attribute name="DurationLongNVarchar" type="LONGNVARCHAR" length="100"/>
+		<db-attribute name="DurationLongVarchar" type="LONGVARCHAR" length="100"/>
+		<db-attribute name="DurationNVarchar" type="NVARCHAR" length="100"/>
+		<db-attribute name="DurationNumeric" type="NUMERIC"/>
+		<db-attribute name="DurationVarchar" type="VARCHAR" length="100"/>
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
 	<db-entity name="LOCAL_DATETIME_TEST">
@@ -25,7 +32,14 @@
 		<db-attribute name="PeriodField" type="VARCHAR" length="100"/>
 	</db-entity>
 	<obj-entity name="DurationTest" className="org.apache.cayenne.testdo.java8.DurationTestEntity" dbEntityName="DURATION_TEST">
-		<obj-attribute name="durationField" type="java.time.Duration" db-attribute-path="DurationField"/>
+		<obj-attribute name="durationVarchar" type="java.time.Duration" db-attribute-path="DurationVarchar"/>
+		<obj-attribute name="durationBigInt" type="java.time.Duration" db-attribute-path="DurationBigInt"/>
+		<obj-attribute name="durationNumeric" type="java.time.Duration" db-attribute-path="DurationNumeric"/>
+		<obj-attribute name="durationDecimal" type="java.time.Duration" db-attribute-path="DurationDecimal"/>
+		<obj-attribute name="durationLongVarchar" type="java.time.Duration" db-attribute-path="DurationLongVarchar"/>
+		<obj-attribute name="durationNVarchar" type="java.time.Duration" db-attribute-path="DurationNVarchar"/>
+		<obj-attribute name="durationLongNVarchar" type="java.time.Duration" db-attribute-path="DurationLongNVarchar"/>
+		<obj-attribute name="durationInt" type="java.time.Duration" db-attribute-path="DurationInt"/>
 	</obj-entity>
 	<obj-entity name="LocalDateTest" className="org.apache.cayenne.testdo.java8.LocalDateTestEntity" dbEntityName="LOCAL_DATE_TEST">
 		<obj-attribute name="date" type="java.time.LocalDate" db-attribute-path="DateField"/>
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
index 8bd18b4..a4e2810 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/Application.java
@@ -19,6 +19,14 @@
 
 package org.apache.cayenne.modeler;
 
+import javax.swing.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+import java.util.stream.Collectors;
+
 import org.apache.cayenne.configuration.DataChannelDescriptor;
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.di.Inject;
@@ -35,14 +43,6 @@ import org.apache.cayenne.project.Project;
 import org.apache.cayenne.swing.BindingFactory;
 import org.apache.cayenne.util.IDUtil;
 
-import javax.swing.*;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-import java.util.stream.Collectors;
-
 /**
  * A main modeler application class that provides a number of services to the Modeler
  * components. Configuration properties: