You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/12/19 07:49:38 UTC

[2/2] cayenne git commit: add new jdbc types

add new jdbc types


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/01d0b24e
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/01d0b24e
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/01d0b24e

Branch: refs/heads/master
Commit: 01d0b24e086fa8ec8251d63a29197ab4938355d2
Parents: 2666793
Author: alexkolonitsky <Al...@gmail.com>
Authored: Thu Dec 18 17:15:17 2014 +0300
Committer: alexkolonitsky <Al...@gmail.com>
Committed: Thu Dec 18 17:15:17 2014 +0300

----------------------------------------------------------------------
 .../value/DefaultValueTransformerFactory.java   |  22 +-
 .../validation/DbAttributeValidator.java        |   5 +-
 .../validation/ProcedureParameterValidator.java |   5 +-
 .../org/apache/cayenne/access/DbLoader.java     |  21 +-
 .../mapper/DefaultJdbc2JavaTypeMapper.java      |   5 +
 .../translator/select/SelectTranslator.java     |  38 +-
 .../apache/cayenne/access/types/CharType.java   |  64 +--
 .../org/apache/cayenne/dba/JdbcAdapter.java     |  10 +-
 .../org/apache/cayenne/dba/TypesHandler.java    |   2 +-
 .../org/apache/cayenne/dba/TypesMapping.java    | 393 ++++++++++---------
 .../apache/cayenne/dba/derby/DerbyAdapter.java  |  47 +--
 .../cayenne/dba/firebird/FirebirdAdapter.java   |  33 +-
 .../dba/oracle/Oracle8LOBBatchQueryWrapper.java |   2 +-
 .../cayenne/dba/postgres/PostgresAdapter.java   |  76 ++--
 .../org/apache/cayenne/map/DbAttribute.java     |  25 ++
 .../org/apache/cayenne/map/ObjAttribute.java    |   6 +
 .../org/apache/cayenne/dba/db2/types.xml        |  12 +
 .../org/apache/cayenne/dba/firebird/types.xml   |   6 +
 .../org/apache/cayenne/dba/h2/types.xml         |  15 +
 .../org/apache/cayenne/dba/hsqldb/types.xml     |  12 +
 .../org/apache/cayenne/dba/mysql/types.xml      |  15 +
 .../org/apache/cayenne/dba/oracle/types.xml     |  18 +
 .../org/apache/cayenne/dba/postgres/types.xml   |  15 +
 .../org/apache/cayenne/dba/sqlite/types.xml     |  12 +
 .../org/apache/cayenne/dba/sqlserver/types.xml  |  14 +
 .../org/apache/cayenne/dba/sybase/types.xml     |  15 +
 .../resources/org/apache/cayenne/dba/types.xml  |  18 +
 .../cayenne/access/DataContextBlobIT.java       |   4 +-
 .../org/apache/cayenne/access/DbLoaderIT.java   |  20 +
 .../cayenne/access/ReturnTypesMappingIT.java    |  82 ++++
 .../cayenne/access/types/CharTypeTest.java      |  17 +-
 .../cayenne/testdo/lob/NClobTestEntity.java     |  28 ++
 .../testdo/lob/auto/_NClobTestEntity.java       |  55 +++
 .../return_types/auto/_ReturnTypesMap1.java     |  21 +
 .../return_types/auto/_ReturnTypesMapLobs1.java |   8 +
 cayenne-server/src/test/resources/lob.map.xml   |   7 +
 .../src/test/resources/return-types.map.xml     |   8 +
 .../cayenne/tools/DbImporterTaskTest.java       |  13 +-
 38 files changed, 774 insertions(+), 395 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java
index 6fa56d7..009623d 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/DefaultValueTransformerFactory.java
@@ -44,16 +44,16 @@ import org.apache.cayenne.map.ObjEntity;
  */
 public class DefaultValueTransformerFactory implements ValueTransformerFactory {
 
-    private Key defaultKey;
+    private final Key defaultKey;
 
-    private Map<String, BytesConverter> objectToBytes;
-    private Map<Integer, BytesConverter> dbToBytes;
+    private final Map<String, BytesConverter> objectToBytes;
+    private final Map<Integer, BytesConverter> dbToBytes;
 
-    private Map<String, BytesConverter> bytesToObject;
-    private Map<Integer, BytesConverter> bytesToDb;
+    private final Map<String, BytesConverter> bytesToObject;
+    private final Map<Integer, BytesConverter> bytesToDb;
 
-    private ConcurrentMap<DbAttribute, ValueEncryptor> encryptors;
-    private ConcurrentMap<DbAttribute, ValueDecryptor> decryptors;
+    private final ConcurrentMap<DbAttribute, ValueEncryptor> encryptors;
+    private final ConcurrentMap<DbAttribute, ValueDecryptor> decryptors;
 
     public DefaultValueTransformerFactory(@Inject KeySource keySource) {
         this.defaultKey = keySource.getKey(keySource.getDefaultKeyAlias());
@@ -106,9 +106,13 @@ public class DefaultValueTransformerFactory implements ValueTransformerFactory {
         map.put(Types.LONGVARBINARY, BytesToBytesConverter.INSTANCE);
 
         map.put(Types.CHAR, Base64StringConverter.INSTANCE);
+        map.put(Types.NCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.CLOB, Base64StringConverter.INSTANCE);
+        map.put(Types.NCLOB, Base64StringConverter.INSTANCE);
+        map.put(Types.LONGVARCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.LONGNVARCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.VARCHAR, Base64StringConverter.INSTANCE);
+        map.put(Types.NVARCHAR, Base64StringConverter.INSTANCE);
 
         return map;
     }
@@ -122,9 +126,13 @@ public class DefaultValueTransformerFactory implements ValueTransformerFactory {
         map.put(Types.LONGVARBINARY, BytesToBytesConverter.INSTANCE);
 
         map.put(Types.CHAR, Base64StringConverter.INSTANCE);
+        map.put(Types.NCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.CLOB, Base64StringConverter.INSTANCE);
+        map.put(Types.NCLOB, Base64StringConverter.INSTANCE);
+        map.put(Types.LONGVARCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.LONGNVARCHAR, Base64StringConverter.INSTANCE);
         map.put(Types.VARCHAR, Base64StringConverter.INSTANCE);
+        map.put(Types.NVARCHAR, Base64StringConverter.INSTANCE);
 
         return map;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DbAttributeValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DbAttributeValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DbAttributeValidator.java
index 769dbf7..0936cdc 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DbAttributeValidator.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DbAttributeValidator.java
@@ -53,7 +53,10 @@ class DbAttributeValidator extends ConfigurationNodeValidator {
 
         // VARCHAR and CHAR attributes must have max length
         else if (attribute.getMaxLength() < 0
-                && (attribute.getType() == java.sql.Types.VARCHAR || attribute.getType() == java.sql.Types.CHAR)) {
+                && (attribute.getType() == java.sql.Types.VARCHAR
+                    || attribute.getType() == java.sql.Types.NVARCHAR
+                    || attribute.getType() == java.sql.Types.CHAR
+                    || attribute.getType() == java.sql.Types.NCHAR)) {
 
             addFailure(
                     validationResult,

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ProcedureParameterValidator.java
----------------------------------------------------------------------
diff --git a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ProcedureParameterValidator.java b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ProcedureParameterValidator.java
index e0e5f38..893a2c2 100644
--- a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ProcedureParameterValidator.java
+++ b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ProcedureParameterValidator.java
@@ -45,7 +45,10 @@ class ProcedureParameterValidator extends ConfigurationNodeValidator {
 
         // VARCHAR and CHAR attributes must have max length
         if (parameter.getMaxLength() < 0
-                && (parameter.getType() == Types.VARCHAR || parameter.getType() == Types.CHAR)) {
+                && (parameter.getType() == Types.VARCHAR
+                    || parameter.getType() == Types.NVARCHAR
+                    || parameter.getType() == Types.CHAR
+                    || parameter.getType() == Types.NCHAR)) {
 
             addFailure(
                     validationResult,

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
index 1b1a828..864e4f0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
@@ -49,12 +49,14 @@ import org.apache.commons.logging.LogFactory;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -364,6 +366,8 @@ public class DbLoader {
         ResultSet rs = getMetaData().getColumns(path.catalog, path.schema, WILDCARD, WILDCARD);
 
         try {
+            Set<String> columns = new HashSet<String>();
+
             while (rs.next()) {
                 // for a reason not quiet apparent to me, Oracle sometimes
                 // returns duplicate record sets for the same table, messing up table
@@ -378,7 +382,7 @@ public class DbLoader {
                     continue;
                 }
 
-                DbAttribute attr = loadDbAttribute(rs);
+                DbAttribute attr = loadDbAttribute(columns, rs);
                 attr.setEntity(dbEntity);
                 Filter<DbAttribute> filter = filters.filter(new DbPath(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName())).columnFilter();
                 if (!filter.isInclude(attr)) {
@@ -400,7 +404,14 @@ public class DbLoader {
         }
     }
 
-    private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException {
+    private DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException {
+        if (columns.isEmpty()) {
+            ResultSetMetaData rsMetaData = rs.getMetaData();
+            for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
+                columns.add(rsMetaData.getColumnLabel(i));
+            }
+        }
+
         // gets attribute's (column's) information
         int columnType = rs.getInt("DATA_TYPE");
 
@@ -422,11 +433,7 @@ public class DbLoader {
                 decimalDigits,
                 rs.getBoolean("NULLABLE"));
 
-        if (adapter.supportsGeneratedKeys()) {
-
-            // TODO: this actually throws on some drivers... need to
-            // ensure that 'supportsGeneratedKeys' check is enough
-            // to prevent an exception here.
+        if (columns.contains("IS_AUTOINCREMENT")) {
             String autoIncrement = rs.getString("IS_AUTOINCREMENT");
             if ("YES".equals(autoIncrement)) {
                 attr.setGenerated(true);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
index 6e0723f..9380050 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/mapper/DefaultJdbc2JavaTypeMapper.java
@@ -74,13 +74,17 @@ public class DefaultJdbc2JavaTypeMapper implements Jdbc2JavaTypeMapper {
         add(Types.BOOLEAN, JAVA_BOOLEAN);
         add(Types.BLOB, JAVA_BYTES);
         add(Types.CLOB, JAVA_STRING);
+        add(Types.NCLOB, JAVA_STRING);
+        add(Types.SQLXML, JAVA_STRING);
         add(Types.CHAR, JAVA_STRING);
+        add(Types.NCHAR, JAVA_STRING);
         add(Types.DATE, JAVA_UTILDATE);
         add(Types.DECIMAL, JAVA_BIGDECIMAL);
         add(Types.DOUBLE, JAVA_DOUBLE);
         add(Types.FLOAT, JAVA_FLOAT);
         add(Types.INTEGER, JAVA_INTEGER);
         add(Types.LONGVARCHAR, JAVA_STRING);
+        add(Types.LONGNVARCHAR, JAVA_STRING);
         add(Types.LONGVARBINARY, JAVA_BYTES);
         add(Types.NUMERIC, JAVA_BIGDECIMAL);
         add(Types.REAL, JAVA_FLOAT);
@@ -90,6 +94,7 @@ public class DefaultJdbc2JavaTypeMapper implements Jdbc2JavaTypeMapper {
         add(Types.TIMESTAMP, JAVA_UTILDATE);
         add(Types.VARBINARY, JAVA_BYTES);
         add(Types.VARCHAR, JAVA_STRING);
+        add(Types.NVARCHAR, JAVA_STRING);
 
         javaSqlEnum.put(JAVA_LONG, Types.BIGINT);
         javaSqlEnum.put(JAVA_BYTES, Types.BINARY);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
index b09fee4..4c0aa4d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/SelectTranslator.java
@@ -67,12 +67,12 @@ import java.util.Set;
  */
 public class SelectTranslator extends QueryAssembler {
 
-    protected static final int[] UNSUPPORTED_DISTINCT_TYPES = new int[] { Types.BLOB, Types.CLOB, Types.LONGVARBINARY,
-            Types.LONGVARCHAR };
+    protected static final int[] UNSUPPORTED_DISTINCT_TYPES = { Types.BLOB, Types.CLOB, Types.NCLOB,
+            Types.LONGVARBINARY, Types.LONGVARCHAR, Types.LONGNVARCHAR };
 
     protected static boolean isUnsupportedForDistinct(int type) {
-        for (int i = 0; i < UNSUPPORTED_DISTINCT_TYPES.length; i++) {
-            if (UNSUPPORTED_DISTINCT_TYPES[i] == type) {
+        for (int unsupportedDistinctType : UNSUPPORTED_DISTINCT_TYPES) {
+            if (unsupportedDistinctType == type) {
                 return true;
             }
         }
@@ -119,8 +119,9 @@ public class SelectTranslator extends QueryAssembler {
      */
     @Override
     public String createSqlString() throws Exception {
-        if (cachedSqlString != null)
+        if (cachedSqlString != null) {
             return cachedSqlString;
+        }
 
         DataMap dataMap = queryMetadata.getDataMap();
         JoinStack joins = getJoinStack();
@@ -308,7 +309,7 @@ public class SelectTranslator extends QueryAssembler {
 
     <T> List<ColumnDescriptor> appendDbEntityColumns(List<ColumnDescriptor> columns, SelectQuery<T> query) {
 
-        final Set<ColumnTracker> attributes = new HashSet<ColumnTracker>();
+        Set<ColumnTracker> attributes = new HashSet<ColumnTracker>();
 
         DbEntity table = getRootDbEntity();
         for (DbAttribute dba : table.getAttributes()) {
@@ -377,9 +378,7 @@ public class SelectTranslator extends QueryAssembler {
                 DbRelationship dbRel = rel.getDbRelationships().get(0);
 
                 List<DbJoin> joins = dbRel.getJoins();
-                int len = joins.size();
-                for (int i = 0; i < len; i++) {
-                    DbJoin join = joins.get(i);
+                for (DbJoin join : joins) {
                     DbAttribute src = join.getSource();
                     appendColumn(columns, null, src, attributes, null);
                 }
@@ -394,7 +393,7 @@ public class SelectTranslator extends QueryAssembler {
 
         // add remaining needed attrs from DbEntity
         DbEntity table = getRootDbEntity();
-        for (final DbAttribute dba : table.getPrimaryKeys()) {
+        for (DbAttribute dba : table.getPrimaryKeys()) {
             appendColumn(columns, null, dba, attributes, null);
         }
 
@@ -606,7 +605,7 @@ public class SelectTranslator extends QueryAssembler {
         return true;
     }
 
-    final class ColumnTracker {
+    static final class ColumnTracker {
 
         private DbAttribute attribute;
         private String alias;
@@ -618,16 +617,23 @@ public class SelectTranslator extends QueryAssembler {
 
         @Override
         public boolean equals(Object object) {
-            if (object instanceof ColumnTracker) {
-                ColumnTracker other = (ColumnTracker) object;
-                return new EqualsBuilder().append(alias, other.alias).append(attribute, other.attribute).isEquals();
+            if (!(object instanceof ColumnTracker)) {
+                return false;
             }
-            return false;
+
+            ColumnTracker other = (ColumnTracker) object;
+            return new EqualsBuilder()
+                    .append(alias, other.alias)
+                    .append(attribute, other.attribute)
+                    .isEquals();
         }
 
         @Override
         public int hashCode() {
-            return new HashCodeBuilder(31, 5).append(alias).append(attribute).toHashCode();
+            return new HashCodeBuilder(31, 5)
+                    .append(alias)
+                    .append(attribute)
+                    .toHashCode();
         }
 
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/access/types/CharType.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/types/CharType.java b/cayenne-server/src/main/java/org/apache/cayenne/access/types/CharType.java
index 3fdfc2b..fcf6904 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/types/CharType.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/types/CharType.java
@@ -42,8 +42,8 @@ public class CharType implements ExtendedType {
     protected boolean trimmingChars;
     protected boolean usingClobs;
 
-    public CharType(boolean trimingChars, boolean usingClobs) {
-        this.trimmingChars = trimingChars;
+    public CharType(boolean trimmingChars, boolean usingClobs) {
+        this.trimmingChars = trimmingChars;
         this.usingClobs = usingClobs;
     }
 
@@ -59,51 +59,33 @@ public class CharType implements ExtendedType {
     @Override
     public Object materializeObject(ResultSet rs, int index, int type) throws Exception {
 
-        String val = null;
-
-        // CLOB handling
-        if (type == Types.CLOB) {
-            val = (isUsingClobs()) ? readClob(rs.getClob(index)) : readCharStream(
-                    rs,
-                    index);
-        }
-        else {
-
-            val = rs.getString(index);
-
-            // trim CHAR type
-            if (val != null && type == Types.CHAR && isTrimmingChars()) {
-                val = rtrim(val);
-            }
+        if (type == Types.CLOB || type == Types.NCLOB) {
+            return isUsingClobs() ? readClob(rs.getClob(index)) : readCharStream(rs, index);
         }
 
-        return val;
+        return handleString(rs.getString(index), type);
     }
 
-    /** Return trimmed string. */
     @Override
     public Object materializeObject(CallableStatement cs, int index, int type)
             throws Exception {
 
-        String val = null;
-
-        // CLOB handling
-        if (type == Types.CLOB) {
+        if (type == Types.CLOB || type == Types.NCLOB) {
             if (!isUsingClobs()) {
                 throw new CayenneException(
                         "Character streams are not supported in stored procedure parameters.");
             }
 
-            val = readClob(cs.getClob(index));
+            return readClob(cs.getClob(index));
         }
-        else {
 
-            val = cs.getString(index);
+        return handleString(cs.getString(index), type);
+    }
 
-            // trim CHAR type
-            if (val != null && type == Types.CHAR && isTrimmingChars()) {
-                val = rtrim(val);
-            }
+    private Object handleString(String val, int type) throws SQLException {
+        // trim CHAR type
+        if (val != null && (type == Types.CHAR || type == Types.NCHAR) && isTrimmingChars()) {
+            return rtrim(val);
         }
 
         return val;
@@ -113,10 +95,10 @@ public class CharType implements ExtendedType {
     protected String rtrim(String value) {
         int end = value.length() - 1;
         int count = end;
-        while ((end >= 0) && (value.charAt(end) <= ' ')) {
+        while (end >= 0 && value.charAt(end) <= ' ') {
             end--;
         }
-        return (end == count) ? value : value.substring(0, end + 1);
+        return end == count ? value : value.substring(0, end + 1);
     }
 
     @Override
@@ -131,11 +113,9 @@ public class CharType implements ExtendedType {
         // instead. This should work with most drivers
         if (type == Types.CLOB) {
             st.setString(pos, (String) value);
-        }
-        else if (scale != -1) {
+        } else if (scale != -1) {
             st.setObject(pos, value, type, scale);
-        }
-        else {
+        } else {
             st.setObject(pos, value, type);
         }
     }
@@ -163,18 +143,16 @@ public class CharType implements ExtendedType {
             SQLException {
         Reader in = rs.getCharacterStream(index);
 
-        return (in != null) ? readValueStream(in, -1, BUF_SIZE) : null;
+        return in != null ? readValueStream(in, -1, BUF_SIZE) : null;
     }
 
     protected String readValueStream(Reader in, int streamSize, int bufSize)
             throws IOException {
         char[] buf = new char[bufSize];
-        int read;
-        StringWriter out = (streamSize > 0)
-                ? new StringWriter(streamSize)
-                : new StringWriter();
+        StringWriter out = streamSize > 0 ? new StringWriter(streamSize) : new StringWriter();
 
         try {
+            int read;
             while ((read = in.read(buf, 0, bufSize)) >= 0) {
                 out.write(buf, 0, read);
             }
@@ -188,7 +166,7 @@ public class CharType implements ExtendedType {
     /**
      * Returns <code>true</code> if 'materializeObject' method should trim trailing spaces
      * from the CHAR columns. This addresses an issue with some JDBC drivers (e.g.
-     * Oracle), that return Strings for CHAR columsn padded with spaces.
+     * Oracle), that return Strings for CHAR columns padded with spaces.
      */
     public boolean isTrimmingChars() {
         return trimmingChars;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
index b57dc33..552aeae 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/JdbcAdapter.java
@@ -262,6 +262,9 @@ public class JdbcAdapter implements DbAdapter {
     static boolean supportsLength(int type) {
         return type == Types.BINARY
                 || type == Types.CHAR
+                || type == Types.NCHAR
+                || type == Types.NVARCHAR
+                || type == Types.LONGNVARCHAR
                 || type == Types.DECIMAL
                 || type == Types.DOUBLE
                 || type == Types.FLOAT
@@ -445,11 +448,12 @@ public class JdbcAdapter implements DbAdapter {
         boolean first = true;
 
         for (DbJoin join : rel.getJoins()) {
-            if (!first) {
+            if (first) {
+                first = false;
+            } else {
                 buf.append(", ");
                 refBuf.append(", ");
-            } else
-                first = false;
+            }
 
             buf.append(quotingStrategy.quotedSourceName(join));
             refBuf.append(quotingStrategy.quotedTargetName(join));

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesHandler.java
index 20e207f..1e1f3ea 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesHandler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesHandler.java
@@ -103,7 +103,7 @@ public class TypesHandler {
     }
 
     public String[] externalTypesForJdbcType(int type) {
-        return typesMap.get(Integer.valueOf(type));
+        return typesMap.get(type);
     }
 
     /** 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesMapping.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesMapping.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesMapping.java
index b84b084..df0d5c8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesMapping.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/TypesMapping.java
@@ -24,7 +24,6 @@ import java.math.BigInteger;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
@@ -34,6 +33,8 @@ import java.util.Map;
 
 import org.apache.cayenne.util.Util;
 
+import static java.sql.Types.*;
+
 /**
  * A utility class that handles mappings of JDBC data types to the database types and Java
  * types. Also contains methods that provide information about JDBC types.
@@ -57,13 +58,16 @@ public class TypesMapping {
     public static final String SQL_BOOLEAN = "BOOLEAN";
 
     public static final String SQL_CLOB = "CLOB";
+    public static final String SQL_NCLOB = "NCLOB";
     public static final String SQL_CHAR = "CHAR";
+    public static final String SQL_NCHAR = "NCHAR";
     public static final String SQL_DATE = "DATE";
     public static final String SQL_DECIMAL = "DECIMAL";
     public static final String SQL_DOUBLE = "DOUBLE";
     public static final String SQL_FLOAT = "FLOAT";
     public static final String SQL_INTEGER = "INTEGER";
     public static final String SQL_LONGVARCHAR = "LONGVARCHAR";
+    public static final String SQL_LONGNVARCHAR = "LONGNVARCHAR";
     public static final String SQL_LONGVARBINARY = "LONGVARBINARY";
     public static final String SQL_NUMERIC = "NUMERIC";
     public static final String SQL_REAL = "REAL";
@@ -73,6 +77,8 @@ public class TypesMapping {
     public static final String SQL_TIMESTAMP = "TIMESTAMP";
     public static final String SQL_VARBINARY = "VARBINARY";
     public static final String SQL_VARCHAR = "VARCHAR";
+    public static final String SQL_NVARCHAR = "NVARCHAR";
+    public static final String SQL_SQLXML = "SQLXML";
     public static final String SQL_OTHER = "OTHER";
     public static final String SQL_NULL = "NULL";
 
@@ -96,124 +102,138 @@ public class TypesMapping {
     /**
      * Keys: SQL string type names, Values: SQL int type definitions from java.sql.Types
      */
-    private static final Map<String, Integer> sqlStringType = new HashMap<String, Integer>();
+    private static final Map<String, Integer> SQL_STRING_TYPE = new HashMap<String, Integer>();
 
     /**
      * Keys: SQL int type definitions from java.sql.Types, Values: SQL string type names
      */
-    private static final Map<Integer, String> sqlEnumType = new HashMap<Integer, String>();
+    private static final Map<Integer, String> SQL_ENUM_TYPE = new HashMap<Integer, String>();
 
     /**
      * Keys: SQL int type definitions from java.sql.Types, Values: java class names
      */
-    private static final Map<Integer, String> sqlEnumJava = new HashMap<Integer, String>();
+    private static final Map<Integer, String> SQL_ENUM_JAVA = new HashMap<Integer, String>();
 
     /**
      * Keys: java class names, Values: SQL int type definitions from java.sql.Types
      */
-    private static final Map<String, Integer> javaSqlEnum = new HashMap<String, Integer>();
+    private static final Map<String, Integer> JAVA_SQL_ENUM = new HashMap<String, Integer>();
 
     static {
-        sqlStringType.put(SQL_ARRAY, Integer.valueOf(Types.ARRAY));
-        sqlStringType.put(SQL_BIGINT, Integer.valueOf(Types.BIGINT));
-        sqlStringType.put(SQL_BINARY, Integer.valueOf(Types.BINARY));
-        sqlStringType.put(SQL_BIT, Integer.valueOf(Types.BIT));
-        sqlStringType.put(SQL_BLOB, Integer.valueOf(Types.BLOB));
-        sqlStringType.put(SQL_BOOLEAN, Integer.valueOf(Types.BOOLEAN));
-        sqlStringType.put(SQL_CLOB, Integer.valueOf(Types.CLOB));
-        sqlStringType.put(SQL_CHAR, Integer.valueOf(Types.CHAR));
-        sqlStringType.put(SQL_DATE, Integer.valueOf(Types.DATE));
-        sqlStringType.put(SQL_DECIMAL, Integer.valueOf(Types.DECIMAL));
-        sqlStringType.put(SQL_DOUBLE, Integer.valueOf(Types.DOUBLE));
-        sqlStringType.put(SQL_FLOAT, Integer.valueOf(Types.FLOAT));
-        sqlStringType.put(SQL_INTEGER, Integer.valueOf(Types.INTEGER));
-        sqlStringType.put(SQL_LONGVARCHAR, Integer.valueOf(Types.LONGVARCHAR));
-        sqlStringType.put(SQL_LONGVARBINARY, Integer.valueOf(Types.LONGVARBINARY));
-        sqlStringType.put(SQL_NUMERIC, Integer.valueOf(Types.NUMERIC));
-        sqlStringType.put(SQL_REAL, Integer.valueOf(Types.REAL));
-        sqlStringType.put(SQL_SMALLINT, Integer.valueOf(Types.SMALLINT));
-        sqlStringType.put(SQL_TINYINT, Integer.valueOf(Types.TINYINT));
-        sqlStringType.put(SQL_TIME, Integer.valueOf(Types.TIME));
-        sqlStringType.put(SQL_TIMESTAMP, Integer.valueOf(Types.TIMESTAMP));
-        sqlStringType.put(SQL_VARBINARY, Integer.valueOf(Types.VARBINARY));
-        sqlStringType.put(SQL_VARCHAR, Integer.valueOf(Types.VARCHAR));
-        sqlStringType.put(SQL_OTHER, Integer.valueOf(Types.OTHER));
-        sqlStringType.put(SQL_NULL, Integer.valueOf(Types.NULL));
-
-        sqlEnumType.put(Integer.valueOf(Types.ARRAY), SQL_ARRAY);
-        sqlEnumType.put(Integer.valueOf(Types.BIGINT), SQL_BIGINT);
-        sqlEnumType.put(Integer.valueOf(Types.BINARY), SQL_BINARY);
-        sqlEnumType.put(Integer.valueOf(Types.BIT), SQL_BIT);
-        sqlEnumType.put(Integer.valueOf(Types.BOOLEAN), SQL_BOOLEAN);
-        sqlEnumType.put(Integer.valueOf(Types.BLOB), SQL_BLOB);
-        sqlEnumType.put(Integer.valueOf(Types.CLOB), SQL_CLOB);
-        sqlEnumType.put(Integer.valueOf(Types.CHAR), SQL_CHAR);
-        sqlEnumType.put(Integer.valueOf(Types.DATE), SQL_DATE);
-        sqlEnumType.put(Integer.valueOf(Types.DECIMAL), SQL_DECIMAL);
-        sqlEnumType.put(Integer.valueOf(Types.DOUBLE), SQL_DOUBLE);
-        sqlEnumType.put(Integer.valueOf(Types.FLOAT), SQL_FLOAT);
-        sqlEnumType.put(Integer.valueOf(Types.INTEGER), SQL_INTEGER);
-        sqlEnumType.put(Integer.valueOf(Types.LONGVARCHAR), SQL_LONGVARCHAR);
-        sqlEnumType.put(Integer.valueOf(Types.LONGVARBINARY), SQL_LONGVARBINARY);
-        sqlEnumType.put(Integer.valueOf(Types.NUMERIC), SQL_NUMERIC);
-        sqlEnumType.put(Integer.valueOf(Types.REAL), SQL_REAL);
-        sqlEnumType.put(Integer.valueOf(Types.SMALLINT), SQL_SMALLINT);
-        sqlEnumType.put(Integer.valueOf(Types.TINYINT), SQL_TINYINT);
-        sqlEnumType.put(Integer.valueOf(Types.TIME), SQL_TIME);
-        sqlEnumType.put(Integer.valueOf(Types.TIMESTAMP), SQL_TIMESTAMP);
-        sqlEnumType.put(Integer.valueOf(Types.VARBINARY), SQL_VARBINARY);
-        sqlEnumType.put(Integer.valueOf(Types.VARCHAR), SQL_VARCHAR);
-        sqlEnumType.put(Integer.valueOf(Types.OTHER), SQL_OTHER);
-        sqlEnumType.put(Integer.valueOf(Types.NULL), SQL_NULL);
-
-        sqlEnumJava.put(Integer.valueOf(Types.BIGINT), JAVA_LONG);
-        sqlEnumJava.put(Integer.valueOf(Types.BINARY), JAVA_BYTES);
-        sqlEnumJava.put(Integer.valueOf(Types.BIT), JAVA_BOOLEAN);
-        sqlEnumJava.put(Integer.valueOf(Types.BOOLEAN), JAVA_BOOLEAN);
-        sqlEnumJava.put(Integer.valueOf(Types.BLOB), JAVA_BYTES);
-        sqlEnumJava.put(Integer.valueOf(Types.CLOB), JAVA_STRING);
-        sqlEnumJava.put(Integer.valueOf(Types.CHAR), JAVA_STRING);
-        sqlEnumJava.put(Integer.valueOf(Types.DATE), JAVA_UTILDATE);
-        sqlEnumJava.put(Integer.valueOf(Types.DECIMAL), JAVA_BIGDECIMAL);
-        sqlEnumJava.put(Integer.valueOf(Types.DOUBLE), JAVA_DOUBLE);
-        sqlEnumJava.put(Integer.valueOf(Types.FLOAT), JAVA_FLOAT);
-        sqlEnumJava.put(Integer.valueOf(Types.INTEGER), JAVA_INTEGER);
-        sqlEnumJava.put(Integer.valueOf(Types.LONGVARCHAR), JAVA_STRING);
-        sqlEnumJava.put(Integer.valueOf(Types.LONGVARBINARY), JAVA_BYTES);
-        sqlEnumJava.put(Integer.valueOf(Types.NUMERIC), JAVA_BIGDECIMAL);
-        sqlEnumJava.put(Integer.valueOf(Types.REAL), JAVA_FLOAT);
-        sqlEnumJava.put(Integer.valueOf(Types.SMALLINT), JAVA_SHORT);
-        sqlEnumJava.put(Integer.valueOf(Types.TINYINT), JAVA_SHORT);
-        sqlEnumJava.put(Integer.valueOf(Types.TIME), JAVA_UTILDATE);
-        sqlEnumJava.put(Integer.valueOf(Types.TIMESTAMP), JAVA_UTILDATE);
-        sqlEnumJava.put(Integer.valueOf(Types.VARBINARY), JAVA_BYTES);
-        sqlEnumJava.put(Integer.valueOf(Types.VARCHAR), JAVA_STRING);
-
-        javaSqlEnum.put(JAVA_LONG, Integer.valueOf(Types.BIGINT));
-        javaSqlEnum.put(JAVA_BYTES, Integer.valueOf(Types.BINARY));
-        javaSqlEnum.put(JAVA_BOOLEAN, Integer.valueOf(Types.BIT));
-        javaSqlEnum.put(JAVA_STRING, Integer.valueOf(Types.VARCHAR));
-        javaSqlEnum.put(JAVA_SQLDATE, Integer.valueOf(Types.DATE));
-        javaSqlEnum.put(JAVA_UTILDATE, Integer.valueOf(Types.DATE));
-        javaSqlEnum.put(JAVA_TIMESTAMP, Integer.valueOf(Types.TIMESTAMP));
-        javaSqlEnum.put(JAVA_BIGDECIMAL, Integer.valueOf(Types.DECIMAL));
-        javaSqlEnum.put(JAVA_DOUBLE, Integer.valueOf(Types.DOUBLE));
-        javaSqlEnum.put(JAVA_FLOAT, Integer.valueOf(Types.FLOAT));
-        javaSqlEnum.put(JAVA_INTEGER, Integer.valueOf(Types.INTEGER));
-        javaSqlEnum.put(JAVA_SHORT, Integer.valueOf(Types.SMALLINT));
-        javaSqlEnum.put(JAVA_BYTE, Integer.valueOf(Types.SMALLINT));
-        javaSqlEnum.put(JAVA_TIME, Integer.valueOf(Types.TIME));
-        javaSqlEnum.put(JAVA_TIMESTAMP, Integer.valueOf(Types.TIMESTAMP));
+        SQL_STRING_TYPE.put(SQL_ARRAY, ARRAY);
+        SQL_STRING_TYPE.put(SQL_BIGINT, BIGINT);
+        SQL_STRING_TYPE.put(SQL_BINARY, BINARY);
+        SQL_STRING_TYPE.put(SQL_BIT, BIT);
+        SQL_STRING_TYPE.put(SQL_BLOB, BLOB);
+        SQL_STRING_TYPE.put(SQL_BOOLEAN, BOOLEAN);
+        SQL_STRING_TYPE.put(SQL_CLOB, CLOB);
+        SQL_STRING_TYPE.put(SQL_NCLOB, NCLOB);
+        SQL_STRING_TYPE.put(SQL_CHAR, CHAR);
+        SQL_STRING_TYPE.put(SQL_NCHAR, NCHAR);
+        SQL_STRING_TYPE.put(SQL_DATE, DATE);
+        SQL_STRING_TYPE.put(SQL_DECIMAL, DECIMAL);
+        SQL_STRING_TYPE.put(SQL_DOUBLE, DOUBLE);
+        SQL_STRING_TYPE.put(SQL_FLOAT, FLOAT);
+        SQL_STRING_TYPE.put(SQL_INTEGER, INTEGER);
+        SQL_STRING_TYPE.put(SQL_LONGVARCHAR, LONGVARCHAR);
+        SQL_STRING_TYPE.put(SQL_LONGNVARCHAR, LONGNVARCHAR);
+        SQL_STRING_TYPE.put(SQL_LONGVARBINARY, LONGVARBINARY);
+        SQL_STRING_TYPE.put(SQL_NUMERIC, NUMERIC);
+        SQL_STRING_TYPE.put(SQL_REAL, REAL);
+        SQL_STRING_TYPE.put(SQL_SMALLINT, SMALLINT);
+        SQL_STRING_TYPE.put(SQL_TINYINT, TINYINT);
+        SQL_STRING_TYPE.put(SQL_TIME, TIME);
+        SQL_STRING_TYPE.put(SQL_TIMESTAMP, TIMESTAMP);
+        SQL_STRING_TYPE.put(SQL_VARBINARY, VARBINARY);
+        SQL_STRING_TYPE.put(SQL_VARCHAR, VARCHAR);
+        SQL_STRING_TYPE.put(SQL_NVARCHAR, NVARCHAR);
+        SQL_STRING_TYPE.put(SQL_OTHER, OTHER);
+        SQL_STRING_TYPE.put(SQL_NULL, NULL);
+
+        SQL_ENUM_TYPE.put(ARRAY, SQL_ARRAY);
+        SQL_ENUM_TYPE.put(BIGINT, SQL_BIGINT);
+        SQL_ENUM_TYPE.put(BINARY, SQL_BINARY);
+        SQL_ENUM_TYPE.put(BIT, SQL_BIT);
+        SQL_ENUM_TYPE.put(BOOLEAN, SQL_BOOLEAN);
+        SQL_ENUM_TYPE.put(BLOB, SQL_BLOB);
+        SQL_ENUM_TYPE.put(CLOB, SQL_CLOB);
+        SQL_ENUM_TYPE.put(NCLOB, SQL_NCLOB);
+        SQL_ENUM_TYPE.put(CHAR, SQL_CHAR);
+        SQL_ENUM_TYPE.put(NCHAR, SQL_NCHAR);
+        SQL_ENUM_TYPE.put(DATE, SQL_DATE);
+        SQL_ENUM_TYPE.put(DECIMAL, SQL_DECIMAL);
+        SQL_ENUM_TYPE.put(DOUBLE, SQL_DOUBLE);
+        SQL_ENUM_TYPE.put(FLOAT, SQL_FLOAT);
+        SQL_ENUM_TYPE.put(INTEGER, SQL_INTEGER);
+        SQL_ENUM_TYPE.put(LONGVARCHAR, SQL_LONGVARCHAR);
+        SQL_ENUM_TYPE.put(LONGNVARCHAR, SQL_LONGNVARCHAR);
+        SQL_ENUM_TYPE.put(LONGVARBINARY, SQL_LONGVARBINARY);
+        SQL_ENUM_TYPE.put(NUMERIC, SQL_NUMERIC);
+        SQL_ENUM_TYPE.put(REAL, SQL_REAL);
+        SQL_ENUM_TYPE.put(SMALLINT, SQL_SMALLINT);
+        SQL_ENUM_TYPE.put(TINYINT, SQL_TINYINT);
+        SQL_ENUM_TYPE.put(TIME, SQL_TIME);
+        SQL_ENUM_TYPE.put(TIMESTAMP, SQL_TIMESTAMP);
+        SQL_ENUM_TYPE.put(VARBINARY, SQL_VARBINARY);
+        SQL_ENUM_TYPE.put(VARCHAR, SQL_VARCHAR);
+        SQL_ENUM_TYPE.put(NVARCHAR, SQL_NVARCHAR);
+        SQL_ENUM_TYPE.put(SQLXML, SQL_SQLXML);
+        SQL_ENUM_TYPE.put(OTHER, SQL_OTHER);
+        SQL_ENUM_TYPE.put(NULL, SQL_NULL);
+
+        SQL_ENUM_JAVA.put(BIGINT, JAVA_LONG);
+        SQL_ENUM_JAVA.put(BINARY, JAVA_BYTES);
+        SQL_ENUM_JAVA.put(BIT, JAVA_BOOLEAN);
+        SQL_ENUM_JAVA.put(BOOLEAN, JAVA_BOOLEAN);
+        SQL_ENUM_JAVA.put(BLOB, JAVA_BYTES);
+        SQL_ENUM_JAVA.put(CLOB, JAVA_STRING);
+        SQL_ENUM_JAVA.put(NCLOB, JAVA_STRING);
+        SQL_ENUM_JAVA.put(CHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(NCHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(DATE, JAVA_UTILDATE);
+        SQL_ENUM_JAVA.put(DECIMAL, JAVA_BIGDECIMAL);
+        SQL_ENUM_JAVA.put(DOUBLE, JAVA_DOUBLE);
+        SQL_ENUM_JAVA.put(FLOAT, JAVA_FLOAT);
+        SQL_ENUM_JAVA.put(INTEGER, JAVA_INTEGER);
+        SQL_ENUM_JAVA.put(LONGVARCHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(LONGNVARCHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(LONGVARBINARY, JAVA_BYTES);
+        SQL_ENUM_JAVA.put(NUMERIC, JAVA_BIGDECIMAL);
+        SQL_ENUM_JAVA.put(REAL, JAVA_FLOAT);
+        SQL_ENUM_JAVA.put(SMALLINT, JAVA_SHORT);
+        SQL_ENUM_JAVA.put(TINYINT, JAVA_SHORT);
+        SQL_ENUM_JAVA.put(TIME, JAVA_UTILDATE);
+        SQL_ENUM_JAVA.put(TIMESTAMP, JAVA_UTILDATE);
+        SQL_ENUM_JAVA.put(VARBINARY, JAVA_BYTES);
+        SQL_ENUM_JAVA.put(VARCHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(NVARCHAR, JAVA_STRING);
+        SQL_ENUM_JAVA.put(SQLXML, JAVA_STRING);
+
+        JAVA_SQL_ENUM.put(JAVA_LONG, BIGINT);
+        JAVA_SQL_ENUM.put(JAVA_BYTES, BINARY);
+        JAVA_SQL_ENUM.put(JAVA_BOOLEAN, BIT);
+        JAVA_SQL_ENUM.put(JAVA_STRING, VARCHAR);
+        JAVA_SQL_ENUM.put(JAVA_SQLDATE, DATE);
+        JAVA_SQL_ENUM.put(JAVA_UTILDATE, DATE);
+        JAVA_SQL_ENUM.put(JAVA_TIMESTAMP, TIMESTAMP);
+        JAVA_SQL_ENUM.put(JAVA_BIGDECIMAL, DECIMAL);
+        JAVA_SQL_ENUM.put(JAVA_DOUBLE, DOUBLE);
+        JAVA_SQL_ENUM.put(JAVA_FLOAT, FLOAT);
+        JAVA_SQL_ENUM.put(JAVA_INTEGER, INTEGER);
+        JAVA_SQL_ENUM.put(JAVA_SHORT, SMALLINT);
+        JAVA_SQL_ENUM.put(JAVA_BYTE, SMALLINT);
+        JAVA_SQL_ENUM.put(JAVA_TIME, TIME);
+        JAVA_SQL_ENUM.put(JAVA_TIMESTAMP, TIMESTAMP);
 
         // add primitives
-        javaSqlEnum.put("byte", Integer.valueOf(Types.TINYINT));
-        javaSqlEnum.put("int", Integer.valueOf(Types.INTEGER));
-        javaSqlEnum.put("short", Integer.valueOf(Types.SMALLINT));
-        javaSqlEnum.put("char", Integer.valueOf(Types.CHAR));
-        javaSqlEnum.put("double", Integer.valueOf(Types.DOUBLE));
-        javaSqlEnum.put("long", Integer.valueOf(Types.BIGINT));
-        javaSqlEnum.put("float", Integer.valueOf(Types.FLOAT));
-        javaSqlEnum.put("boolean", Integer.valueOf(Types.BIT));
+        JAVA_SQL_ENUM.put("byte", TINYINT);
+        JAVA_SQL_ENUM.put("int", INTEGER);
+        JAVA_SQL_ENUM.put("short", SMALLINT);
+        JAVA_SQL_ENUM.put("char", CHAR);
+        JAVA_SQL_ENUM.put("double", DOUBLE);
+        JAVA_SQL_ENUM.put("long", BIGINT);
+        JAVA_SQL_ENUM.put("float", FLOAT);
+        JAVA_SQL_ENUM.put("boolean", BIT);
     }
 
     /**
@@ -230,34 +250,34 @@ public class TypesMapping {
      * Returns true if supplied type is a numeric type.
      */
     public static boolean isNumeric(int type) {
-        return type == Types.BIGINT
-                || type == Types.BIT
-                || type == Types.DECIMAL
-                || type == Types.DOUBLE
-                || type == Types.FLOAT
-                || type == Types.INTEGER
-                || type == Types.NUMERIC
-                || type == Types.REAL
-                || type == Types.SMALLINT
-                || type == Types.TINYINT;
+        return type == BIGINT
+                || type == BIT
+                || type == DECIMAL
+                || type == DOUBLE
+                || type == FLOAT
+                || type == INTEGER
+                || type == NUMERIC
+                || type == REAL
+                || type == SMALLINT
+                || type == TINYINT;
     }
 
     /**
      * Returns true if supplied type is a decimal type.
      */
     public static boolean isDecimal(int type) {
-        return type == Types.DECIMAL
-                || type == Types.DOUBLE
-                || type == Types.FLOAT
-                || type == Types.REAL
-                || type == Types.NUMERIC;
+        return type == DECIMAL
+                || type == DOUBLE
+                || type == FLOAT
+                || type == REAL
+                || type == NUMERIC;
     }
 
     /**
      * Returns an array of string names of the default JDBC data types.
      */
     public static String[] getDatabaseTypes() {
-        Collection<String> types = sqlStringType.keySet();
+        Collection<String> types = SQL_STRING_TYPE.keySet();
         return types.toArray(new String[types.size()]);
     }
 
@@ -268,74 +288,80 @@ public class TypesMapping {
     protected static String pickDataType(int jdbcType, TypeInfo[] alts) {
         int len = alts.length;
 
-        if (len == 0)
+        if (len == 0) {
             return null;
+        }
 
-        if (len == 1)
+        if (len == 1) {
             return alts[0].name;
+        }
 
         // now the fun starts.. try to guess the right type
 
         String jdbcName = getSqlNameByType(jdbcType).toUpperCase();
 
         // 1. exact match
-        for (int i = 0; i < len; i++) {
-            if (jdbcName.equalsIgnoreCase(alts[i].name))
-                return alts[i].name;
+        for (TypeInfo alt : alts) {
+            if (jdbcName.equalsIgnoreCase(alt.name)) {
+                return alt.name;
+            }
         }
 
         // 2. filter those with biggest precision
         long maxPrec = 0;
-        for (int i = 0; i < len; i++) {
-            if (maxPrec < alts[i].precision) {
-                maxPrec = alts[i].precision;
+        for (TypeInfo alt : alts) {
+            if (maxPrec < alt.precision) {
+                maxPrec = alt.precision;
             }
         }
 
         List<TypeInfo> list = new ArrayList<TypeInfo>();
-        for (int i = 0; i < len; i++) {
-            if (maxPrec == alts[i].precision) {
-                list.add(alts[i]);
+        for (TypeInfo alt : alts) {
+            if (maxPrec == alt.precision) {
+                list.add(alt);
             }
         }
 
         // work with smaller list now.....
         int slen = list.size();
-        if (slen == 1)
-            return (list.get(0)).name;
+        if (slen == 1) {
+            return list.get(0).name;
+        }
 
         // start/end match
-        for (int i = 0; i < slen; i++) {
-            String uppercase = (list.get(i)).name.toUpperCase();
-            if (uppercase.startsWith(jdbcName) || uppercase.endsWith(jdbcName))
-                return (list.get(i)).name;
+        for (TypeInfo aList : list) {
+            String uppercase = aList.name.toUpperCase();
+            if (uppercase.startsWith(jdbcName) || uppercase.endsWith(jdbcName)) {
+                return aList.name;
+            }
         }
 
         // in the middle match
-        for (int i = 0; i < slen; i++) {
-            String uppercase = (list.get(i)).name.toUpperCase();
+        for (TypeInfo aList : list) {
+            String uppercase = aList.name.toUpperCase();
 
-            if (uppercase.contains(jdbcName))
-                return (list.get(i)).name;
+            if (uppercase.contains(jdbcName)) {
+                return aList.name;
+            }
         }
 
         // out of ideas... return the first one
-        return (list.get(0)).name;
+        return list.get(0).name;
     }
 
     /**
      * Returns a JDBC int type for SQL typem name.
      */
     public static int getSqlTypeByName(String typeName) {
-        Integer tmp = sqlStringType.get(typeName);
-        return (null == tmp) ? NOT_DEFINED : tmp.intValue();
+        Integer tmp = SQL_STRING_TYPE.get(typeName);
+        return tmp == null ? NOT_DEFINED : tmp;
     }
 
     /**
      * Returns a String representation of the SQL type from its JDBC code.
      */
     public static String getSqlNameByType(int type) {
-        return sqlEnumType.get(Integer.valueOf(type));
+        return SQL_ENUM_TYPE.get(type);
     }
 
     /**
@@ -349,9 +375,9 @@ public class TypesMapping {
             return NOT_DEFINED;
         }
 
-        Integer type = javaSqlEnum.get(className);
+        Integer type = JAVA_SQL_ENUM.get(className);
         if (type != null) {
-            return type.intValue();
+            return type;
         }
 
         // try to load a Java class - some nonstandard mappings may work
@@ -390,7 +416,7 @@ public class TypesMapping {
                 name = aClass.getName();
             }
 
-            Object type = javaSqlEnum.get(name);
+            Object type = JAVA_SQL_ENUM.get(name);
             if (type != null) {
                 return ((Number) type).intValue();
             }
@@ -404,24 +430,26 @@ public class TypesMapping {
             Class<?> elementType = javaClass.getComponentType();
             if (Character.class.isAssignableFrom(elementType)
                     || Character.TYPE.isAssignableFrom(elementType)) {
-                return Types.VARCHAR;
+                return VARCHAR;
             }
             else if (Byte.class.isAssignableFrom(elementType)
                     || Byte.TYPE.isAssignableFrom(elementType)) {
-                return Types.VARBINARY;
+                return VARBINARY;
             }
         }
 
         if (Calendar.class.isAssignableFrom(javaClass)) {
-            return Types.TIMESTAMP;
+            return TIMESTAMP;
         }
-        else if (BigInteger.class.isAssignableFrom(javaClass)) {
-            return Types.BIGINT;
+
+        if (BigInteger.class.isAssignableFrom(javaClass)) {
+            return BIGINT;
         }
+
         // serializable check should be the last one when all other mapping attempts
         // failed
-        else if (Serializable.class.isAssignableFrom(javaClass)) {
-            return Types.VARBINARY;
+        if (Serializable.class.isAssignableFrom(javaClass)) {
+            return VARBINARY;
         }
 
         return NOT_DEFINED;
@@ -436,7 +464,7 @@ public class TypesMapping {
      * @return Fully qualified Java type name or null if not found.
      */
     public static String getJavaBySqlType(int type) {
-        return sqlEnumJava.get(Integer.valueOf(type));
+        return SQL_ENUM_JAVA.get(type);
     }
 
  
@@ -453,7 +481,7 @@ public class TypesMapping {
                 info.jdbcType = rs.getInt("DATA_TYPE");
                 info.precision = rs.getLong("PRECISION");
 
-                Integer key = Integer.valueOf(info.jdbcType);
+                Integer key = info.jdbcType;
                 List<TypeInfo> infos = databaseTypes.get(key);
 
                 if (infos == null) {
@@ -471,40 +499,28 @@ public class TypesMapping {
         // do some tricks to substitute for missing datatypes
 
         // 1. swap TIMESTAMP - DATE
-        Integer ts = Integer.valueOf(Types.TIMESTAMP);
-        Integer dt = Integer.valueOf(Types.DATE);
-        List<TypeInfo> tsInfo = databaseTypes.get(ts);
-        List<TypeInfo> dtInfo = databaseTypes.get(dt);
-
-        if (tsInfo != null && dtInfo == null)
-            databaseTypes.put(dt, tsInfo);
-
-        if (dtInfo != null && tsInfo == null)
-            databaseTypes.put(ts, dtInfo);
+        swapTypes(TIMESTAMP, DATE);
 
         // 2. Swap CLOB - LONGVARCHAR
-        Integer clob = Integer.valueOf(Types.CLOB);
-        Integer lvc = Integer.valueOf(Types.LONGVARCHAR);
-        List<TypeInfo> clobInfo = databaseTypes.get(clob);
-        List<TypeInfo> lvcInfo = databaseTypes.get(lvc);
-
-        if (clobInfo != null && lvcInfo == null)
-            databaseTypes.put(lvc, clobInfo);
+        swapTypes(CLOB, LONGVARCHAR);
 
-        if (lvcInfo != null && clobInfo == null)
-            databaseTypes.put(clob, lvcInfo);
+        // 3. Swap BLOB - LONGVARBINARY
+        swapTypes(BLOB, LONGVARBINARY);
 
-        // 2. Swap BLOB - LONGVARBINARY
-        Integer blob = Integer.valueOf(Types.BLOB);
-        Integer lvb = Integer.valueOf(Types.LONGVARBINARY);
-        List<TypeInfo> blobInfo = databaseTypes.get(blob);
-        List<TypeInfo> lvbInfo = databaseTypes.get(lvb);
+        // 4. Swap NCLOB - LONGNVARCHAR
+        swapTypes(NCLOB, LONGNVARCHAR);
+    }
 
-        if (blobInfo != null && lvbInfo == null)
-            databaseTypes.put(lvb, blobInfo);
+    private void swapTypes(int type1, int type2) {
+        List<TypeInfo> type1Info = databaseTypes.get(type1);
+        List<TypeInfo> type2Info = databaseTypes.get(type2);
 
-        if (lvbInfo != null && blobInfo == null)
-            databaseTypes.put(blob, lvbInfo);
+        if (type1Info != null && type2Info == null) {
+            databaseTypes.put(type2, type1Info);
+        }
+        if (type2Info != null && type1Info == null) {
+            databaseTypes.put(type1, type2Info);
+        }
     }
 
     /** Stores (incomplete) information about database data type */
@@ -516,13 +532,8 @@ public class TypesMapping {
 
         @Override
         public String toString() {
-            StringBuilder buf = new StringBuilder();
-            buf.append("[   TypeInfo: ").append(name);
-            buf.append("\n    JDBC Type: ").append(
-                    TypesMapping.getSqlNameByType(jdbcType));
-            buf.append("\n    Precision: ").append(precision);
-            buf.append("\n]");
-            return buf.toString();
+            return "[   TypeInfo: " + name + "\n    JDBC Type: " + TypesMapping.getSqlNameByType(jdbcType)
+                    + "\n    Precision: " + precision + "\n]";
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
index f686f6d..f24a872 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/derby/DerbyAdapter.java
@@ -119,52 +119,25 @@ public class DerbyAdapter extends JdbcAdapter {
             String entityName = column.getEntity() != null ? ((DbEntity) column
                     .getEntity()).getFullyQualifiedName() : "<null>";
             throw new CayenneRuntimeException("Undefined type for attribute '"
-                    + entityName
-                    + "."
-                    + column.getName()
-                    + "': "
-                    + column.getType());
+                    + entityName + "." + column.getName() + "': " + column.getType());
         }
 
-        String type = types[0];
-
-        String length = "";
-        if (typeSupportsLength(column.getType())) {
-            int len = column.getMaxLength();
-            int scale = TypesMapping.isDecimal(column.getType()) ? column.getScale() : -1;
 
-            // sanity check
-            if (scale > len) {
-                scale = -1;
-            }
 
-            if (len > 0) {
-                length = " (" + len;
-
-                if (scale >= 0) {
-                    length += ", " + scale;
-                }
+        sqlBuffer.append(quotingStrategy.quotedName(column));
+        sqlBuffer.append(' ');
 
-                length += ")";
-            }
-        }
+        String type = types[0];
+        String length = sizeAndPrecision(this, column);
 
         // assemble...
         // note that max length for types like XYZ FOR BIT DATA must be entered in the
         // middle of type name, e.g. VARCHAR (100) FOR BIT DATA.
-
-        sqlBuffer.append(quotingStrategy.quotedName(column));
-
-        sqlBuffer.append(' ');
-        if (length.length() > 0 && type.endsWith(FOR_BIT_DATA_SUFFIX)) {
-            sqlBuffer.append(type.substring(
-                    0,
-                    type.length() - FOR_BIT_DATA_SUFFIX.length()));
-            sqlBuffer.append(length);
-            sqlBuffer.append(FOR_BIT_DATA_SUFFIX);
-        }
-        else {
-            sqlBuffer.append(type).append(length);
+        int suffixIndex = type.indexOf(FOR_BIT_DATA_SUFFIX);
+        if (!length.isEmpty() && suffixIndex > 0) {
+            sqlBuffer.append(type.substring(0, suffixIndex)).append(length).append(FOR_BIT_DATA_SUFFIX);
+        } else {
+            sqlBuffer.append(type).append(" ").append(length);
         }
 
         if (column.isMandatory()) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
index 544f460..c387052 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/firebird/FirebirdAdapter.java
@@ -36,7 +36,6 @@ import org.apache.cayenne.dba.JdbcAdapter;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.resource.ResourceLocator;
 
 /**
@@ -54,6 +53,8 @@ import org.apache.cayenne.resource.ResourceLocator;
  */
 public class FirebirdAdapter extends JdbcAdapter {
 
+    private static final String NCHAR_SUFFIX = " CHARACTER SET UNICODE_FSS";
+
     public FirebirdAdapter(@Inject RuntimeProperties runtimeProperties,
             @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
             @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
@@ -91,31 +92,17 @@ public class FirebirdAdapter extends JdbcAdapter {
                     + "': " + column.getType());
         }
 
-        String type = types[0];
         sqlBuffer.append(quotingStrategy.quotedName(column));
-        sqlBuffer.append(' ').append(type);
-
-        // append size and precision (if applicable)s
-        if (typeSupportsLength(column.getType())) {
-            int len = column.getMaxLength();
-
-            int scale = TypesMapping.isDecimal(column.getType()) && column.getType() != Types.FLOAT ? column
-                    .getScale() : -1;
+        sqlBuffer.append(' ');
 
-            // sanity check
-            if (scale > len) {
-                scale = -1;
-            }
-
-            if (len > 0) {
-                sqlBuffer.append('(').append(len);
-
-                if (scale >= 0) {
-                    sqlBuffer.append(", ").append(scale);
-                }
+        String type = types[0];
+        String length = sizeAndPrecision(this, column);
 
-                sqlBuffer.append(')');
-            }
+        int suffixIndex = type.indexOf(NCHAR_SUFFIX);
+        if (!length.isEmpty() && suffixIndex > 0) {
+            sqlBuffer.append(type.substring(0, suffixIndex)).append(length).append(NCHAR_SUFFIX);
+        } else {
+            sqlBuffer.append(type).append(" ").append(length);
         }
 
         sqlBuffer.append(column.isMandatory() ? " NOT NULL" : "");

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
index 29c755f..5632e73 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/Oracle8LOBBatchQueryWrapper.java
@@ -69,7 +69,7 @@ class Oracle8LOBBatchQueryWrapper {
             DbAttribute attribute = this.dbAttributes.get(i);
             int type = attribute.getType();
             qualifierAttributes[i] = attribute.isPrimaryKey();
-            allLOBAttributes[i] = (type == Types.BLOB || type == Types.CLOB);
+            allLOBAttributes[i] = type == Types.BLOB || type == Types.CLOB;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index 1b5af78..6ffe746 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -61,6 +61,8 @@ import org.apache.cayenne.resource.ResourceLocator;
  */
 public class PostgresAdapter extends JdbcAdapter {
 
+    public static final String BYTEA = "bytea";
+
     public PostgresAdapter(@Inject RuntimeProperties runtimeProperties,
             @Inject(Constants.SERVER_DEFAULT_TYPES_LIST) List<ExtendedType> defaultExtendedTypes,
             @Inject(Constants.SERVER_USER_TYPES_LIST) List<ExtendedType> userExtendedTypes,
@@ -99,7 +101,7 @@ public class PostgresAdapter extends JdbcAdapter {
         // "bytea" maps to pretty much any binary type, so
         // it is up to us to select the most sensible default.
         // And the winner is LONGVARBINARY
-        if ("bytea".equalsIgnoreCase(typeName)) {
+        if (BYTEA.equalsIgnoreCase(typeName)) {
             type = Types.LONGVARBINARY;
         }
         // oid is returned as INTEGER, need to make it BLOB
@@ -126,11 +128,7 @@ public class PostgresAdapter extends JdbcAdapter {
 
         QuotingStrategy context = getQuotingStrategy();
         StringBuilder buf = new StringBuilder();
-        buf.append("CREATE TABLE ");
-
-        buf.append(context.quotedFullyQualifiedName(ent));
-
-        buf.append(" (");
+        buf.append("CREATE TABLE ").append(context.quotedFullyQualifiedName(ent)).append(" (");
 
         // columns
         Iterator<DbAttribute> it = ent.getAttributes().iterator();
@@ -142,51 +140,7 @@ public class PostgresAdapter extends JdbcAdapter {
                 buf.append(", ");
             }
 
-            DbAttribute at = it.next();
-
-            // attribute may not be fully valid, do a simple check
-            if (at.getType() == TypesMapping.NOT_DEFINED) {
-                throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
-                        + at.getName() + "'.");
-            }
-
-            String[] types = externalTypesForJdbcType(at.getType());
-            if (types == null || types.length == 0) {
-                throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
-                        + at.getName() + "': " + at.getType());
-            }
-
-            String type = types[0];
-            buf.append(context.quotedName(at)).append(' ').append(type);
-
-            // append size and precision (if applicable)
-            if (typeSupportsLength(at.getType())) {
-
-                int len = at.getMaxLength();
-                // Postgres does not support notation float(a, b)
-                int scale = (TypesMapping.isDecimal(at.getType()) && at.getType() != Types.FLOAT) ? at.getScale() : -1;
-
-                // sanity check
-                if (scale > len) {
-                    scale = -1;
-                }
-
-                if (len > 0) {
-                    buf.append('(').append(len);
-
-                    if (scale >= 0) {
-                        buf.append(", ").append(scale);
-                    }
-
-                    buf.append(')');
-                }
-            }
-
-            if (at.isMandatory()) {
-                buf.append(" NOT NULL");
-            } else {
-                buf.append(" NULL");
-            }
+            createAttribute(ent, context, buf, it.next());
         }
 
         // primary key clause
@@ -216,13 +170,31 @@ public class PostgresAdapter extends JdbcAdapter {
         return buf.toString();
     }
 
+    private void createAttribute(DbEntity ent, QuotingStrategy context, StringBuilder buf, DbAttribute at) {
+        // attribute may not be fully valid, do a simple check
+        if (at.getType() == TypesMapping.NOT_DEFINED) {
+            throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+                    + at.getName() + "'.");
+        }
+
+        String[] types = externalTypesForJdbcType(at.getType());
+        if (types == null || types.length == 0) {
+            throw new CayenneRuntimeException("Undefined type for attribute '" + ent.getFullyQualifiedName() + "."
+                    + at.getName() + "': " + at.getType());
+        }
+
+        buf.append(context.quotedName(at))
+           .append(' ').append(types[0]).append(sizeAndPrecision(this, at))
+           .append(at.isMandatory() ? " NOT" : "").append(" NULL");
+    }
+
     @Override
     public boolean typeSupportsLength(int type) {
         // "bytea" type does not support length
         String[] externalTypes = externalTypesForJdbcType(type);
         if (externalTypes != null && externalTypes.length > 0) {
             for (String externalType : externalTypes) {
-                if ("bytea".equalsIgnoreCase(externalType)) {
+                if (BYTEA.equalsIgnoreCase(externalType)) {
                     return false;
                 }
             }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
index 014d39f..796d69c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbAttribute.java
@@ -290,4 +290,29 @@ public class DbAttribute extends Attribute implements ConfigurationNode {
     public void setScale(int scale) {
         this.scale = scale;
     }
+
+    @Override
+    public String toString() {
+        String res = "DbAttr: ";
+        String type = TypesMapping.getSqlNameByType(getType());
+
+        res += type != null ? type : "type(" + getType() + ")";
+        res += " " + name;
+
+        if (scale > -1 || attributePrecision > -1) {
+            res += "[" + scale + ", " + attributePrecision + "]";
+        }
+
+        if (maxLength > -1) {
+            res += "[" + maxLength + "]";
+        }
+
+        if (primaryKey) {
+            res += " Primary Key ";
+        } else if (mandatory) {
+            res += " Mandatory ";
+        }
+
+        return res;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
index 4c8696c..fa54af4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/ObjAttribute.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
@@ -370,4 +371,9 @@ public class ObjAttribute extends Attribute implements ConfigurationNode {
             setDbAttributePath(newDbAttributePath.toString());
         }
     }
+
+    @Override
+    public String toString() {
+        return "ObjAttr: " + type + " " + name + "; DbPath[" + dbAttributePath + "]";
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/db2/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/db2/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/db2/types.xml
index 40ebd6b..348d712 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/db2/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/db2/types.xml
@@ -45,9 +45,15 @@ IBM DB2 types mapping
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="NCHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK">
        <db-type name="DATALINK"/>
    </jdbc-type>
@@ -75,6 +81,9 @@ IBM DB2 types mapping
    <jdbc-type name="LONGVARCHAR">
        <db-type name="LONG VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="LONG NVARCHAR"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="DECIMAL"/>
    </jdbc-type>
@@ -108,4 +117,7 @@ IBM DB2 types mapping
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="NVARCHAR"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/firebird/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/firebird/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/firebird/types.xml
index 2617cc5..08b94c4 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/firebird/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/firebird/types.xml
@@ -48,6 +48,9 @@ http://db.apache.org/ddlutils/databases/firebird.html
    <jdbc-type name="CHAR">
        <db-type name="VARCHAR"/> <!-- LIKE operator doesn't work as expected for CHAR type -->
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="CHAR CHARACTER SET UNICODE_FSS"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="BLOB SUB_TYPE TEXT"/>
    </jdbc-type>
@@ -111,4 +114,7 @@ http://db.apache.org/ddlutils/databases/firebird.html
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="VARCHAR">
+       <db-type name="VARCHAR(x) CHARACTER SET UNICODE_FSS"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/h2/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/h2/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/h2/types.xml
index 9c6b0bd..f02630b 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/h2/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/h2/types.xml
@@ -45,9 +45,15 @@ H2 types mapping
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="NCHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK">
        <db-type name="DATALINK"/>
    </jdbc-type>
@@ -75,6 +81,9 @@ H2 types mapping
    <jdbc-type name="LONGVARCHAR">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="NUMERIC"/>
    </jdbc-type>
@@ -108,4 +117,10 @@ H2 types mapping
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="NVARCHAR"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
 </types>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/hsqldb/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/hsqldb/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/hsqldb/types.xml
index 595ff94..b56ea7a 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/hsqldb/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/hsqldb/types.xml
@@ -45,9 +45,15 @@ HSQLDB types mapping
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="CHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="LONGVARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="LONGVARCHAR"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK">
        <db-type name="DATALINK"/>
    </jdbc-type>
@@ -75,6 +81,9 @@ HSQLDB types mapping
    <jdbc-type name="LONGVARCHAR">
        <db-type name="LONGVARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="LONGVARCHAR"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="NUMERIC"/>
    </jdbc-type>
@@ -108,4 +117,7 @@ HSQLDB types mapping
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="VARCHAR"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/mysql/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/mysql/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/mysql/types.xml
index 8416a04..d75642a 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/mysql/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/mysql/types.xml
@@ -46,9 +46,15 @@ MySQL types mapping
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="CHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="LONGTEXT"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="LONGTEXT"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK"/>
    <jdbc-type name="DATE">
        <db-type name="DATE"/>
@@ -73,6 +79,9 @@ MySQL types mapping
    <jdbc-type name="LONGVARCHAR">
        <db-type name="LONGTEXT"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="LONGTEXT"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="DECIMAL"/>
        <db-type name="NUMERIC"/>
@@ -103,4 +112,10 @@ MySQL types mapping
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="VARCHAR"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="LONGTEXT"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
index a17aa86..1da9b37 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
@@ -25,6 +25,9 @@ Oracle types mapping
 
 <types>
    <jdbc-type name="ARRAY"/>
+   <jdbc-type name="ROWID">
+       <db-type name="ROWID"/>
+   </jdbc-type>
    <jdbc-type name="BIGINT">
        <db-type name="NUMBER"/>
    </jdbc-type>
@@ -43,9 +46,15 @@ Oracle types mapping
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="NCHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK"/>
    <jdbc-type name="DATE">
        <db-type name="DATE"/>
@@ -69,6 +78,9 @@ Oracle types mapping
    <jdbc-type name="LONGVARCHAR">
        <db-type name="LONG VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="LONG NVARCHAR2"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="NUMBER"/>
    </jdbc-type>
@@ -96,4 +108,10 @@ Oracle types mapping
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="NVARCHAR2"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="XMLType"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
index 5714b38..8799f6d 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
@@ -44,9 +44,15 @@ Broken PostgreSQL types mapping.
    <jdbc-type name="CHAR">
        <db-type name="character"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="character"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="text"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="text"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK"/>
    <jdbc-type name="DATE">
        <db-type name="date"/>
@@ -70,6 +76,9 @@ Broken PostgreSQL types mapping.
    <jdbc-type name="LONGVARCHAR">
        <db-type name="text"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="text"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="numeric"/>
    </jdbc-type>
@@ -97,4 +106,10 @@ Broken PostgreSQL types mapping.
    <jdbc-type name="VARCHAR">
        <db-type name="varchar"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="varchar"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="xml"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlite/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlite/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlite/types.xml
index 141623c..6eb7dad 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlite/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlite/types.xml
@@ -48,9 +48,15 @@ http://sqlite.org/datatype3.html
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="NCHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="TEXT"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK">
        <db-type name="DATALINK"/>
    </jdbc-type>
@@ -111,4 +117,10 @@ http://sqlite.org/datatype3.html
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="NVARCHAR"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="TEXT"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlserver/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlserver/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlserver/types.xml
index a4e8f21..aca1b21 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlserver/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sqlserver/types.xml
@@ -26,6 +26,9 @@
    <jdbc-type name="BIGINT">
        <db-type name="bigint"/>
    </jdbc-type>
+   <jdbc-type name="ROWID">
+       <db-type name="ROWID"/>
+   </jdbc-type>
    <jdbc-type name="BINARY">
        <db-type name="binary"/>
    </jdbc-type>
@@ -40,10 +43,14 @@
    </jdbc-type>
    <jdbc-type name="CHAR">
        <db-type name="char"/>
+    </jdbc-type>
+    <jdbc-type name="NCHAR">
        <db-type name="nchar"/>
    </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="text"/>
+    </jdbc-type>
+    <jdbc-type name="NCLOB">
        <db-type name="ntext"/>
    </jdbc-type>
    <jdbc-type name="DATALINK"/>
@@ -68,6 +75,8 @@
    </jdbc-type>
    <jdbc-type name="LONGVARCHAR">
        <db-type name="text"/>
+   </jdbc-type>
+    <jdbc-type name="LONGNVARCHAR">
        <db-type name="ntext"/>
    </jdbc-type>
    <jdbc-type name="NUMERIC">
@@ -96,6 +105,11 @@
    </jdbc-type>
    <jdbc-type name="VARCHAR">
        <db-type name="varchar"/>
+   </jdbc-type>
+    <jdbc-type name="NVARCHAR">
        <db-type name="nvarchar"/>
    </jdbc-type>
+    <jdbc-type name="SQLXML">
+       <db-type name="xml"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/sybase/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sybase/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sybase/types.xml
index 9e2959c..9327ddf 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/sybase/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/sybase/types.xml
@@ -42,9 +42,15 @@
    <jdbc-type name="CHAR">
        <db-type name="char"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="nchar"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="text"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="text"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK"/>
    <jdbc-type name="DATE">
        <db-type name="datetime"/>
@@ -68,6 +74,9 @@
    <jdbc-type name="LONGVARCHAR">
        <db-type name="text"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="text"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="numeric"/>
    </jdbc-type>
@@ -95,4 +104,10 @@
    <jdbc-type name="VARCHAR">
        <db-type name="varchar"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="nvarchar"/>
+   </jdbc-type>
+   <jdbc-type name="SQLXML">
+       <db-type name="text"/>
+   </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/main/resources/org/apache/cayenne/dba/types.xml
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/types.xml
index 4ac5029..5c1dc5f 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/types.xml
@@ -33,6 +33,9 @@ File must be called "types.xml".
    <jdbc-type name="BIGINT">
        <db-type name="BIGINT"/>
    </jdbc-type>
+   <jdbc-type name="ROWID">
+       <db-type name="ROWID"/>
+   </jdbc-type>
    <jdbc-type name="BINARY">
        <db-type name="BINARY"/>
    </jdbc-type>
@@ -48,9 +51,15 @@ File must be called "types.xml".
    <jdbc-type name="CHAR">
        <db-type name="CHAR"/>
    </jdbc-type>
+   <jdbc-type name="NCHAR">
+       <db-type name="NCHAR"/>
+   </jdbc-type>
    <jdbc-type name="CLOB">
        <db-type name="CLOB"/>
    </jdbc-type>
+   <jdbc-type name="NCLOB">
+       <db-type name="NCLOB"/>
+   </jdbc-type>
    <jdbc-type name="DATALINK">
        <db-type name="DATALINK"/>
    </jdbc-type>
@@ -78,6 +87,9 @@ File must be called "types.xml".
    <jdbc-type name="LONGVARCHAR">
        <db-type name="LONGVARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="LONGNVARCHAR">
+       <db-type name="LONGNVARCHAR"/>
+   </jdbc-type>
    <jdbc-type name="NUMERIC">
        <db-type name="NUMERIC"/>
    </jdbc-type>
@@ -111,4 +123,10 @@ File must be called "types.xml".
    <jdbc-type name="VARCHAR">
        <db-type name="VARCHAR"/>
    </jdbc-type>
+   <jdbc-type name="NVARCHAR">
+       <db-type name="NVARCHAR"/>
+   </jdbc-type>
+    <jdbc-type name="SQLXML">
+        <db-type name="SQLXML"/>
+    </jdbc-type>
 </types>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextBlobIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextBlobIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextBlobIT.java
index 8b0c4fa..5142ebd 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextBlobIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextBlobIT.java
@@ -121,9 +121,7 @@ public class DataContextBlobIT extends ServerCase {
             return;
         }
 
-        byte[] bytes2 = new byte[] {
-                'a', 'b', 'c', 'd'
-        };
+        byte[] bytes2 = {'a', 'b', 'c', 'd'};
 
         // insert new blob
         context.newObject(BlobTestEntity.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/01d0b24e/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
index 40347be..0132dff 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
@@ -287,12 +287,22 @@ public class DbLoaderIT extends ServerCase {
         assertNotNull(blobAttr);
         assertTrue(msgForTypeMismatch(Types.BLOB, blobAttr), Types.BLOB == blobAttr.getType()
                 || Types.LONGVARBINARY == blobAttr.getType());
+
         DbEntity clobEnt = getDbEntity(map, "CLOB_TEST");
         assertNotNull(clobEnt);
         DbAttribute clobAttr = getDbAttribute(clobEnt, "CLOB_COL");
         assertNotNull(clobAttr);
         assertTrue(msgForTypeMismatch(Types.CLOB, clobAttr), Types.CLOB == clobAttr.getType()
                 || Types.LONGVARCHAR == clobAttr.getType());
+
+/*
+        DbEntity nclobEnt = getDbEntity(map, "NCLOB_TEST");
+        assertNotNull(nclobEnt);
+        DbAttribute nclobAttr = getDbAttribute(nclobEnt, "NCLOB_COL");
+        assertNotNull(nclobAttr);
+        assertTrue(msgForTypeMismatch(Types.NCLOB, nclobAttr), Types.NCLOB == nclobAttr.getType()
+                || Types.LONGVARCHAR == nclobAttr.getType());
+*/
     }
 
     private void assertLobObjEntities(DataMap map) {
@@ -302,12 +312,22 @@ public class DbLoaderIT extends ServerCase {
         ObjAttribute blobAttr = blobEnt.getAttribute("blobCol");
         assertNotNull("BlobTest.blobCol failed to doLoad", blobAttr);
         assertEquals("byte[]", blobAttr.getType());
+
+
         ObjEntity clobEnt = map.getObjEntity("ClobTest");
         assertNotNull(clobEnt);
         // CLOBs should be mapped as Strings by default
         ObjAttribute clobAttr = clobEnt.getAttribute("clobCol");
         assertNotNull(clobAttr);
         assertEquals(String.class.getName(), clobAttr.getType());
+
+
+        ObjEntity nclobEnt = map.getObjEntity("NclobTest");
+        assertNotNull(nclobEnt);
+        // CLOBs should be mapped as Strings by default
+        ObjAttribute nclobAttr = nclobEnt.getAttribute("nclobCol");
+        assertNotNull(nclobAttr);
+        assertEquals(String.class.getName(), nclobAttr.getType());
     }
 
     private DbEntity getDbEntity(DataMap map, String name) {