You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/11/23 12:21:43 UTC

[1/4] ignite git commit: IGNITE-1753 Refactored usages of deprectaed CacheTypeMetadata to JdbcType.

Repository: ignite
Updated Branches:
  refs/heads/ignite-1.5 19d2dd057 -> d71f6129b


http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
index 2de9c62..f03f24f 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/model/ignite-type-metadata.xml
@@ -18,7 +18,7 @@
 -->
 
 <!--
-    XML generated by Apache Ignite Schema Import utility: 02/05/2015
+    XML generated by Apache Ignite Schema Import utility: 11/20/2015
 -->
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:util="http://www.springframework.org/schema/util"
@@ -27,149 +27,301 @@
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/util
                            http://www.springframework.org/schema/util/spring-util.xsd">
-    <bean class="org.apache.ignite.cache.CacheTypeMetadata">
-        <property name="databaseSchema" value="PUBLIC"/>
-        <property name="databaseTable" value="OBJECTS"/>
-        <property name="keyType" value="org.apache.ignite.schema.test.model.ObjectsKey"/>
-        <property name="valueType" value="org.apache.ignite.schema.test.model.Objects"/>
-        <property name="keyFields">
+    <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
+        <property name="types">
             <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="PK"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="pk"/>
-                    <property name="javaType" value="int"/>
-                </bean>
-            </list>
-        </property>
-        <property name="valueFields">
-            <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="PK"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="pk"/>
-                    <property name="javaType" value="int"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BOOLCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.BOOLEAN"/>
-                    </property>
-                    <property name="javaName" value="boolcol"/>
-                    <property name="javaType" value="java.lang.Boolean"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BYTECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TINYINT"/>
-                    </property>
-                    <property name="javaName" value="bytecol"/>
-                    <property name="javaType" value="java.lang.Byte"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="SHORTCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.SMALLINT"/>
-                    </property>
-                    <property name="javaName" value="shortcol"/>
-                    <property name="javaType" value="java.lang.Short"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="INTCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="intcol"/>
-                    <property name="javaType" value="java.lang.Integer"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="LONGCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.BIGINT"/>
-                    </property>
-                    <property name="javaName" value="longcol"/>
-                    <property name="javaType" value="java.lang.Long"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="FLOATCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.REAL"/>
-                    </property>
-                    <property name="javaName" value="floatcol"/>
-                    <property name="javaType" value="java.lang.Float"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DOUBLECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DOUBLE"/>
+                <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
+                    <property name="databaseSchema" value="PUBLIC"/>
+                    <property name="databaseTable" value="OBJECTS"/>
+                    <property name="keyType" value="org.apache.ignite.schema.test.model.ObjectsKey"/>
+                    <property name="valueType" value="org.apache.ignite.schema.test.model.Objects"/>
+                    <property name="keyFields">
+                        <list>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="PK"/>
+                                <property name="javaFieldType" value="int"/>
+                                <property name="javaFieldName" value="pk"/>
+                            </bean>
+                        </list>
+                    </property>
+                    <property name="valueFields">
+                        <list>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="PK"/>
+                                <property name="javaFieldType" value="int"/>
+                                <property name="javaFieldName" value="pk"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.BOOLEAN"/>
+                                </property>
+                                <property name="databaseFieldName" value="BOOLCOL"/>
+                                <property name="javaFieldType" value="java.lang.Boolean"/>
+                                <property name="javaFieldName" value="boolcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TINYINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="BYTECOL"/>
+                                <property name="javaFieldType" value="java.lang.Byte"/>
+                                <property name="javaFieldName" value="bytecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.SMALLINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="SHORTCOL"/>
+                                <property name="javaFieldType" value="java.lang.Short"/>
+                                <property name="javaFieldName" value="shortcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="INTCOL"/>
+                                <property name="javaFieldType" value="java.lang.Integer"/>
+                                <property name="javaFieldName" value="intcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.BIGINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="LONGCOL"/>
+                                <property name="javaFieldType" value="java.lang.Long"/>
+                                <property name="javaFieldName" value="longcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.REAL"/>
+                                </property>
+                                <property name="databaseFieldName" value="FLOATCOL"/>
+                                <property name="javaFieldType" value="java.lang.Float"/>
+                                <property name="javaFieldName" value="floatcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DOUBLE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DOUBLECOL"/>
+                                <property name="javaFieldType" value="java.lang.Double"/>
+                                <property name="javaFieldName" value="doublecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DOUBLE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DOUBLECOL2"/>
+                                <property name="javaFieldType" value="java.lang.Double"/>
+                                <property name="javaFieldName" value="doublecol2"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DECIMAL"/>
+                                </property>
+                                <property name="databaseFieldName" value="BIGDECIMALCOL"/>
+                                <property name="javaFieldType" value="java.math.BigDecimal"/>
+                                <property name="javaFieldName" value="bigdecimalcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.VARCHAR"/>
+                                </property>
+                                <property name="databaseFieldName" value="STRCOL"/>
+                                <property name="javaFieldType" value="java.lang.String"/>
+                                <property name="javaFieldName" value="strcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DATE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DATECOL"/>
+                                <property name="javaFieldType" value="java.sql.Date"/>
+                                <property name="javaFieldName" value="datecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TIME"/>
+                                </property>
+                                <property name="databaseFieldName" value="TIMECOL"/>
+                                <property name="javaFieldType" value="java.sql.Time"/>
+                                <property name="javaFieldName" value="timecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TIMESTAMP"/>
+                                </property>
+                                <property name="databaseFieldName" value="TSCOL"/>
+                                <property name="javaFieldType" value="java.sql.Timestamp"/>
+                                <property name="javaFieldName" value="tscol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.VARBINARY"/>
+                                </property>
+                                <property name="databaseFieldName" value="ARRCOL"/>
+                                <property name="javaFieldType" value="java.lang.Object"/>
+                                <property name="javaFieldName" value="arrcol"/>
+                            </bean>
+                        </list>
+                    </property>
+                </bean>
+                <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
+                    <property name="databaseSchema" value="PUBLIC"/>
+                    <property name="databaseTable" value="PRIMITIVES"/>
+                    <property name="keyType" value="org.apache.ignite.schema.test.model.PrimitivesKey"/>
+                    <property name="valueType" value="org.apache.ignite.schema.test.model.Primitives"/>
+                    <property name="keyFields">
+                        <list>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="PK"/>
+                                <property name="javaFieldType" value="int"/>
+                                <property name="javaFieldName" value="pk"/>
+                            </bean>
+                        </list>
+                    </property>
+                    <property name="valueFields">
+                        <list>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="PK"/>
+                                <property name="javaFieldType" value="int"/>
+                                <property name="javaFieldName" value="pk"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.BOOLEAN"/>
+                                </property>
+                                <property name="databaseFieldName" value="BOOLCOL"/>
+                                <property name="javaFieldType" value="boolean"/>
+                                <property name="javaFieldName" value="boolcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TINYINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="BYTECOL"/>
+                                <property name="javaFieldType" value="byte"/>
+                                <property name="javaFieldName" value="bytecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.SMALLINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="SHORTCOL"/>
+                                <property name="javaFieldType" value="short"/>
+                                <property name="javaFieldName" value="shortcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.INTEGER"/>
+                                </property>
+                                <property name="databaseFieldName" value="INTCOL"/>
+                                <property name="javaFieldType" value="int"/>
+                                <property name="javaFieldName" value="intcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.BIGINT"/>
+                                </property>
+                                <property name="databaseFieldName" value="LONGCOL"/>
+                                <property name="javaFieldType" value="long"/>
+                                <property name="javaFieldName" value="longcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.REAL"/>
+                                </property>
+                                <property name="databaseFieldName" value="FLOATCOL"/>
+                                <property name="javaFieldType" value="float"/>
+                                <property name="javaFieldName" value="floatcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DOUBLE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DOUBLECOL"/>
+                                <property name="javaFieldType" value="double"/>
+                                <property name="javaFieldName" value="doublecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DOUBLE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DOUBLECOL2"/>
+                                <property name="javaFieldType" value="double"/>
+                                <property name="javaFieldName" value="doublecol2"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DECIMAL"/>
+                                </property>
+                                <property name="databaseFieldName" value="BIGDECIMALCOL"/>
+                                <property name="javaFieldType" value="java.math.BigDecimal"/>
+                                <property name="javaFieldName" value="bigdecimalcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.VARCHAR"/>
+                                </property>
+                                <property name="databaseFieldName" value="STRCOL"/>
+                                <property name="javaFieldType" value="java.lang.String"/>
+                                <property name="javaFieldName" value="strcol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.DATE"/>
+                                </property>
+                                <property name="databaseFieldName" value="DATECOL"/>
+                                <property name="javaFieldType" value="java.sql.Date"/>
+                                <property name="javaFieldName" value="datecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TIME"/>
+                                </property>
+                                <property name="databaseFieldName" value="TIMECOL"/>
+                                <property name="javaFieldType" value="java.sql.Time"/>
+                                <property name="javaFieldName" value="timecol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.TIMESTAMP"/>
+                                </property>
+                                <property name="databaseFieldName" value="TSCOL"/>
+                                <property name="javaFieldType" value="java.sql.Timestamp"/>
+                                <property name="javaFieldName" value="tscol"/>
+                            </bean>
+                            <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                <property name="databaseFieldType">
+                                    <util:constant static-field="java.sql.Types.VARBINARY"/>
+                                </property>
+                                <property name="databaseFieldName" value="ARRCOL"/>
+                                <property name="javaFieldType" value="java.lang.Object"/>
+                                <property name="javaFieldName" value="arrcol"/>
+                            </bean>
+                        </list>
                     </property>
-                    <property name="javaName" value="doublecol"/>
-                    <property name="javaType" value="java.lang.Double"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DOUBLECOL2"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DOUBLE"/>
-                    </property>
-                    <property name="javaName" value="doublecol2"/>
-                    <property name="javaType" value="java.lang.Double"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BIGDECIMALCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DECIMAL"/>
-                    </property>
-                    <property name="javaName" value="bigdecimalcol"/>
-                    <property name="javaType" value="java.math.BigDecimal"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="STRCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.VARCHAR"/>
-                    </property>
-                    <property name="javaName" value="strcol"/>
-                    <property name="javaType" value="java.lang.String"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DATECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DATE"/>
-                    </property>
-                    <property name="javaName" value="datecol"/>
-                    <property name="javaType" value="java.sql.Date"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="TIMECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TIME"/>
-                    </property>
-                    <property name="javaName" value="timecol"/>
-                    <property name="javaType" value="java.sql.Time"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="TSCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TIMESTAMP"/>
-                    </property>
-                    <property name="javaName" value="tscol"/>
-                    <property name="javaType" value="java.sql.Timestamp"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="ARRCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.VARBINARY"/>
-                    </property>
-                    <property name="javaName" value="arrcol"/>
-                    <property name="javaType" value="java.lang.Object"/>
                 </bean>
             </list>
         </property>
-        <property name="queryFields">
-            <map>
+    </bean>
+    <bean class="org.apache.ignite.cache.QueryEntity">
+        <property name="keyType" value="org.apache.ignite.schema.test.model.ObjectsKey"/>
+        <property name="valueType" value="org.apache.ignite.schema.test.model.Objects"/>
+        <property name="fields">
+            <util:map map-class="java.util.LinkedHashMap">
                 <entry key="pk" value="int"/>
                 <entry key="boolcol" value="java.lang.Boolean"/>
                 <entry key="bytecol" value="java.lang.Byte"/>
@@ -185,157 +337,29 @@
                 <entry key="timecol" value="java.sql.Time"/>
                 <entry key="tscol" value="java.sql.Timestamp"/>
                 <entry key="arrcol" value="java.lang.Object"/>
-            </map>
-        </property>
-        <property name="ascendingFields">
-            <map>
-                <entry key="pk" value="int"/>
-            </map>
-        </property>
-    </bean>
-    <bean class="org.apache.ignite.cache.CacheTypeMetadata">
-        <property name="databaseSchema" value="PUBLIC"/>
-        <property name="databaseTable" value="PRIMITIVES"/>
-        <property name="keyType" value="org.apache.ignite.schema.test.model.PrimitivesKey"/>
-        <property name="valueType" value="org.apache.ignite.schema.test.model.Primitives"/>
-        <property name="keyFields">
-            <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="PK"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="pk"/>
-                    <property name="javaType" value="int"/>
-                </bean>
-            </list>
+            </util:map>
         </property>
-        <property name="valueFields">
+        <property name="indexes">
             <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="PK"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="pk"/>
-                    <property name="javaType" value="int"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BOOLCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.BOOLEAN"/>
-                    </property>
-                    <property name="javaName" value="boolcol"/>
-                    <property name="javaType" value="boolean"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BYTECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TINYINT"/>
-                    </property>
-                    <property name="javaName" value="bytecol"/>
-                    <property name="javaType" value="byte"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="SHORTCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.SMALLINT"/>
-                    </property>
-                    <property name="javaName" value="shortcol"/>
-                    <property name="javaType" value="short"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="INTCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.INTEGER"/>
-                    </property>
-                    <property name="javaName" value="intcol"/>
-                    <property name="javaType" value="int"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="LONGCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.BIGINT"/>
-                    </property>
-                    <property name="javaName" value="longcol"/>
-                    <property name="javaType" value="long"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="FLOATCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.REAL"/>
-                    </property>
-                    <property name="javaName" value="floatcol"/>
-                    <property name="javaType" value="float"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DOUBLECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DOUBLE"/>
-                    </property>
-                    <property name="javaName" value="doublecol"/>
-                    <property name="javaType" value="double"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DOUBLECOL2"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DOUBLE"/>
-                    </property>
-                    <property name="javaName" value="doublecol2"/>
-                    <property name="javaType" value="double"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="BIGDECIMALCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DECIMAL"/>
+                <bean class="org.apache.ignite.cache.QueryIndex">
+                    <property name="name" value="PRIMARY_KEY_C"/>
+                    <property name="indexType">
+                        <util:constant static-field="org.apache.ignite.cache.QueryIndexType.SORTED"/>
                     </property>
-                    <property name="javaName" value="bigdecimalcol"/>
-                    <property name="javaType" value="java.math.BigDecimal"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="STRCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.VARCHAR"/>
-                    </property>
-                    <property name="javaName" value="strcol"/>
-                    <property name="javaType" value="java.lang.String"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="DATECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.DATE"/>
+                    <property name="fields">
+                        <map>
+                            <entry key="PK" value="true"/>
+                        </map>
                     </property>
-                    <property name="javaName" value="datecol"/>
-                    <property name="javaType" value="java.sql.Date"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="TIMECOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TIME"/>
-                    </property>
-                    <property name="javaName" value="timecol"/>
-                    <property name="javaType" value="java.sql.Time"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="TSCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.TIMESTAMP"/>
-                    </property>
-                    <property name="javaName" value="tscol"/>
-                    <property name="javaType" value="java.sql.Timestamp"/>
-                </bean>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="ARRCOL"/>
-                    <property name="databaseType">
-                        <util:constant static-field="java.sql.Types.VARBINARY"/>
-                    </property>
-                    <property name="javaName" value="arrcol"/>
-                    <property name="javaType" value="java.lang.Object"/>
                 </bean>
             </list>
         </property>
-        <property name="queryFields">
-            <map>
+    </bean>
+    <bean class="org.apache.ignite.cache.QueryEntity">
+        <property name="keyType" value="org.apache.ignite.schema.test.model.PrimitivesKey"/>
+        <property name="valueType" value="org.apache.ignite.schema.test.model.Primitives"/>
+        <property name="fields">
+            <util:map map-class="java.util.LinkedHashMap">
                 <entry key="pk" value="int"/>
                 <entry key="boolcol" value="boolean"/>
                 <entry key="bytecol" value="byte"/>
@@ -351,12 +375,22 @@
                 <entry key="timecol" value="java.sql.Time"/>
                 <entry key="tscol" value="java.sql.Timestamp"/>
                 <entry key="arrcol" value="java.lang.Object"/>
-            </map>
+            </util:map>
         </property>
-        <property name="ascendingFields">
-            <map>
-                <entry key="pk" value="int"/>
-            </map>
+        <property name="indexes">
+            <list>
+                <bean class="org.apache.ignite.cache.QueryIndex">
+                    <property name="name" value="PRIMARY_KEY_D"/>
+                    <property name="indexType">
+                        <util:constant static-field="org.apache.ignite.cache.QueryIndexType.SORTED"/>
+                    </property>
+                    <property name="fields">
+                        <map>
+                            <entry key="PK" value="true"/>
+                        </map>
+                    </property>
+                </bean>
+            </list>
         </property>
     </bean>
 </beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/yardstick/config/ignite-store-config.xml
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/ignite-store-config.xml b/modules/yardstick/config/ignite-store-config.xml
index 35b8e19..031de91 100644
--- a/modules/yardstick/config/ignite-store-config.xml
+++ b/modules/yardstick/config/ignite-store-config.xml
@@ -35,31 +35,31 @@
         <property name="user" value="sa"/>
     </bean>
 
-    <bean id="sampleTypeMetadata" class="org.apache.ignite.cache.CacheTypeMetadata">
+    <bean id="sampleTypeMetadata" class="org.apache.ignite.cache.store.jdbc.JdbcType">
         <property name="databaseTable" value="SAMPLE"/>
         <property name="keyType" value="org.apache.ignite.yardstick.cache.model.SampleKey"/>
-        <property name="valueType" value="org.apache.ignite.yardstick.cache.model.SampleValue"/>
         <property name="keyFields">
             <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="ID"/>
-                    <property name="databaseType">
+                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                    <property name="databaseFieldType">
                         <util:constant static-field="java.sql.Types.INTEGER"/>
                     </property>
-                    <property name="javaName" value="id"/>
-                    <property name="javaType" value="int"/>
+                    <property name="databaseFieldName" value="ID"/>
+                    <property name="javaFieldType" value="int"/>
+                    <property name="javaFieldName" value="id"/>
                 </bean>
             </list>
         </property>
+        <property name="valueType" value="org.apache.ignite.yardstick.cache.model.SampleValue"/>
         <property name="valueFields">
             <list>
-                <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                    <property name="databaseName" value="VALUE"/>
-                    <property name="databaseType">
+                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                    <property name="databaseFieldType">
                         <util:constant static-field="java.sql.Types.INTEGER"/>
                     </property>
-                    <property name="javaName" value="id"/>
-                    <property name="javaType" value="int"/>
+                    <property name="databaseFieldName" value="VALUE"/>
+                    <property name="javaFieldType" value="int"/>
+                    <property name="javaFieldName" value="id"/>
                 </bean>
             </list>
         </property>
@@ -79,18 +79,19 @@
 
                     <property name="swapEnabled" value="false"/>
 
-                    <property name="typeMetadata">
-                        <list>
-                            <ref bean="sampleTypeMetadata"/>
-                        </list>
-                    </property>
-
                     <property name="cacheStoreFactory">
                         <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                             <property name="dataSourceBean" value="storeDataSource"/>
                             <property name="dialect">
                                 <bean class="org.apache.ignite.cache.store.jdbc.dialect.H2Dialect"/>
                             </property>
+                            <property name="types">
+                                <list>
+                                    <bean parent="sampleTypeMetadata">
+                                        <property name="cacheName" value="atomic"/>
+                                    </bean>
+                                </list>
+                            </property>
                         </bean>
                     </property>
                 </bean>
@@ -104,18 +105,19 @@
 
                     <property name="swapEnabled" value="false"/>
 
-                    <property name="typeMetadata">
-                        <list>
-                            <ref bean="sampleTypeMetadata"/>
-                        </list>
-                    </property>
-
                     <property name="cacheStoreFactory">
                         <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                             <property name="dataSourceBean" value="storeDataSource"/>
                             <property name="dialect">
                                 <bean class="org.apache.ignite.cache.store.jdbc.dialect.H2Dialect"/>
                             </property>
+                            <property name="types">
+                                <list>
+                                    <bean parent="sampleTypeMetadata">
+                                        <property name="cacheName" value="tx"/>
+                                    </bean>
+                                </list>
+                            </property>
                         </bean>
                     </property>
                 </bean>


[3/4] ignite git commit: IGNITE-1753 Refactored usages of deprectaed CacheTypeMetadata to JdbcType.

Posted by ak...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
index d78ea48..aa013b9 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
@@ -21,226 +21,392 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import javax.cache.CacheException;
 import javax.cache.integration.CacheLoaderException;
-import org.apache.ignite.cache.CacheTypeFieldMetadata;
-import org.apache.ignite.cache.CacheTypeMetadata;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectBuilder;
 import org.apache.ignite.cache.store.CacheStore;
 import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.jetbrains.annotations.Nullable;
 
 /**
  * Implementation of {@link CacheStore} backed by JDBC and POJO via reflection.
  *
- * This implementation stores objects in underlying database using java beans mapping description via reflection.
- * <p>
+ * This implementation stores objects in underlying database using java beans mapping description via reflection. <p>
  * Use {@link CacheJdbcPojoStoreFactory} factory to pass {@link CacheJdbcPojoStore} to {@link CacheConfiguration}.
  */
 public class CacheJdbcPojoStore<K, V> extends CacheAbstractJdbcStore<K, V> {
+    /** POJO methods cache. */
+    private volatile Map<String, Map<String, PojoMethodsCache>> pojosMthds = Collections.emptyMap();
+
     /**
-     * POJO methods cache.
+     * Get field value from object for use as query parameter.
+     *
+     * @param cacheName Cache name.
+     * @param typeName Type name.
+     * @param fldName Field name.
+     * @param obj Cache object.
+     * @return Field value from object.
+     * @throws CacheException in case of error.
      */
-    protected static class PojoMethodsCache {
-        /** POJO class. */
-        protected final Class<?> cls;
-
-        /** Constructor for POJO object. */
-        private Constructor ctor;
-
-        /** {@code true} if object is a simple type. */
-        private final boolean simple;
-
-        /** Cached setters for POJO object. */
-        private Map<String, Method> getters;
-
-        /** Cached getters for POJO object. */
-        private Map<String, Method> setters;
-
-        /**
-         * POJO methods cache.
-         *
-         * @param clsName Class name.
-         * @param fields Fields.
-         *
-         * @throws CacheException If failed to construct type cache.
-         */
-        public PojoMethodsCache(String clsName, Collection<CacheTypeFieldMetadata> fields) throws CacheException {
-            try {
-                cls = Class.forName(clsName);
-
-                if (simple = simpleType(cls))
-                    return;
+    @Override @Nullable protected Object extractParameter(@Nullable String cacheName, String typeName, TypeKind typeKind,
+        String fldName, Object obj) throws CacheException {
+        switch (typeKind) {
+            case BUILT_IN:
+                return obj;
+            case POJO:
+                return extractPojoParameter(cacheName, typeName, fldName, obj);
+            default:
+                return extractBinaryParameter(fldName, obj);
+        }
+    }
 
-                ctor = cls.getDeclaredConstructor();
+    /**
+     * Get field value from POJO for use as query parameter.
+     *
+     * @param cacheName Cache name.
+     * @param typeName Type name.
+     * @param fldName Field name.
+     * @param obj Cache object.
+     * @return Field value from object.
+     * @throws CacheException in case of error.
+     */
+    @Nullable private Object extractPojoParameter(@Nullable String cacheName, String typeName, String fldName,
+        Object obj) throws CacheException {
+        try {
+            Map<String, PojoMethodsCache> cacheMethods = pojosMthds.get(cacheName);
 
-                if (!ctor.isAccessible())
-                    ctor.setAccessible(true);
-            }
-            catch (ClassNotFoundException e) {
-                throw new CacheException("Failed to find class: " + clsName, e);
-            }
-            catch (NoSuchMethodException e) {
-                throw new CacheException("Failed to find default constructor for class: " + clsName, e);
-            }
+            if (cacheMethods == null)
+                throw new CacheException("Failed to find POJO type metadata for cache: " + U.maskName(cacheName));
 
-            setters = U.newHashMap(fields.size());
+            PojoMethodsCache mc = cacheMethods.get(typeName);
 
-            getters = U.newHashMap(fields.size());
+            if (mc == null)
+                throw new CacheException("Failed to find POJO type metadata for type: " + typeName);
 
-            for (CacheTypeFieldMetadata field : fields) {
-                String prop = capitalFirst(field.getJavaName());
+            Method getter = mc.getters.get(fldName);
 
-                try {
-                    getters.put(field.getJavaName(), cls.getMethod("get" + prop));
-                }
-                catch (NoSuchMethodException ignored) {
-                    try {
-                        getters.put(field.getJavaName(), cls.getMethod("is" + prop));
-                    }
-                    catch (NoSuchMethodException e) {
-                        throw new CacheException("Failed to find getter in POJO class [clsName=" + clsName +
-                            ", prop=" + field.getJavaName() + "]", e);
-                    }
-                }
+            if (getter == null)
+                throw new CacheLoaderException("Failed to find getter in POJO class [class=" + typeName +
+                    ", prop=" + fldName + "]");
 
-                try {
-                    setters.put(field.getJavaName(), cls.getMethod("set" + prop, field.getJavaType()));
-                }
-                catch (NoSuchMethodException e) {
-                    throw new CacheException("Failed to find setter in POJO class [clsName=" + clsName +
-                        ", prop=" + field.getJavaName() + "]", e);
-                }
-            }
+            return getter.invoke(obj);
         }
-
-        /**
-         * Capitalizes the first character of the given string.
-         *
-         * @param str String.
-         * @return String with capitalized first character.
-         */
-        @Nullable private String capitalFirst(@Nullable String str) {
-            return str == null ? null :
-                str.isEmpty() ? "" : Character.toUpperCase(str.charAt(0)) + str.substring(1);
+        catch (Exception e) {
+            throw new CacheException("Failed to read object of class: " + typeName, e);
         }
     }
 
-    /** Methods cache. */
-    protected volatile Map<String, Map<String, PojoMethodsCache>> mtdsCache = Collections.emptyMap();
+    /**
+     * Get field value from Binary object for use as query parameter.
+     *
+     * @param fieldName Field name to extract query parameter for.
+     * @param obj Object to process.
+     * @return Field value from object.
+     * @throws CacheException in case of error.
+     */
+    private Object extractBinaryParameter(String fieldName, Object obj) throws CacheException {
+        if (obj instanceof BinaryObject)
+            return ((BinaryObject)obj).field(fieldName);
+
+        throw new CacheException("Failed to read property value from non binary object [class=" +
+            obj.getClass() + ", property=" + fieldName + "]");
+    }
 
     /** {@inheritDoc} */
-    @Override protected void prepareBuilders(@Nullable String cacheName, Collection<CacheTypeMetadata> types)
-        throws CacheException {
-        Map<String, PojoMethodsCache> typeMethods = U.newHashMap(types.size() * 2);
+    @Override protected <R> R buildObject(@Nullable String cacheName, String typeName, TypeKind typeKind,
+        JdbcTypeField[] flds, Collection<String> hashFlds, Map<String, Integer> loadColIdxs, ResultSet rs)
+        throws CacheLoaderException {
+        switch (typeKind) {
+            case BUILT_IN:
+                return (R)buildBuiltinObject(typeName, flds, loadColIdxs, rs);
+            case POJO:
+                return (R)buildPojoObject(cacheName, typeName, flds, loadColIdxs, rs);
+            default:
+                return (R)buildBinaryObject(typeName, flds, hashFlds, loadColIdxs, rs);
+        }
+    }
 
-        for (CacheTypeMetadata type : types) {
-            String keyType = type.getKeyType();
-            typeMethods.put(keyType, new PojoMethodsCache(keyType, type.getKeyFields()));
+    /**
+     * Construct Java built in object from query result.
+     *
+     * @param typeName Type name.
+     * @param fields Fields descriptors.
+     * @param loadColIdxs Select query columns indexes.
+     * @param rs ResultSet to take data from.
+     * @return Constructed object.
+     * @throws CacheLoaderException If failed to construct POJO.
+     */
+    private Object buildBuiltinObject(String typeName, JdbcTypeField[] fields, Map<String, Integer> loadColIdxs,
+        ResultSet rs) throws CacheLoaderException {
+        try {
+            JdbcTypeField field = fields[0];
 
-            String valType = type.getValueType();
-            typeMethods.put(valType, new PojoMethodsCache(valType, type.getValueFields()));
+            return getColumnValue(rs, loadColIdxs.get(field.getDatabaseFieldName()), field.getJavaFieldType());
         }
+        catch (SQLException e) {
+            throw new CacheLoaderException("Failed to read object of class: " + typeName, e);
+        }
+    }
 
-        Map<String, Map<String, PojoMethodsCache>> newMtdsCache = new HashMap<>(mtdsCache);
+    /**
+     * Construct POJO from query result.
+     *
+     * @param cacheName Cache name.
+     * @param typeName Type name.
+     * @param flds Fields descriptors.
+     * @param loadColIdxs Select query columns index.
+     * @param rs ResultSet.
+     * @return Constructed POJO.
+     * @throws CacheLoaderException If failed to construct POJO.
+     */
+    private Object buildPojoObject(@Nullable String cacheName, String typeName,
+        JdbcTypeField[] flds, Map<String, Integer> loadColIdxs, ResultSet rs)
+        throws CacheLoaderException {
 
-        newMtdsCache.put(cacheName, typeMethods);
+        Map<String, PojoMethodsCache> cacheMethods = pojosMthds.get(cacheName);
 
-        mtdsCache = newMtdsCache;
-    }
+        if (cacheMethods == null)
+            throw new CacheLoaderException("Failed to find POJO types metadata for cache: " + U.maskName(cacheName));
 
-    /** {@inheritDoc} */
-    @Override protected <R> R buildObject(String cacheName, String typeName, Collection<CacheTypeFieldMetadata> fields,
-        Map<String, Integer> loadColIdxs, ResultSet rs) throws CacheLoaderException {
-        PojoMethodsCache mc = mtdsCache.get(cacheName).get(typeName);
+        PojoMethodsCache mc = cacheMethods.get(typeName);
 
         if (mc == null)
-            throw new CacheLoaderException("Failed to find cache type metadata for type: " + typeName);
+            throw new CacheLoaderException("Failed to find POJO type metadata for type: " + typeName);
 
         try {
-            if (mc.simple) {
-                CacheTypeFieldMetadata field = F.first(fields);
-
-                return (R)getColumnValue(rs, loadColIdxs.get(field.getDatabaseName()), mc.cls);
-            }
-
             Object obj = mc.ctor.newInstance();
 
-            for (CacheTypeFieldMetadata field : fields) {
-                String fldJavaName = field.getJavaName();
+            for (JdbcTypeField fld : flds) {
+                String fldJavaName = fld.getJavaFieldName();
 
                 Method setter = mc.setters.get(fldJavaName);
 
                 if (setter == null)
-                    throw new IllegalStateException("Failed to find setter in POJO class [clsName=" + typeName +
+                    throw new IllegalStateException("Failed to find setter in POJO class [type=" + typeName +
                         ", prop=" + fldJavaName + "]");
 
-                String fldDbName = field.getDatabaseName();
+                String fldDbName = fld.getDatabaseFieldName();
 
                 Integer colIdx = loadColIdxs.get(fldDbName);
 
                 try {
-                    setter.invoke(obj, getColumnValue(rs, colIdx, field.getJavaType()));
+                    Object colVal = getColumnValue(rs, colIdx, fld.getJavaFieldType());
+
+                    try {
+                        setter.invoke(obj, colVal);
+                    }
+                    catch (Exception e) {
+                        throw new CacheLoaderException("Failed to set property in POJO class [type=" + typeName +
+                            ", prop=" + fldJavaName + ", col=" + colIdx + ", dbName=" + fldDbName + "]", e);
+                    }
                 }
-                catch (Exception e) {
-                    throw new IllegalStateException("Failed to set property in POJO class [clsName=" + typeName +
+                catch (SQLException e) {
+                    throw new CacheLoaderException("Failed to read object property [type= " + typeName +
                         ", prop=" + fldJavaName + ", col=" + colIdx + ", dbName=" + fldDbName + "]", e);
                 }
             }
 
-            return (R)obj;
-        }
-        catch (SQLException e) {
-            throw new CacheLoaderException("Failed to read object of class: " + typeName, e);
+            return obj;
         }
         catch (Exception e) {
             throw new CacheLoaderException("Failed to construct instance of class: " + typeName, e);
         }
     }
 
-    /** {@inheritDoc} */
-    @Nullable @Override protected Object extractParameter(String cacheName, String typeName, String fieldName,
-        Object obj)
-        throws CacheException {
+    /**
+     * Construct binary object from query result.
+     *
+     * @param typeName Type name.
+     * @param fields Fields descriptors.
+     * @param hashFields Collection of fields to build hash for.
+     * @param loadColIdxs Select query columns index.
+     * @param rs ResultSet.
+     * @return Constructed binary object.
+     * @throws CacheLoaderException If failed to construct binary object.
+     */
+    protected Object buildBinaryObject(String typeName, JdbcTypeField[] fields,
+        Collection<String> hashFields, Map<String, Integer> loadColIdxs, ResultSet rs) throws CacheLoaderException {
         try {
-            PojoMethodsCache mc = mtdsCache.get(cacheName).get(typeName);
+            BinaryObjectBuilder builder = ignite.binary().builder(typeName);
 
-            if (mc == null)
-                throw new CacheException("Failed to find cache type metadata for type: " + typeName);
+            boolean calcHash = hashFields != null;
 
-            if (mc.simple)
-                return obj;
+            Collection<Object> hashValues = calcHash ? new ArrayList<>(hashFields.size()) : null;
 
-            Method getter = mc.getters.get(fieldName);
+            for (JdbcTypeField field : fields) {
+                Integer colIdx = loadColIdxs.get(field.getDatabaseFieldName());
 
-            if (getter == null)
-                throw new CacheLoaderException("Failed to find getter in POJO class [clsName=" + typeName +
-                    ", prop=" + fieldName + "]");
+                Object colVal = getColumnValue(rs, colIdx, field.getJavaFieldType());
 
-            return getter.invoke(obj);
+                builder.setField(field.getJavaFieldName(), colVal);
+
+                if (calcHash)
+                    hashValues.add(colVal);
+            }
+
+            if (calcHash)
+                builder.hashCode(hasher.hashCode(hashValues));
+
+            return builder.build();
         }
-        catch (Exception e) {
-            throw new CacheException("Failed to read object of class: " + typeName, e);
+        catch (SQLException e) {
+            throw new CacheException("Failed to read binary object", e);
         }
     }
 
-    /** {@inheritDoc} */
-    @Override protected Object keyTypeId(Object key) throws CacheException {
-        return key.getClass();
+    /**
+     * Calculate type ID for object.
+     *
+     * @param obj Object to calculate type ID for.
+     * @return Type ID.
+     * @throws CacheException If failed to calculate type ID for given object.
+     */
+    @Override protected Object typeIdForObject(Object obj) throws CacheException {
+        if (obj instanceof BinaryObject)
+            return ((BinaryObject)obj).typeId();
+
+        return obj.getClass();
     }
 
     /** {@inheritDoc} */
-    @Override protected Object keyTypeId(String type) throws CacheException {
+    @Override protected Object typeIdForTypeName(TypeKind kind, String typeName) throws CacheException {
+        if (kind == TypeKind.BINARY)
+            return ignite.binary().typeId(typeName);
+
         try {
-            return Class.forName(type);
+            return Class.forName(typeName);
         }
         catch (ClassNotFoundException e) {
-            throw new CacheException("Failed to find class: " + type, e);
+            throw new CacheException("Failed to find class: " + typeName, e);
+        }
+    }
+
+    /**
+     * Prepare internal store specific builders for provided types metadata.
+     *
+     * @param cacheName Cache name to prepare builders for.
+     * @param types Collection of types.
+     * @throws CacheException If failed to prepare internal builders for types.
+     */
+    @Override protected void prepareBuilders(@Nullable String cacheName, Collection<JdbcType> types)
+        throws CacheException {
+        Map<String, PojoMethodsCache> pojoMethods = U.newHashMap(types.size() * 2);
+
+        for (JdbcType type : types) {
+            String keyTypeName = type.getKeyType();
+
+            TypeKind keyKind = kindForName(keyTypeName);
+
+            if (keyKind == TypeKind.POJO) {
+                if (pojoMethods.containsKey(keyTypeName))
+                    throw new CacheException("Found duplicate key type [cache=" + U.maskName(cacheName) +
+                        ", keyType=" + keyTypeName + "]");
+
+                pojoMethods.put(keyTypeName, new PojoMethodsCache(keyTypeName, type.getKeyFields()));
+            }
+
+            String valTypeName = type.getValueType();
+
+            TypeKind valKind = kindForName(valTypeName);
+
+            if (valKind == TypeKind.POJO)
+                pojoMethods.put(valTypeName, new PojoMethodsCache(valTypeName, type.getValueFields()));
+        }
+
+        if (!pojoMethods.isEmpty()) {
+            Map<String, Map<String, PojoMethodsCache>> newPojosMethods = new HashMap<>(pojosMthds);
+
+            newPojosMethods.put(cacheName, pojoMethods);
+
+            pojosMthds = newPojosMethods;
+        }
+    }
+
+    /**
+     * POJO methods cache.
+     */
+    private static class PojoMethodsCache {
+        /** POJO class. */
+        private final Class<?> cls;
+
+        /** Constructor for POJO object. */
+        private Constructor ctor;
+
+        /** Cached setters for POJO object. */
+        private Map<String, Method> getters;
+
+        /** Cached getters for POJO object. */
+        private Map<String, Method> setters;
+
+        /**
+         * POJO methods cache.
+         *
+         * @param clsName Class name.
+         * @param fields Fields.
+         * @throws CacheException If failed to construct type cache.
+         */
+        private PojoMethodsCache(String clsName, JdbcTypeField[] fields) throws CacheException {
+            try {
+                cls = Class.forName(clsName);
+
+                ctor = cls.getDeclaredConstructor();
+
+                if (!ctor.isAccessible())
+                    ctor.setAccessible(true);
+            }
+            catch (ClassNotFoundException e) {
+                throw new CacheException("Failed to find class: " + clsName, e);
+            }
+            catch (NoSuchMethodException e) {
+                throw new CacheException("Failed to find default constructor for class: " + clsName, e);
+            }
+
+            setters = U.newHashMap(fields.length);
+
+            getters = U.newHashMap(fields.length);
+
+            for (JdbcTypeField field : fields) {
+                String prop = capitalFirst(field.getJavaFieldName());
+
+                try {
+                    getters.put(field.getJavaFieldName(), cls.getMethod("get" + prop));
+                }
+                catch (NoSuchMethodException ignored) {
+                    try {
+                        getters.put(field.getJavaFieldName(), cls.getMethod("is" + prop));
+                    }
+                    catch (NoSuchMethodException e) {
+                        throw new CacheException("Failed to find getter in POJO class [class=" + clsName +
+                            ", prop=" + field.getJavaFieldName() + "]", e);
+                    }
+                }
+
+                try {
+                    setters.put(field.getJavaFieldName(), cls.getMethod("set" + prop, field.getJavaFieldType()));
+                }
+                catch (NoSuchMethodException e) {
+                    throw new CacheException("Failed to find setter in POJO class [class=" + clsName +
+                        ", prop=" + field.getJavaFieldName() + "]", e);
+                }
+            }
+        }
+
+        /**
+         * Capitalizes the first character of the given string.
+         *
+         * @param str String.
+         * @return String with capitalized first character.
+         */
+        @Nullable private String capitalFirst(@Nullable String str) {
+            return str == null ? null :
+                str.isEmpty() ? "" : Character.toUpperCase(str.charAt(0)) + str.substring(1);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
index c90a69b..ded83ce 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
@@ -34,17 +34,53 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
  *
  * <h2 class="header">Spring Example</h2>
  * <pre name="code" class="xml">
- *     &lt;bean id= "simpleDataSource" class="org.h2.jdbcx.JdbcDataSource"/&gt;
+ *     &lt;bean id= "myDataSource" class="org.h2.jdbcx.JdbcDataSource"/&gt;
  *
  *     &lt;bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"&gt;
  *          ...
  *          &lt;property name="cacheConfiguration"&gt;
  *               &lt;list&gt;
  *                  &lt;bean class="org.apache.ignite.configuration.CacheConfiguration"&gt;
+ *                      &lt;property name="name" value="myCache" /&gt;
  *                      ...
  *                      &lt;property name="cacheStoreFactory"&gt;
  *                          &lt;bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory"&gt;
- *                              &lt;property name="dataSourceBean" value = "simpleDataSource" /&gt;
+ *                              &lt;property name="dataSourceBean" value="myDataSource" /&gt;
+ *                              &lt;property name="types"&gt;
+ *                                  &lt;list&gt;
+ *                                      &lt;bean class="org.apache.ignite.cache.store.jdbc.JdbcType"&gt;
+ *                                          &lt;property name="cacheName" value="myCache" /&gt;
+ *                                          &lt;property name="databaseSchema" value="MY_DB_SCHEMA" /&gt;
+ *                                          &lt;property name="databaseTable" value="PERSON" /&gt;
+ *                                          &lt;property name="keyType" value="java.lang.Integer" /&gt;
+ *                                          &lt;property name="keyFields"&gt;
+ *                                              &lt;list&gt;
+ *                                                  &lt;bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField"&gt;
+ *                                                      &lt;property name="databaseFieldType" &gt;
+ *                                                          &lt;util:constant static-field="java.sql.Types.INTEGER"/&gt;
+ *                                                      &lt;/property&gt;
+ *                                                      &lt;property name="databaseFieldName" value="ID" /&gt;
+ *                                                      &lt;property name="javaFieldType" value="java.lang.Integer" /&gt;
+ *                                                      &lt;property name="javaFieldName" value="id" /&gt;
+ *                                                  &lt;/bean&gt;
+ *                                              &lt;/list&gt;
+ *                                          &lt;/property&gt;
+ *                                          &lt;property name="valueType" value="my.company.Person" /&gt;
+ *                                          &lt;property name="valueFields"&gt;
+ *                                              &lt;list&gt;
+ *                                                  &lt;bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField"&gt;
+ *                                                      &lt;property name="databaseFieldType" &gt;
+ *                                                          &lt;util:constant static-field="java.sql.Types.VARCHAR"/&gt;
+ *                                                      &lt;/property&gt;
+ *                                                      &lt;property name="databaseFieldName" value="NAME" /&gt;
+ *                                                      &lt;property name="javaFieldType" value="java.lang.String" /&gt;
+ *                                                      &lt;property name="javaFieldName" value="name" /&gt;
+ *                                                  &lt;/bean&gt;
+ *                                              &lt;/list&gt;
+ *                                          &lt;/property&gt;
+ *                                      &lt;/bean&gt;
+ *                                  &lt;/list&gt;
+ *                              &lt;/property&gt;
  *                          &lt;/bean&gt;
  *                      &lt;/property&gt;
  *                  &lt;/bean&gt;
@@ -57,47 +93,81 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
  * <br>
  * For information about Spring framework visit <a href="http://www.springframework.org/">www.springframework.org</a>
  */
-public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheJdbcPojoStore<K, V>> {
+public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheAbstractJdbcStore<K, V>> {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Default value for write attempts. */
+    public static final int DFLT_WRITE_ATTEMPTS = 2;
+
+    /** Default batch size for put and remove operations. */
+    public static final int DFLT_BATCH_SIZE = 512;
+
+    /** Default batch size for put and remove operations. */
+    public static final int DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD = 512;
+
+    /** Maximum batch size for writeAll and deleteAll operations. */
+    private int batchSizw = DFLT_BATCH_SIZE;
+
     /** Name of data source bean. */
     private String dataSrcBean;
 
-    /** Data source. */
-    private transient DataSource dataSrc;
-
     /** Database dialect. */
     private JdbcDialect dialect;
 
+    /** Max workers thread count. These threads are responsible for load cache. */
+    private int maxPoolSize = Runtime.getRuntime().availableProcessors();
+
+    /** Maximum write attempts in case of database error. */
+    private int maxWriteAttempts = DFLT_WRITE_ATTEMPTS;
+
+    /** Parallel load cache minimum threshold. If {@code 0} then load sequentially. */
+    private int parallelLoadCacheMinThreshold = DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD;
+
+    /** Hash calculator.  */
+    private JdbcTypeHasher hasher = JdbcTypeDefaultHasher.INSTANCE;
+
+    /** Types that store could process. */
+    private JdbcType[] types;
+
+    /** Data source. */
+    private transient DataSource dataSrc;
+
     /** Application context. */
     @SpringApplicationContextResource
-    private transient Object appContext;
+    private transient Object appCtx;
 
     /** {@inheritDoc} */
     @Override public CacheJdbcPojoStore<K, V> create() {
         CacheJdbcPojoStore<K, V> store = new CacheJdbcPojoStore<>();
 
+        store.setBatchSize(batchSizw);
         store.setDialect(dialect);
+        store.setMaximumPoolSize(maxPoolSize);
+        store.setMaximumWriteAttempts(maxWriteAttempts);
+        store.setParallelLoadCacheMinimumThreshold(parallelLoadCacheMinThreshold);
+        store.setTypes(types);
 
         if (dataSrc != null)
             store.setDataSource(dataSrc);
-        else if (dataSrcBean != null) {
-            if (appContext == null)
-                throw new IgniteException("Spring application context resource is not injected.");
+        else {
+            if (dataSrcBean != null) {
+                if (appCtx == null)
+                    throw new IgniteException("Spring application context resource is not injected.");
 
-            IgniteSpringHelper spring;
+                IgniteSpringHelper spring;
 
-            try {
-                spring = IgniteComponentType.SPRING.create(false);
+                try {
+                    spring = IgniteComponentType.SPRING.create(false);
 
-                DataSource data = spring.loadBeanFromAppContext(appContext, dataSrcBean);
+                    DataSource data = spring.loadBeanFromAppContext(appCtx, dataSrcBean);
 
-                store.setDataSource(data);
-            }
-            catch (Exception e) {
-                throw new IgniteException("Failed to load bean in application context [beanName=" + dataSrcBean +
-                    ", igniteConfig=" + appContext + ']', e);
+                    store.setDataSource(data);
+                }
+                catch (Exception e) {
+                    throw new IgniteException("Failed to load bean in application context [beanName=" + dataSrcBean +
+                        ", igniteConfig=" + appCtx + ']', e);
+                }
             }
         }
 
@@ -105,43 +175,188 @@ public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheJdbcPojoSto
     }
 
     /**
-     * Sets name of the data source bean.
+     * Sets data source. Data source should be fully configured and ready-to-use.
      *
-     * @param dataSrcBean Data source bean name.
+     * @param dataSrc Data source.
      * @return {@code This} for chaining.
      * @see CacheJdbcPojoStore#setDataSource(DataSource)
      */
-    public CacheJdbcPojoStoreFactory<K, V> setDataSourceBean(String dataSrcBean) {
-        this.dataSrcBean = dataSrcBean;
+    public CacheJdbcPojoStoreFactory<K, V> setDataSource(DataSource dataSrc) {
+        this.dataSrc = dataSrc;
 
         return this;
     }
 
     /**
-     * Sets data source. Data source should be fully configured and ready-to-use.
+     * Get maximum batch size for delete and delete operations.
      *
-     * @param dataSrc Data source.
+     * @return Maximum batch size.
+     */
+    public int getBatchSize() {
+        return batchSizw;
+    }
+
+    /**
+     * Set maximum batch size for write and delete operations.
+     *
+     * @param batchSize Maximum batch size.
      * @return {@code This} for chaining.
-     * @see CacheJdbcPojoStore#setDataSource(DataSource)
      */
-    public CacheJdbcPojoStoreFactory<K, V> setDataSource(DataSource dataSrc) {
-        this.dataSrc = dataSrc;
+    public CacheJdbcPojoStoreFactory setBatchSize(int batchSize) {
+        this.batchSizw = batchSize;
+
+        return this;
+    }
+
+    /**
+     * Gets name of the data source bean.
+     *
+     * @return Data source bean name.
+     */
+    public String getDataSourceBean() {
+        return dataSrcBean;
+    }
+
+    /**
+     * Sets name of the data source bean.
+     *
+     * @param dataSrcBean Data source bean name.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setDataSourceBean(String dataSrcBean) {
+        this.dataSrcBean = dataSrcBean;
 
         return this;
     }
 
     /**
+     * Get database dialect.
+     *
+     * @return Database dialect.
+     */
+    public JdbcDialect getDialect() {
+        return dialect;
+    }
+
+    /**
      * Set database dialect.
      *
      * @param dialect Database dialect.
-     * @see CacheJdbcPojoStore#setDialect(JdbcDialect)
+     * @return {@code This} for chaining.
      */
-    public void setDialect(JdbcDialect dialect) {
+    public CacheJdbcPojoStoreFactory setDialect(JdbcDialect dialect) {
         this.dialect = dialect;
+
+        return this;
+    }
+
+    /**
+     * Get maximum workers thread count. These threads are responsible for queries execution.
+     *
+     * @return Maximum workers thread count.
+     */
+    public int getMaximumPoolSize() {
+        return maxPoolSize;
+    }
+
+    /**
+     * Set Maximum workers thread count. These threads are responsible for queries execution.
+     *
+     * @param maxPoolSize Max workers thread count.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setMaximumPoolSize(int maxPoolSize) {
+        this.maxPoolSize = maxPoolSize;
+
+        return this;
+    }
+
+    /**
+     * Gets maximum number of write attempts in case of database error.
+     *
+     * @return Maximum number of write attempts.
+     */
+    public int getMaximumWriteAttempts() {
+        return maxWriteAttempts;
+    }
+
+    /**
+     * Sets maximum number of write attempts in case of database error.
+     *
+     * @param maxWrtAttempts Number of write attempts.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setMaximumWriteAttempts(int maxWrtAttempts) {
+        this.maxWriteAttempts = maxWrtAttempts;
+
+        return this;
+    }
+
+    /**
+     * Parallel load cache minimum row count threshold.
+     *
+     * @return If {@code 0} then load sequentially.
+     */
+    public int getParallelLoadCacheMinimumThreshold() {
+        return parallelLoadCacheMinThreshold;
+    }
+
+    /**
+     * Parallel load cache minimum row count threshold.
+     *
+     * @param parallelLoadCacheMinThreshold Minimum row count threshold. If {@code 0} then load sequentially.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setParallelLoadCacheMinimumThreshold(int parallelLoadCacheMinThreshold) {
+        this.parallelLoadCacheMinThreshold = parallelLoadCacheMinThreshold;
+
+        return this;
+    }
+
+    /**
+     * Gets types known by store.
+     *
+     * @return Types known by store.
+     */
+    public JdbcType[] getTypes() {
+        return types;
+    }
+
+    /**
+     * Sets store configurations.
+     *
+     * @param types Store should process.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setTypes(JdbcType... types) {
+        this.types = types;
+
+        return this;
+    }
+
+    /**
+     * Gets hash code calculator.
+     *
+     * @return Hash code calculator.
+     */
+    public JdbcTypeHasher getHasher() {
+        return hasher;
+    }
+
+    /**
+     * Sets hash code calculator.
+     *
+     * @param hasher Hash code calculator.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setHasher(JdbcTypeHasher hasher) {
+        this.hasher = hasher;
+
+        return this;
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(CacheJdbcPojoStoreFactory.class, this);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
new file mode 100644
index 0000000..2107240
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
@@ -0,0 +1,255 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Description for type that could be stored into database by store.
+ */
+public class JdbcType implements Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Cache name. */
+    private String cacheName;
+
+    /** Schema name in database. */
+    private String dbSchema;
+
+    /** Table name in database. */
+    private String dbTbl;
+
+    /** Key class used to store key in cache. */
+    private String keyType;
+
+    /** List of fields descriptors for key object. */
+    @GridToStringInclude
+    private JdbcTypeField[] keyFields;
+
+    /** Value class used to store value in cache. */
+    private String valType;
+
+    /** List of fields descriptors for value object. */
+    @GridToStringInclude
+    private JdbcTypeField[] valFlds;
+
+    /** Custom type hasher. */
+    private JdbcTypeHasher hasher;
+
+    /**
+     * Empty constructor (all values are initialized to their defaults).
+     */
+    public JdbcType() {
+        /* No-op. */
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param type Type to copy.
+     */
+    public JdbcType(JdbcType type) {
+        cacheName = type.getCacheName();
+
+        dbSchema = type.getDatabaseSchema();
+        dbTbl = type.getDatabaseTable();
+
+        keyType = type.getKeyType();
+        keyFields = type.getKeyFields();
+
+        valType = type.getValueType();
+        valFlds = type.getValueFields();
+    }
+
+    /**
+     * Gets associated cache name.
+     *
+     * @return Сache name.
+     */
+    public String getCacheName() {
+        return cacheName;
+    }
+
+    /**
+     * Sets associated cache name.
+     *
+     * @param cacheName Cache name.
+     */
+    public JdbcType setCacheName(String cacheName) {
+        this.cacheName = cacheName;
+
+        return this;
+    }
+
+    /**
+     * Gets database schema name.
+     *
+     * @return Schema name.
+     */
+    public String getDatabaseSchema() {
+        return dbSchema;
+    }
+
+    /**
+     * Sets database schema name.
+     *
+     * @param dbSchema Schema name.
+     */
+    public JdbcType setDatabaseSchema(String dbSchema) {
+        this.dbSchema = dbSchema;
+
+        return this;
+    }
+
+    /**
+     * Gets table name in database.
+     *
+     * @return Table name in database.
+     */
+    public String getDatabaseTable() {
+        return dbTbl;
+    }
+
+    /**
+     * Table name in database.
+     *
+     * @param dbTbl Table name in database.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setDatabaseTable(String dbTbl) {
+        this.dbTbl = dbTbl;
+
+        return this;
+    }
+
+    /**
+     * Gets key type.
+     *
+     * @return Key type.
+     */
+    public String getKeyType() {
+        return keyType;
+    }
+
+    /**
+     * Sets key type.
+     *
+     * @param keyType Key type.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setKeyType(String keyType) {
+        this.keyType = keyType;
+
+        return this;
+    }
+
+    /**
+     * Sets key type.
+     *
+     * @param cls Key type class.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setKeyType(Class<?> cls) {
+        setKeyType(cls.getName());
+
+        return this;
+    }
+
+    /**
+     * Gets value type.
+     *
+     * @return Key type.
+     */
+    public String getValueType() {
+        return valType;
+    }
+
+    /**
+     * Sets value type.
+     *
+     * @param valType Value type.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setValueType(String valType) {
+        this.valType = valType;
+
+        return this;
+    }
+
+    /**
+     * Sets value type.
+     *
+     * @param cls Value type class.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setValueType(Class<?> cls) {
+        setValueType(cls.getName());
+
+        return this;
+    }
+
+    /**
+     * Gets optional persistent key fields (needed only if {@link CacheJdbcPojoStore} is used).
+     *
+     * @return Persistent key fields.
+     */
+    public JdbcTypeField[] getKeyFields() {
+        return keyFields;
+    }
+
+    /**
+     * Sets optional persistent key fields (needed only if {@link CacheJdbcPojoStore} is used).
+     *
+     * @param keyFlds Persistent key fields.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setKeyFields(JdbcTypeField... keyFlds) {
+        this.keyFields = keyFlds;
+
+        return this;
+    }
+
+    /**
+     * Gets optional persistent value fields (needed only if {@link CacheJdbcPojoStore} is used).
+     *
+     * @return Persistent value fields.
+     */
+    public JdbcTypeField[] getValueFields() {
+        return valFlds;
+    }
+
+    /**
+     * Sets optional persistent value fields (needed only if {@link CacheJdbcPojoStore} is used).
+     *
+     * @param valFlds Persistent value fields.
+     * @return {@code this} for chaining.
+     */
+    public JdbcType setValueFields(JdbcTypeField... valFlds) {
+        this.valFlds = valFlds;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcType.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
new file mode 100644
index 0000000..3baad3b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHasher.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import java.util.Collection;
+
+/**
+ * Default implementation of {@link JdbcTypeHasher}.
+ *
+ * This implementation ignores type and field names.
+ */
+public class JdbcTypeDefaultHasher implements JdbcTypeHasher {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Singleton instance to use. */
+    public static final JdbcTypeHasher INSTANCE = new JdbcTypeDefaultHasher();
+
+    /** {@inheritDoc} */
+    @Override public int hashCode(Collection<?> values) {
+        int hash = 0;
+
+        for (Object val : values)
+            hash = 31 * hash + (val != null ? val.hashCode() : 0);
+
+        return hash;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
new file mode 100644
index 0000000..3396b81
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeField.java
@@ -0,0 +1,172 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import java.io.Serializable;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Description of how field declared in database and in cache.
+ */
+public class JdbcTypeField implements Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Field JDBC type in database. */
+    private int dbFldType;
+
+    /** Field name in database. */
+    private String dbFldName;
+
+    /** Field java type. */
+    private Class<?> javaFldType;
+
+    /** Field name in java object. */
+    private String javaFldName;
+
+    /**
+     * Default constructor.
+     */
+    public JdbcTypeField() {
+        // No-op.
+    }
+
+    /**
+     * Full constructor.
+     *
+     * @param dbFldType Field JDBC type in database.
+     * @param dbFldName Field name in database.
+     * @param javaFldType Field java type.
+     * @param javaFldName Field name in java object.
+     */
+    public JdbcTypeField(int dbFldType, String dbFldName, Class<?> javaFldType, String javaFldName) {
+        this.dbFldType = dbFldType;
+        this.dbFldName = dbFldName;
+        this.javaFldType = javaFldType;
+        this.javaFldName = javaFldName;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param field Field to copy.
+     */
+    public JdbcTypeField(JdbcTypeField field) {
+        this(field.getDatabaseFieldType(), field.getDatabaseFieldName(),
+            field.getJavaFieldType(), field.getJavaFieldName());
+    }
+
+    /**
+     * @return Column JDBC type in database.
+     */
+    public int getDatabaseFieldType() {
+        return dbFldType;
+    }
+
+    /**
+     * @param dbFldType Column JDBC type in database.
+     * @return {@code this} for chaining.
+     */
+    public JdbcTypeField setDatabaseFieldType(int dbFldType) {
+        this.dbFldType = dbFldType;
+
+        return this;
+    }
+
+
+    /**
+     * @return Column name in database.
+     */
+    public String getDatabaseFieldName() {
+        return dbFldName;
+    }
+
+    /**
+     * @param dbFldName Column name in database.
+     * @return {@code this} for chaining.
+     */
+    public JdbcTypeField setDatabaseFieldName(String dbFldName) {
+        this.dbFldName = dbFldName;
+
+        return this;
+    }
+
+    /**
+     * @return Field java type.
+     */
+    public Class<?> getJavaFieldType() {
+        return javaFldType;
+    }
+
+    /**
+     * @param javaFldType Corresponding java type.
+     * @return {@code this} for chaining.
+     */
+    public JdbcTypeField setJavaFieldType(Class<?> javaFldType) {
+        this.javaFldType = javaFldType;
+
+        return this;
+    }
+
+    /**
+     * @return Field name in java object.
+     */
+    public String getJavaFieldName() {
+        return javaFldName;
+    }
+
+    /**
+     * @param javaFldName Field name in java object.
+     * @return {@code this} for chaining.
+     */
+    public JdbcTypeField setJavaFieldName(String javaFldName) {
+        this.javaFldName = javaFldName;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (!(o instanceof JdbcTypeField))
+            return false;
+
+        JdbcTypeField that = (JdbcTypeField)o;
+
+        return dbFldType == that.dbFldType && dbFldName.equals(that.dbFldName) &&
+            javaFldType == that.javaFldType && javaFldName.equals(that.javaFldName);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = dbFldType;
+        res = 31 * res + dbFldName.hashCode();
+
+        res = 31 * res + javaFldType.hashCode();
+        res = 31 * res + javaFldName.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcTypeField.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
new file mode 100644
index 0000000..9d1fcea
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHasher.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * API for implementing custom hashing logic for binary objects on server side.
+ */
+public interface JdbcTypeHasher extends Serializable {
+    /**
+     * Calculate hash code for specified object and fields.
+     *
+     * @param values Collection of values that should participate in hash code calculation.
+     * @return Hash code.
+     */
+    public int hashCode(Collection<?> values);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index fbe54e0..d0eeeb1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -260,6 +260,10 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     if (F.isEmpty(meta.getValueType()))
                         throw new IgniteCheckedException("Value type is not set: " + meta);
 
+                    if (meta.getQueryFields().isEmpty() && meta.getAscendingFields().isEmpty() &&
+                        meta.getDescendingFields().isEmpty() && meta.getGroups().isEmpty())
+                        continue;
+
                     TypeDescriptor desc = new TypeDescriptor();
 
                     // Key and value classes still can be available if they are primitive or JDK part.
@@ -2314,4 +2318,4 @@ public class GridQueryProcessor extends GridProcessorAdapter {
     private enum IndexType {
         ASC, DESC, TEXT
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
index 6171ff8..1bbcf2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCache.java
@@ -229,7 +229,9 @@ public class VisorCache implements Serializable {
     protected void estimateMemorySize(IgniteEx ignite, GridCacheAdapter ca, int sample) throws IgniteCheckedException {
         int size = ca.size();
 
-        Set<GridCacheEntryEx> set = ca.map().entries0();
+        Set<GridCacheEntryEx> set = ca.context().isNear()
+            ? ((GridNearCacheAdapter)ca).dht().map().entries0()
+            : ca.map().entries0();
 
         long memSz = 0;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
new file mode 100644
index 0000000..0f40bd9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreAbstractSelfTest.java
@@ -0,0 +1,395 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect;
+import org.apache.ignite.cache.store.jdbc.model.Person;
+import org.apache.ignite.cache.store.jdbc.model.PersonKey;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.h2.jdbcx.JdbcConnectionPool;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public abstract class CacheJdbcPojoStoreAbstractSelfTest extends GridCommonAbstractTest {
+    /** IP finder. */
+    protected static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** DB connection URL. */
+    protected static final String DFLT_CONN_URL = "jdbc:h2:mem:TestDatabase;DB_CLOSE_DELAY=-1";
+
+    /** Organization count. */
+    protected static final int ORGANIZATION_CNT = 1000;
+
+    /** Person count. */
+    protected static final int PERSON_CNT = 100000;
+
+    /** Flag indicating that tests should use transactional cache. */
+    protected static boolean transactional;
+
+    /** Flag indicating that tests should use primitive classes like java.lang.Integer for keys. */
+    protected static boolean builtinKeys;
+
+    /** Flag indicating that classes for keys available on class path or not. */
+    protected static boolean noKeyClasses;
+
+    /** Flag indicating that classes for values available on class path or not. */
+    protected static boolean noValClasses;
+
+    /**
+     * @return Connection to test in-memory H2 database.
+     * @throws SQLException
+     */
+    protected Connection getConnection() throws SQLException {
+        return DriverManager.getConnection(DFLT_CONN_URL, "sa", "");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        Connection conn = getConnection();
+
+        Statement stmt = conn.createStatement();
+
+        stmt.executeUpdate("DROP TABLE IF EXISTS Organization");
+        stmt.executeUpdate("DROP TABLE IF EXISTS Person");
+
+        stmt.executeUpdate("CREATE TABLE Organization (" +
+            " id INTEGER PRIMARY KEY," +
+            " name VARCHAR(50)," +
+            " city VARCHAR(50))");
+
+        stmt.executeUpdate("CREATE TABLE Person (" +
+            " id INTEGER PRIMARY KEY," +
+            " org_id INTEGER," +
+            " name VARCHAR(50))");
+
+        conn.commit();
+
+        U.closeQuiet(stmt);
+
+        fillSampleDatabase(conn);
+
+        U.closeQuiet(conn);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(IP_FINDER);
+
+        cfg.setDiscoverySpi(disco);
+
+        cfg.setCacheConfiguration(cacheConfiguration());
+
+        cfg.setMarshaller(marshaller());
+
+        ConnectorConfiguration connCfg = new ConnectorConfiguration();
+        cfg.setConnectorConfiguration(connCfg);
+
+        return cfg;
+    }
+
+    /**
+     * @return Marshaller to be used in test.
+     */
+    protected abstract Marshaller marshaller();
+
+    /**
+     * @return Types to be used in test.
+     */
+    protected JdbcType[] storeTypes() {
+        JdbcType[] storeTypes = new JdbcType[2];
+
+        storeTypes[0] = new JdbcType();
+        storeTypes[0].setDatabaseSchema("PUBLIC");
+        storeTypes[0].setDatabaseTable("ORGANIZATION");
+
+        if (builtinKeys) {
+            storeTypes[0].setKeyType("java.lang.Integer");
+            storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+        }
+        else {
+            storeTypes[0].setKeyType("org.apache.ignite.cache.store.jdbc.model.OrganizationKey" + (noKeyClasses ? "1" : ""));
+            storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+        }
+
+        storeTypes[0].setValueType("org.apache.ignite.cache.store.jdbc.model.Organization" + (noValClasses ? "1" : ""));
+        storeTypes[0].setValueFields(
+            new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+            new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+            new JdbcTypeField(Types.VARCHAR, "CITY", String.class, "city"));
+
+        storeTypes[1] = new JdbcType();
+        storeTypes[1].setDatabaseSchema("PUBLIC");
+        storeTypes[1].setDatabaseTable("PERSON");
+
+        if (builtinKeys) {
+            storeTypes[1].setKeyType("java.lang.Long");
+            storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Long.class, "id"));
+        }
+        else {
+            storeTypes[1].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonKey" + (noKeyClasses ? "1" : ""));
+            storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+        }
+
+        storeTypes[1].setValueType("org.apache.ignite.cache.store.jdbc.model.Person" + (noValClasses ? "1" : ""));
+        storeTypes[1].setValueFields(
+            new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+            new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+            new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"));
+
+        return storeTypes;
+    }
+
+    /**
+     * @return Cache configuration for test.
+     * @throws Exception In case when failed to create cache configuration.
+     */
+    protected CacheConfiguration cacheConfiguration() throws Exception {
+        CacheConfiguration cc = defaultCacheConfiguration();
+
+        cc.setCacheMode(PARTITIONED);
+        cc.setAtomicityMode(transactional ? TRANSACTIONAL : ATOMIC);
+        cc.setSwapEnabled(false);
+        cc.setWriteBehindEnabled(false);
+
+        CacheJdbcPojoStoreFactory<Object, Object> storeFactory = new CacheJdbcPojoStoreFactory<>();
+        storeFactory.setDialect(new H2Dialect());
+        storeFactory.setTypes(storeTypes());
+        storeFactory.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", "")); // H2 DataSource
+
+        cc.setCacheStoreFactory(storeFactory);
+        cc.setReadThrough(true);
+        cc.setWriteThrough(true);
+        cc.setLoadPreviousValue(true);
+
+        return cc;
+    }
+
+    /**
+     * Fill in-memory database with sample data.
+     *
+     * @param conn Connection to database.
+     * @throws SQLException In case of filling database with sample data failed.
+     */
+    protected void fillSampleDatabase(Connection conn) throws SQLException {
+        info("Start to fill sample database...");
+
+        PreparedStatement orgStmt = conn.prepareStatement("INSERT INTO Organization(id, name, city) VALUES (?, ?, ?)");
+
+        for (int i = 0; i < ORGANIZATION_CNT; i++) {
+            orgStmt.setInt(1, i);
+            orgStmt.setString(2, "name" + i);
+            orgStmt.setString(3, "city" + i % 10);
+
+            orgStmt.addBatch();
+        }
+
+        orgStmt.executeBatch();
+
+        U.closeQuiet(orgStmt);
+
+        conn.commit();
+
+        PreparedStatement prnStmt = conn.prepareStatement("INSERT INTO Person(id, org_id, name) VALUES (?, ?, ?)");
+
+        for (int i = 0; i < PERSON_CNT; i++) {
+            prnStmt.setInt(1, i);
+            prnStmt.setInt(2, i % 100);
+            prnStmt.setString(3, "name" + i);
+
+            prnStmt.addBatch();
+        }
+
+        prnStmt.executeBatch();
+
+        conn.commit();
+
+        U.closeQuiet(prnStmt);
+
+        info("Sample database prepared.");
+    }
+
+    /**
+     * Start test grid with specified options.
+     *
+     * @param builtin {@code True} if keys are built in java types.
+     * @param noKeyCls {@code True} if keys classes are not on class path.
+     * @param noValCls {@code True} if values classes are not on class path.
+     * @param trn {@code True} if cache should be started in transactional mode.
+     * @throws Exception
+     */
+    protected void startTestGrid(boolean builtin, boolean noKeyCls, boolean noValCls, boolean trn) throws Exception {
+        builtinKeys = builtin;
+        noKeyClasses = noKeyCls;
+        noValClasses = noValCls;
+        transactional = trn;
+
+        startGrid();
+    }
+
+    /**
+     * Check that data was loaded correctly.
+     */
+    protected void checkCacheContent() {
+        IgniteCache<Object, Object> c1 = grid().cache(null);
+
+        c1.loadCache(null);
+
+        assertEquals(ORGANIZATION_CNT + PERSON_CNT, c1.size());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCache() throws Exception {
+        startTestGrid(false, false, false, false);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheTx() throws Exception {
+        startTestGrid(false, false, false, true);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCachePrimitiveKeys() throws Exception {
+        startTestGrid(true, false, false, false);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCachePrimitiveKeysTx() throws Exception {
+        startTestGrid(true, false, false, true);
+
+        checkCacheContent();
+    }
+
+    /**
+     * Check put in cache and store it in db.
+     *
+     * @throws Exception If failed.
+     */
+    private void checkPut() throws Exception {
+        IgniteCache<PersonKey, Person> c1 = grid().cache(null);
+
+        Connection conn = getConnection();
+        try {
+            PreparedStatement stmt = conn.prepareStatement("SELECT ID, ORG_ID, NAME FROM PERSON WHERE ID = ?");
+
+            stmt.setInt(1, -1);
+
+            ResultSet rs = stmt.executeQuery();
+
+            assertFalse("Unexpected non empty result set", rs.next());
+
+            U.closeQuiet(rs);
+
+            // Test put-insert.
+            PersonKey key = new PersonKey(-1);
+
+            c1.put(key, new Person(-1, -2, "Person-to-test-put-insert", 999));
+
+            rs = stmt.executeQuery();
+
+            assertTrue("Unexpected empty result set", rs.next());
+
+            assertEquals(-1, rs.getInt(1));
+            assertEquals(-2, rs.getInt(2));
+            assertEquals("Person-to-test-put-insert", rs.getString(3));
+
+            assertFalse("Unexpected more data in result set", rs.next());
+
+            U.closeQuiet(rs);
+
+            // Test put-update.
+            c1.put(key, new Person(-1, -3, "Person-to-test-put-update", 999));
+
+            rs = stmt.executeQuery();
+
+            assertTrue("Unexpected empty result set", rs.next());
+
+            assertEquals(-1, rs.getInt(1));
+            assertEquals(-3, rs.getInt(2));
+            assertEquals("Person-to-test-put-update", rs.getString(3));
+
+            assertFalse("Unexpected more data in result set", rs.next());
+
+            U.closeQuiet(rs);
+        }
+        finally {
+            U.closeQuiet(conn);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPut() throws Exception {
+        startTestGrid(false, false, false, false);
+
+        checkPut();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutTx() throws Exception {
+        startTestGrid(false, false, false, true);
+
+        checkPut();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
new file mode 100644
index 0000000..f40f7d7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreOptimizedMarshallerSelfTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public class CacheJdbcPojoStoreOptimizedMarshallerSelfTest extends CacheJdbcPojoStoreAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected Marshaller marshaller(){
+        return new OptimizedMarshaller();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
new file mode 100644
index 0000000..39504b1
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStorePortableMarshallerSelfTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ignite.cache.store.jdbc;
+
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.marshaller.portable.BinaryMarshaller;
+
+/**
+ * Class for {@code PojoCacheStore} tests.
+ */
+public class CacheJdbcPojoStorePortableMarshallerSelfTest extends CacheJdbcPojoStoreAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected Marshaller marshaller(){
+        return new BinaryMarshaller();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoKeyClasses() throws Exception {
+        startTestGrid(false, true, false, false);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoKeyClassesTx() throws Exception {
+        startTestGrid(false, true, false, true);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoValueClasses() throws Exception {
+        startTestGrid(false, false, true, false);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoValueClassesTx() throws Exception {
+        startTestGrid(false, false, true, true);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoKeyAndValueClasses() throws Exception {
+        startTestGrid(false, true, true, false);
+
+        checkCacheContent();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLoadCacheNoKeyAndValueClassesTx() throws Exception {
+        startTestGrid(false, true, true, true);
+
+        checkCacheContent();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
index 0ad2cad..d8f75d3 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreTest.java
@@ -17,23 +17,19 @@
 
 package org.apache.ignite.cache.store.jdbc;
 
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Timestamp;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import javax.cache.integration.CacheWriterException;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.cache.CacheTypeMetadata;
-import org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect;
-import org.apache.ignite.cache.store.jdbc.dialect.JdbcDialect;
+
+import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect;
 import org.apache.ignite.cache.store.jdbc.model.Organization;
 import org.apache.ignite.cache.store.jdbc.model.OrganizationKey;
 import org.apache.ignite.cache.store.jdbc.model.Person;
@@ -41,16 +37,11 @@ import org.apache.ignite.cache.store.jdbc.model.PersonComplexKey;
 import org.apache.ignite.cache.store.jdbc.model.PersonKey;
 import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
 import org.apache.ignite.internal.util.typedef.CI2;
-import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiInClosure;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.cache.GridAbstractCacheStoreSelfTest;
 import org.h2.jdbcx.JdbcConnectionPool;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
-import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.core.io.UrlResource;
 
 /**
  * Class for {@code PojoCacheStore} tests.
@@ -59,9 +50,6 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
     /** DB connection URL. */
     private static final String DFLT_CONN_URL = "jdbc:h2:mem:autoCacheStore;DB_CLOSE_DELAY=-1";
 
-    /** Default config with mapping. */
-    private static final String DFLT_MAPPING_CONFIG = "modules/core/src/test/config/store/jdbc/ignite-type-metadata.xml";
-
     /** Organization count. */
     protected static final int ORGANIZATION_CNT = 1000;
 
@@ -77,71 +65,86 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
 
     /** {@inheritDoc} */
     @Override protected CacheJdbcPojoStore<Object, Object> store() {
-        CacheJdbcPojoStore<Object, Object> store = new CacheJdbcPojoStore<>();
-
-//        PGPoolingDataSource ds = new PGPoolingDataSource();
-//        ds.setUser("postgres");
-//        ds.setPassword("postgres");
-//        ds.setServerName("ip");
-//        ds.setDatabaseName("postgres");
-//        store.setDataSource(ds);
-
-//        MysqlDataSource ds = new MysqlDataSource();
-//        ds.setURL("jdbc:mysql://ip:port/dbname");
-//        ds.setUser("mysql");
-//        ds.setPassword("mysql");
-
+        CacheJdbcPojoStoreFactory<Object, Object> storeFactory = new CacheJdbcPojoStoreFactory<>();
+
+        JdbcType[] storeTypes = new JdbcType[6];
+
+        storeTypes[0] = new JdbcType();
+        storeTypes[0].setDatabaseSchema("PUBLIC");
+        storeTypes[0].setDatabaseTable("ORGANIZATION");
+        storeTypes[0].setKeyType("org.apache.ignite.cache.store.jdbc.model.OrganizationKey");
+        storeTypes[0].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+
+        storeTypes[0].setValueType("org.apache.ignite.cache.store.jdbc.model.Organization");
+        storeTypes[0].setValueFields(
+            new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+            new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+            new JdbcTypeField(Types.VARCHAR, "CITY", String.class, "city"));
+
+        storeTypes[1] = new JdbcType();
+        storeTypes[1].setDatabaseSchema("PUBLIC");
+        storeTypes[1].setDatabaseTable("PERSON");
+        storeTypes[1].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonKey");
+        storeTypes[1].setKeyFields(new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"));
+
+        storeTypes[1].setValueType("org.apache.ignite.cache.store.jdbc.model.Person");
+        storeTypes[1].setValueFields(
+            new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+            new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+            new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"));
+
+        storeTypes[2] = new JdbcType();
+        storeTypes[2].setDatabaseSchema("PUBLIC");
+        storeTypes[2].setDatabaseTable("PERSON_COMPLEX");
+        storeTypes[2].setKeyType("org.apache.ignite.cache.store.jdbc.model.PersonComplexKey");
+        storeTypes[2].setKeyFields(
+            new JdbcTypeField(Types.INTEGER, "ID", int.class, "id"),
+            new JdbcTypeField(Types.INTEGER, "ORG_ID", int.class, "orgId"),
+            new JdbcTypeField(Types.INTEGER, "CITY_ID", int.class, "cityId"));
+
+        storeTypes[2].setValueType("org.apache.ignite.cache.store.jdbc.model.Person");
+        storeTypes[2].setValueFields(
+            new JdbcTypeField(Types.INTEGER, "ID", Integer.class, "id"),
+            new JdbcTypeField(Types.INTEGER, "ORG_ID", Integer.class, "orgId"),
+            new JdbcTypeField(Types.VARCHAR, "NAME", String.class, "name"),
+            new JdbcTypeField(Types.INTEGER, "SALARY", Integer.class, "salary"));
+
+        storeTypes[3] = new JdbcType();
+        storeTypes[3].setDatabaseSchema("PUBLIC");
+        storeTypes[3].setDatabaseTable("TIMESTAMP_ENTRIES");
+        storeTypes[3].setKeyType("java.sql.Timestamp");
+        storeTypes[3].setKeyFields(new JdbcTypeField(Types.TIMESTAMP, "KEY", Timestamp.class, null));
+
+        storeTypes[3].setValueType("java.lang.Integer");
+        storeTypes[3].setValueFields(new JdbcTypeField(Types.INTEGER, "VAL", Integer.class, null));
+
+        storeTypes[4] = new JdbcType();
+        storeTypes[4].setDatabaseSchema("PUBLIC");
+        storeTypes[4].setDatabaseTable("STRING_ENTRIES");
+        storeTypes[4].setKeyType("java.lang.String");
+        storeTypes[4].setKeyFields(new JdbcTypeField(Types.VARCHAR, "KEY", String.class, null));
+
+        storeTypes[4].setValueType("java.lang.String");
+        storeTypes[4].setValueFields(new JdbcTypeField(Types.VARCHAR, "VAL", Integer.class, null));
+
+        storeTypes[5] = new JdbcType();
+        storeTypes[5].setDatabaseSchema("PUBLIC");
+        storeTypes[5].setDatabaseTable("UUID_ENTRIES");
+        storeTypes[5].setKeyType("java.util.UUID");
+        storeTypes[5].setKeyFields(new JdbcTypeField(Types.BINARY, "KEY", UUID.class, null));
+
+        storeTypes[5].setValueType("java.util.UUID");
+        storeTypes[5].setValueFields(new JdbcTypeField(Types.BINARY, "VAL", UUID.class, null));
+
+        storeFactory.setTypes(storeTypes);
+
+        storeFactory.setDialect(new H2Dialect());
+
+        CacheJdbcPojoStore<Object, Object> store = storeFactory.create();
+
+        // H2 DataSource
         store.setDataSource(JdbcConnectionPool.create(DFLT_CONN_URL, "sa", ""));
 
-        URL cfgUrl;
-
-        try {
-            cfgUrl = new URL(DFLT_MAPPING_CONFIG);
-        }
-        catch (MalformedURLException ignore) {
-            cfgUrl = U.resolveIgniteUrl(DFLT_MAPPING_CONFIG);
-        }
-
-        if (cfgUrl == null)
-            throw new IgniteException("Failed to resolve metadata path: " + DFLT_MAPPING_CONFIG);
-
-        try {
-            GenericApplicationContext springCtx = new GenericApplicationContext();
-
-            new XmlBeanDefinitionReader(springCtx).loadBeanDefinitions(new UrlResource(cfgUrl));
-
-            springCtx.refresh();
-
-            Collection<CacheTypeMetadata> typeMeta = springCtx.getBeansOfType(CacheTypeMetadata.class).values();
-
-            Map<Integer, Map<Object, CacheAbstractJdbcStore.EntryMapping>> cacheMappings = new HashMap<>();
-
-            JdbcDialect dialect = store.resolveDialect();
-
-            GridTestUtils.setFieldValue(store, CacheAbstractJdbcStore.class, "dialect", dialect);
-
-            Map<Object, CacheAbstractJdbcStore.EntryMapping> entryMappings = U.newHashMap(typeMeta.size());
-
-            for (CacheTypeMetadata type : typeMeta)
-                entryMappings.put(store.keyTypeId(type.getKeyType()),
-                    new CacheAbstractJdbcStore.EntryMapping(null, dialect, type));
-
-            store.prepareBuilders(null, typeMeta);
-
-            cacheMappings.put(null, entryMappings);
-
-            GridTestUtils.setFieldValue(store, CacheAbstractJdbcStore.class, "cacheMappings", cacheMappings);
-        }
-        catch (BeansException e) {
-            if (X.hasCause(e, ClassNotFoundException.class))
-                throw new IgniteException("Failed to instantiate Spring XML application context " +
-                    "(make sure all classes used in Spring configuration are present at CLASSPATH) " +
-                    "[springUrl=" + cfgUrl + ']', e);
-            else
-                throw new IgniteException("Failed to instantiate Spring XML application context [springUrl=" +
-                    cfgUrl + ", err=" + e.getMessage() + ']', e);
-        }
-
         return store;
     }
 
@@ -224,7 +227,6 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
         super.beforeTest();
     }
 
-
     /**
      * @throws Exception If failed.
      */
@@ -274,7 +276,7 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
             if (i > 0)
                 prnComplexStmt.setInt(5, 1000 + i * 500);
             else // Add person with null salary
-                prnComplexStmt.setNull(5, java.sql.Types.INTEGER);
+                prnComplexStmt.setNull(5, Types.INTEGER);
 
             prnComplexStmt.addBatch();
         }
@@ -302,9 +304,9 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
 
                     Person val = (Person)v;
 
-                    assert key.getId() == val.getId();
-                    assert key.getOrgId() == val.getOrgId();
-                    assertEquals("name"  + key.getId(), val.getName());
+                    assertTrue("Key ID should be the same as value ID", key.getId() == val.getId());
+                    assertTrue("Key orgID should be the same as value orgID", key.getOrgId() == val.getOrgId());
+                    assertEquals("name" + key.getId(), val.getName());
 
                     prnComplexKeys.add((PersonComplexKey)k);
                 }
@@ -351,25 +353,23 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
      * @throws Exception If failed.
      */
     public void testWriteRetry() throws Exception {
+        CacheJdbcPojoStore<Object, Object> store = store();
+
         // Special dialect that will skip updates, to test write retry.
-        BasicJdbcDialect dialect = new BasicJdbcDialect() {
+        store.setDialect(new H2Dialect() {
             /** {@inheritDoc} */
-            @Override public String updateQuery(String tblName, Collection<String> keyCols, Iterable<String> valCols) {
-                return super.updateQuery(tblName, keyCols, valCols) + " AND 1 = 0";
+            @Override public boolean hasMerge() {
+                return false;
             }
-        };
-
-        store.setDialect(dialect);
-
-        Map<String, Map<Object, CacheAbstractJdbcStore.EntryMapping>> cacheMappings =
-            GridTestUtils.getFieldValue(store, CacheAbstractJdbcStore.class, "cacheMappings");
-
-        CacheAbstractJdbcStore.EntryMapping em = cacheMappings.get(null).get(OrganizationKey.class);
 
-        CacheTypeMetadata typeMeta = GridTestUtils.getFieldValue(em, CacheAbstractJdbcStore.EntryMapping.class, "typeMeta");
+            /** {@inheritDoc} */
+            @Override public String updateQuery(String tblName, Collection<String> keyCols,
+                Iterable<String> valCols) {
+                return super.updateQuery(tblName, keyCols, valCols) + " AND 1 = 0";
+            }
+        });
 
-        cacheMappings.get(null).put(OrganizationKey.class,
-            new CacheAbstractJdbcStore.EntryMapping(null, dialect, typeMeta));
+        inject(store);
 
         Connection conn = store.openConnection(false);
 
@@ -392,6 +392,8 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
 
         try {
             store.write(new CacheEntryImpl<>(k1, v1));
+
+            fail("CacheWriterException wasn't thrown.");
         }
         catch (CacheWriterException e) {
             if (!e.getMessage().startsWith("Failed insert entry in database, violate a unique index or primary key") ||
@@ -418,4 +420,4 @@ public class CacheJdbcPojoStoreTest extends GridAbstractCacheStoreSelfTest<Cache
 
         assertNull(store.load(k));
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
index 757cedd..4c4bd58 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/jdbc/CacheJdbcStoreAbstractMultithreadedSelfTest.java
@@ -308,4 +308,4 @@ public abstract class CacheJdbcStoreAbstractMultithreadedSelfTest<T extends Cach
             }
         }, 8, "tx");
     }
-}
\ No newline at end of file
+}


[2/4] ignite git commit: IGNITE-1753 Refactored usages of deprectaed CacheTypeMetadata to JdbcType.

Posted by ak...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
index f6432a7..8af9443 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
@@ -30,7 +30,9 @@ import org.apache.ignite.cache.store.GridCacheBalancingStoreSelfTest;
 import org.apache.ignite.cache.store.GridCacheLoadOnlyStoreAdapterSelfTest;
 import org.apache.ignite.cache.store.StoreResourceInjectionSelfTest;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreMultitreadedSelfTest;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreOptimizedMarshallerSelfTest;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreTest;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStorePortableMarshallerSelfTest;
 import org.apache.ignite.cache.store.jdbc.GridCacheJdbcBlobStoreMultithreadedSelfTest;
 import org.apache.ignite.cache.store.jdbc.GridCacheJdbcBlobStoreSelfTest;
 import org.apache.ignite.internal.processors.cache.CacheAffinityCallSelfTest;
@@ -139,7 +141,7 @@ public class IgniteCacheTestSuite extends TestSuite {
     }
 
     /**
-     * @param ignoredTests
+     * @param ignoredTests Tests to ignore.
      * @return Test suite.
      * @throws Exception Thrown in case of the failure.
      */
@@ -211,6 +213,8 @@ public class IgniteCacheTestSuite extends TestSuite {
         suite.addTestSuite(GridCacheJdbcBlobStoreSelfTest.class);
         suite.addTestSuite(GridCacheJdbcBlobStoreMultithreadedSelfTest.class);
         suite.addTestSuite(CacheJdbcPojoStoreTest.class);
+        suite.addTestSuite(CacheJdbcPojoStoreOptimizedMarshallerSelfTest.class);
+        suite.addTestSuite(CacheJdbcPojoStorePortableMarshallerSelfTest.class);
         suite.addTestSuite(CacheJdbcPojoStoreMultitreadedSelfTest.class);
         suite.addTestSuite(GridCacheBalancingStoreSelfTest.class);
         suite.addTestSuite(GridCacheAffinityApiSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/README.txt
----------------------------------------------------------------------
diff --git a/modules/schema-import/README.txt b/modules/schema-import/README.txt
index 9b0a44d..d4f2dbf 100644
--- a/modules/schema-import/README.txt
+++ b/modules/schema-import/README.txt
@@ -17,19 +17,19 @@ Use Schema Import Utility for generation of type mapping and domain model in Jav
 
 For example you may use the following script for create sample type 'Person' in your RDBMS system:
 
-create table PERSON(id integer not null, firstName varchar(50), lastName varchar(50), PRIMARY KEY(id));
+create table PERSON(id integer not null PRIMARY KEY, first_name varchar(50), last_name varchar(50), salary double);
 
-insert into PERSON(id, first_name, last_name) values(1, 'Johannes', 'Kepler');
-insert into PERSON(id, first_name, last_name) values(2, 'Galileo', 'Galilei');
-insert into PERSON(id, first_name, last_name) values(3, 'Henry', 'More');
-insert into PERSON(id, first_name, last_name) values(4, 'Polish', 'Brethren');
-insert into PERSON(id, first_name, last_name) values(5, 'Robert', 'Boyle');
-insert into PERSON(id, first_name, last_name) values(6, 'Isaac', 'Newton');
+insert into PERSON(id, first_name, first_name, salary) values(1, 'Johannes', 'Kepler', 1000);
+insert into PERSON(id, first_name, first_name, salary) values(2, 'Galileo', 'Galilei', 1200);
+insert into PERSON(id, first_name, first_name, salary) values(3, 'Henry', 'More', 1150);
+insert into PERSON(id, first_name, first_name, salary) values(4, 'Polish', 'Brethren', 2000);
+insert into PERSON(id, first_name, first_name, salary) values(5, 'Robert', 'Boyle', 2500);
+insert into PERSON(id, first_name, first_name, salary) values(6, 'Isaac', 'Newton', 1300);
 
 The Ignite Schema Import utility generates the following artifacts:
- # Java POJO key and value classes
- # XML CacheTypeMetadata configuration
- # Java configuration snippet (alternative to XML)
+ # Java POJO key and value classes (enter "org.apache.ignite.schema" package name before generation).
+ # XML CacheTypeMetadata configuration.
+ # Java configuration snippet (alternative to XML).
 
 After you exit from the wizard, you should:
  # Copy generated POJO java classes to you project source folder.
@@ -42,6 +42,9 @@ After you exit from the wizard, you should:
 
 Example of spring configuration:
 
+<!-- Sample data source. -->
+<bean id="myDataSource" class="org.h2.jdbcx.JdbcDataSource"/>
+
 <bean class="org.apache.ignite.configuration.IgniteConfiguration">
     ...
     <!-- Cache configuration. -->
@@ -52,67 +55,63 @@ Example of spring configuration:
 
                 <!-- Cache store. -->
                 <property name="cacheStoreFactory">
-                    <bean class="javax.cache.configuration.FactoryBuilder$SingletonFactory">
-                        <constructor-arg>
-                            <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStore">
-                                <property name="dataSource">
-                                    <!-- TODO: Need specify connection pooling DataSource to your RDBMS system. -->
-                                    ...
-                                </property>
-                            </bean>
-                        </constructor-arg>
-                    </bean>
-                </property>
-
-                <!-- Type mapping description. -->
-                <property name="typeMetadata">
-                    <list>
-                        <bean class="org.apache.ignite.cache.CacheTypeMetadata">
-                            <property name="databaseTable" value="PERSON"/>
-                            <property name="keyType" value="org.apache.ignite.examples.datagrid.store.model.PersonKey"/>
-                            <property name="valueType" value="org.apache.ignite.examples.datagrid.store.Person"/>
-                            <property name="keyFields">
-                                <list>
-                                    <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                                        <property name="databaseName" value="ID"/>
-                                        <property name="databaseType">
-                                            <util:constant static-field="java.sql.Types.BIGINT"/>
-                                        </property>
-                                        <property name="javaName" value="id"/>
-                                        <property name="javaType" value="long"/>
-                                    </bean>
-                                </list>
-                            </property>
-                            <property name="valueFields">
+                    <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
+                        <property name="dataSourceBean" value="myDataSource"/>
+                        <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStore">
+                            <property name="dataSourceBean" value="myDataSource" />
+                            <property name="types">
                                 <list>
-                                    <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                                        <property name="databaseName" value="ID"/>
-                                        <property name="databaseType">
-                                            <util:constant static-field="java.sql.Types.BIGINT"/>
+                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
+                                        <property name="cacheName" value="myCache" />
+                                        <property name="databaseSchema" value="MY_DB_SCHEMA" />
+                                        <property name="databaseTable" value="PERSON" />
+                                        <property name="keyType" value="java.lang.Integer" />
+                                        <property name="keyFields">
+                                            <list>
+                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                                    <property name="databaseFieldType" >
+                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
+                                                    </property>
+                                                    <property name="databaseFieldName" value="ID" />
+                                                    <property name="javaFieldType" value="java.lang.Integer" />
+                                                    <property name="javaFieldName" value="id" />
+                                                </bean>
+                                            </list>
                                         </property>
-                                        <property name="javaName" value="id"/>
-                                        <property name="javaType" value="long"/>
-                                    </bean>
-                                    <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                                        <property name="databaseName" value="FIRST_NAME"/>
-                                        <property name="databaseType">
-                                            <util:constant static-field="java.sql.Types.VARCHAR"/>
+                                        <property name="valueType" value="my.company.Person" />
+                                        <property name="valueFields">
+                                            <list>
+                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                                    <property name="databaseFieldType" >
+                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
+                                                    </property>
+                                                    <property name="databaseFieldName" value="first_name" />
+                                                    <property name="javaFieldType" value="java.lang.String" />
+                                                    <property name="javaFieldName" value="firstName" />
+                                                </bean>
+                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                                    <property name="databaseFieldType" >
+                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
+                                                    </property>
+                                                    <property name="databaseFieldName" value="last_name" />
+                                                    <property name="javaFieldType" value="java.lang.String" />
+                                                    <property name="javaFieldName" value="lastName" />
+                                                </bean>
+                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
+                                                    <property name="databaseFieldType" >
+                                                        <util:constant static-field="java.sql.Types.DOUBLE"/>
+                                                    </property>
+                                                    <property name="databaseFieldName" value="salary" />
+                                                    <property name="javaFieldType" value="java.lang.Double" />
+                                                    <property name="javaFieldName" value="salary" />
+                                                </bean>
+                                            </list>
                                         </property>
-                                        <property name="javaName" value="firstName"/>
-                                        <property name="javaType" value="java.lang.String"/>
-                                    </bean>
-                                    <bean class="org.apache.ignite.cache.CacheTypeFieldMetadata">
-                                        <property name="databaseName" value="LAST_NAME"/>
-                                        <property name="databaseType">
-                                            <util:constant static-field="java.sql.Types.VARCHAR"/>
-                                        </property>
-                                        <property name="javaName" value="lastName"/>
-                                        <property name="javaType" value="java.lang.String"/>
                                     </bean>
                                 </list>
                             </property>
                         </bean>
-                    </list>
+                    </bean>
                 </property>
                 ...
             </bean>
@@ -127,44 +126,46 @@ IgniteConfiguration cfg = new IgniteConfiguration();
 ...
 CacheConfiguration ccfg = new CacheConfiguration<>();
 
-DataSource dataSource = null; // TODO: Need specify connection pooling DataSource to your RDBMS system.
-
-// Create store.
-CacheJdbcPojoStore store = new CacheJdbcPojoStore();
-store.setDataSource(dataSource);
-
 // Create store factory.
-ccfg.setCacheStoreFactory(new FactoryBuilder.SingletonFactory<>(store));
-
-// Configure cache to use store.
-ccfg.setReadThrough(true);
-ccfg.setWriteThrough(true);
+CacheJdbcPojoStoreFactory storeFactory = new CacheJdbcPojoStoreFactory();
+storeFactory.setDataSourceBean("myDataSource");
 
 // Configure cache types.
-Collection<CacheTypeMetadata> meta = new ArrayList<>();
+Collection<JdbcType> jdbcTypes = new ArrayList<>();
 
 // PERSON type mapping.
-CacheTypeMetadata tm = new CacheTypeMetadata();
+JdbcType jdbcType = new JdbcType();
+
+jdbcType.setCacheName(CACHE_NAME);
 
-tm.setDatabaseTable("PERSON");
+jdbcType.setDatabaseSchema("MY_DB_SCHEMA");
+jdbcType.setDatabaseTable("PERSON");
 
-tm.setKeyType("java.lang.Long");
-tm.setValueType("org.apache.ignite.examples.datagrid.store.Person");
+jdbcType.setKeyType("java.lang.Integer");
+jdbcType.setValueType("my.company.Person");
 
 // Key fields for PERSONS.
-tm.setKeyFields(F.asList(new CacheTypeFieldMetadata("ID", Types.BIGINT, "id", Long.class)));
+jdbcType.setKeyFields(F.asArray(new JdbcType(Types.INTEGER, "ID", Integer.class, "id")));
 
 // Value fields for PERSONS.
-tm.setValueFields(F.asList(
-    new CacheTypeFieldMetadata("ID", Types.BIGINT, "id", long.class),
-    new CacheTypeFieldMetadata("FIRST_NAME", Types.VARCHAR, "firstName", String.class),
-    new CacheTypeFieldMetadata("LAST_NAME", Types.VARCHAR, "lastName", String.class)
+jdbcType.setValueFields(F.asArray(
+    new JdbcType(Types.INTEGER, "ID", int.class, "id"),
+    new JdbcType(Types.VARCHAR, "first_name", String.class, "firstName"),
+    new JdbcType(Types.VARCHAR, "last_name", String.class, "lastName"),
+    new JdbcType(Types.DOUBLE, "salary", Double.class, "salary")
 ));
-...
-ccfg.setTypeMetadata(tm);
+
+storeFactory.setTypes(jdbcTypes.toArray(new JdbcType[]));
+
+// Configure cache to use store.
+ccfg.setReadThrough(true);
+ccfg.setWriteThrough(true);
+ccfg.setCacheStoreFactory(storeFactory);
 
 cfg.setCacheConfiguration(ccfg);
+
 ...
+
 // Start Ignite node.
 Ignition.start(cfg);
 
@@ -183,6 +184,7 @@ Performance optimization.
 
 1. Use DataSource with connection pool.
 2. Enable write-behind feature by default write-behind is disabled.
+   Note, write-behind should not be used with TRANSACTIONAL caches.
 
 Example of spring configuration:
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
index f1119cf..283ccc1 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/CodeGenerator.java
@@ -33,7 +33,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
-import org.apache.ignite.schema.model.IndexItem;
+
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.schema.model.PojoDescriptor;
 import org.apache.ignite.schema.model.PojoField;
 import org.apache.ignite.schema.ui.ConfirmCallable;
@@ -53,11 +55,9 @@ public class CodeGenerator {
     private static final String TAB2 = TAB + TAB;
     /** */
     private static final String TAB3 = TAB + TAB + TAB;
-    /** */
-    private static final String TAB4 = TAB + TAB + TAB + TAB;
 
     /** Java key words. */
-    private static final Set<String> javaKeywords = new HashSet<>(Arrays.asList(
+    private static final Set<String> JAVA_KEYWORDS = new HashSet<>(Arrays.asList(
         "abstract",     "assert",        "boolean",      "break",           "byte",
         "case",         "catch",         "char",         "class",           "const",
         "continue",     "default",       "do",           "double",          "else",
@@ -71,6 +71,12 @@ public class CodeGenerator {
         "void",         "volatile",      "while"
     ));
 
+    /** java.lang.*  */
+    private  static final String JAVA_LANG_PKG = "java.lang.";
+
+    /** java.util.*  */
+    private  static final String JAVA_UTIL_PKG = "java.util.";
+
     /** Regexp to validate java identifier. */
     private static final Pattern VALID_JAVA_IDENTIFIER =
         Pattern.compile("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*");
@@ -98,7 +104,7 @@ public class CodeGenerator {
             if (part.isEmpty())
                 throw new IllegalStateException(msg + " could not has empty parts!");
 
-            if (javaKeywords.contains(part))
+            if (JAVA_KEYWORDS.contains(part))
                 throw new IllegalStateException(msg + " could not contains reserved keyword:" +
                     " [type = " + type + ", identifier=" + identifier + ", keyword=" + part + "]");
 
@@ -160,16 +166,6 @@ public class CodeGenerator {
     }
 
     /**
-     * Add line to source code with four indents.
-     *
-     * @param src Source code.
-     * @param line Code line.
-     */
-    private static void add4(Collection<String> src, String line) {
-        src.add(TAB4 + line);
-    }
-
-    /**
      * @param str Source string.
      * @return String with first letters in upper case.
      */
@@ -278,11 +274,15 @@ public class CodeGenerator {
         boolean constructor, boolean includeKeys, ConfirmCallable askOverwrite) throws IOException {
         String type = key ? pojo.keyClassName() : pojo.valueClassName();
 
-        File out = new File(pkgFolder, type + ".java");
-
         checkValidJavaIdentifier(pkg, true, "Package", type);
+
         checkValidJavaIdentifier(type, false, "Type", type);
 
+        if (!pkgFolder.exists() && !pkgFolder.mkdirs())
+            throw new IOException("Failed to create folders for package: " + pkg);
+
+        File out = new File(pkgFolder, type + ".java");
+
         if (out.exists()) {
             MessageBox.Result choice = askOverwrite.confirm(out.getName());
 
@@ -529,9 +529,6 @@ public class CodeGenerator {
         boolean includeKeys, ConfirmCallable askOverwrite) throws IOException {
         File pkgFolder = new File(outFolder, pkg.replace('.', File.separatorChar));
 
-        if (!pkgFolder.exists() && !pkgFolder.mkdirs())
-            throw new IOException("Failed to create folders for package: " + pkg);
-
         generateCode(pojo, true, pkg, pkgFolder, constructor, false, askOverwrite);
 
         generateCode(pojo, false, pkg, pkgFolder, constructor, includeKeys, askOverwrite);
@@ -548,12 +545,13 @@ public class CodeGenerator {
         for (PojoField field : fields) {
             String javaTypeName = field.javaTypeName();
 
-            if (javaTypeName.startsWith("java.lang."))
-                javaTypeName = javaTypeName.substring(10);
+            if (javaTypeName.startsWith(JAVA_LANG_PKG))
+                javaTypeName = javaTypeName.substring(JAVA_LANG_PKG.length());
+            else  if (javaTypeName.startsWith(JAVA_UTIL_PKG))
+                javaTypeName = javaTypeName.substring(JAVA_UTIL_PKG.length());
 
-            add2(src, owner + ".add(new CacheTypeFieldMetadata(\"" + field.dbName() + "\", " +
-                "Types." + field.dbTypeName() + ", \"" +
-                field.javaName() + "\", " + javaTypeName + ".class));");
+            add2(src, owner + ".add(new JdbcTypeField(Types." + field.dbTypeName() + ", \"" + field.dbName() + "\", " +
+                    javaTypeName + ".class, \"" + field.javaName() + "\"));");
         }
     }
 
@@ -562,26 +560,24 @@ public class CodeGenerator {
      *
      * @param src Source code lines.
      * @param fields List of fields to add.
-     * @param varName Variable name to generate.
-     * @param mtdName Method name to generate.
      * @param comment Commentary text.
      * @param first {@code true} if variable should be declared.
      * @return {@code false} if variable was declared.
      */
-    private static boolean addQueryFields(Collection<String> src, Collection<PojoField> fields, String varName,
-        String mtdName, String comment, boolean first) {
+    private static boolean addQueryFields(Collection<String> src, Collection<PojoField> fields, String comment,
+        boolean first) {
         if (fields.isEmpty())
             return first;
 
         add2(src, comment);
-        add2(src, (first ? "Map<String, Class<?>> " : "") + varName + " = new LinkedHashMap<>();");
+        add2(src, (first ? "LinkedHashMap<String, String> " : "") + "fields = new LinkedHashMap<>();");
         add0(src, "");
 
         for (PojoField field : fields)
-            add2(src, varName + ".put(\"" + field.javaName() + "\", " + javaTypeName(field) + ".class);");
+            add2(src, "fields.put(\"" + field.javaName() + "\", \"" + javaTypeName(field) + "\");");
 
         add0(src, "");
-        add2(src, "type." + mtdName + "(" + varName + ");");
+        add2(src, "qryEntity.setFields(fields);");
         add0(src, "");
 
         return false;
@@ -615,118 +611,146 @@ public class CodeGenerator {
 
         Collection<String> src = new ArrayList<>(256);
 
-        header(src, pkg, "org.apache.ignite.cache.*;org.apache.ignite.cache.store.*;" +
-                "org.apache.ignite.configuration.*;org.apache.ignite.lang.*;;" +
-                "javax.cache.configuration.*;java.sql.*;java.util.*",
+        header(src, pkg, "java.sql.*;java.util.*;" +
+            "org.apache.ignite.cache.*;org.apache.ignite.cache.store.jdbc.*;" +
+            "org.apache.ignite.configuration.*;" + pkg + ".*",
             "CacheConfig", "CacheConfig");
 
         add1(src, "/**");
         add1(src, "* Configure cache.");
         add1(src, "*");
-        add1(src, "* @param name Cache name.");
+        add1(src, "* @param cacheName Cache name.");
         add1(src, "* @param storeFactory Cache store factory.");
         add1(src, "*/");
-        add1(src, "public static <K, V> CacheConfiguration<K, V> cache(String name," +
-            " Factory<CacheStore<K, V>> storeFactory) {");
+        add1(src, "public static <K, V> CacheConfiguration<K, V> cache(String cacheName," +
+            " CacheJdbcPojoStoreFactory<K, V> storeFactory) {");
         add2(src, "if (storeFactory == null)");
         add3(src, " throw new IllegalArgumentException(\"Cache store factory cannot be null.\");");
         add0(src, "");
-        add2(src, "CacheConfiguration<K, V> ccfg = new CacheConfiguration<>(name);");
+        add2(src, "CacheConfiguration<K, V> ccfg = new CacheConfiguration<>(cacheName);");
         add0(src, "");
         add2(src, "ccfg.setCacheStoreFactory(storeFactory);");
         add2(src, "ccfg.setReadThrough(true);");
         add2(src, "ccfg.setWriteThrough(true);");
         add0(src, "");
 
-        add2(src, "// Configure cache types. ");
-        add2(src, "Collection<CacheTypeMetadata> meta = new ArrayList<>();");
+        add2(src, "// Configure JDBC types. ");
+        add2(src, "Collection<JdbcType> jdbcTypes = new ArrayList<>();");
         add0(src, "");
 
         boolean first = true;
-        boolean firstAsc = true;
-        boolean firstDesc = true;
-        boolean firstGrps = true;
-        boolean firstGrp = true;
 
         for (PojoDescriptor pojo : pojos) {
             String tbl = pojo.table();
 
             add2(src, "// " + tbl + ".");
-            add2(src, (first ? "CacheTypeMetadata " : "") + "type = new CacheTypeMetadata();");
-            add0(src, "");
-            add2(src, "meta.add(type);");
+            add2(src, (first ? "JdbcType " : "") + "jdbcType = new JdbcType();");
             add0(src, "");
 
+            add2(src, "jdbcType.setCacheName(cacheName);");
+
             // Database info.
-            add2(src, "type.setDatabaseSchema(\"" + pojo.schema() + "\");");
-            add2(src, "type.setDatabaseTable(\"" + tbl + "\");");
+            add2(src, "jdbcType.setDatabaseSchema(\"" + pojo.schema() + "\");");
+            add2(src, "jdbcType.setDatabaseTable(\"" + tbl + "\");");
 
             // Java info.
-            add2(src, "type.setKeyType(" + pojo.keyClassName() + ".class.getName());");
-            add2(src, "type.setValueType(" + pojo.valueClassName() + ".class.getName());");
+            add2(src, "jdbcType.setKeyType(" + pojo.keyClassName() + ".class.getName());");
+            add2(src, "jdbcType.setValueType(" + pojo.valueClassName() + ".class.getName());");
             add0(src, "");
 
             // Key fields.
             add2(src, "// Key fields for " + tbl + ".");
-            add2(src, (first ? "Collection<CacheTypeFieldMetadata> " : "") + "keys = new ArrayList<>();");
+            add2(src, (first ? "Collection<JdbcTypeField> " : "") + "keys = new ArrayList<>();");
             addFields(src, "keys", pojo.keyFields());
-            add2(src, "type.setKeyFields(keys);");
+            add2(src, "jdbcType.setKeyFields(keys.toArray(new JdbcTypeField[keys.size()]));");
             add0(src, "");
 
             // Value fields.
             add2(src, "// Value fields for " + tbl + ".");
-            add2(src, (first ? "Collection<CacheTypeFieldMetadata> " : "") + "vals = new ArrayList<>();");
+            add2(src, (first ? "Collection<JdbcTypeField> " : "") + "vals = new ArrayList<>();");
             addFields(src, "vals", pojo.valueFields(includeKeys));
-            add2(src, "type.setValueFields(vals);");
+            add2(src, "jdbcType.setValueFields(vals.toArray(new JdbcTypeField[vals.size()]));");
             add0(src, "");
 
-            // Query fields.
-            addQueryFields(src, pojo.fields(), "qryFlds", "setQueryFields", "// Query fields for " + tbl + ".", first);
+            add2(src, "jdbcTypes.add(jdbcType);");
+            add0(src, "");
 
-            // Ascending fields.
-            firstAsc = addQueryFields(src, pojo.ascendingFields(), "ascFlds", "setAscendingFields",
-                "// Ascending fields for " + tbl + ".", firstAsc);
+            first = false;
+        }
 
-            // Descending fields.
-            firstDesc = addQueryFields(src, pojo.descendingFields(), "descFlds", "setDescendingFields",
-                "// Descending fields for " + tbl + ".", firstDesc);
+        add2(src, "storeFactory.setTypes(jdbcTypes.toArray(new JdbcType[jdbcTypes.size()]));");
+        add0(src, "");
 
-            // Groups.
-            Map<String, Map<String, IndexItem>> groups = pojo.groups();
+        // Queries entities.
+        add2(src, "// Configure query entities. ");
+        add2(src, "Collection<QueryEntity> qryEntities = new ArrayList<>();");
+        add0(src, "");
 
-            if (!groups.isEmpty()) {
-                add2(src, "// Groups for " + tbl + ".");
-                add2(src, (firstGrps ? "Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> " : "") +
-                    "grps = new LinkedHashMap<>();");
-                add0(src, "");
+        first = true;
+        boolean firstIdxs = true;
+        boolean firstIdx = true;
 
-                firstGrps = false;
+        for (PojoDescriptor pojo : pojos) {
+            String tbl = pojo.table();
 
-                for (Map.Entry<String, Map<String, IndexItem>> group : groups.entrySet()) {
-                    add2(src, (firstGrp ? "LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>> " : "") +
-                        "grpItems = new LinkedHashMap<>();");
-                    add0(src, "");
+            add2(src, (first ? "QueryEntity " : "") + "qryEntity = new QueryEntity();");
+            add0(src, "");
+            add2(src, "qryEntity.setKeyType(" + pojo.keyClassName() + ".class.getName());");
+            add2(src, "qryEntity.setValueType(" + pojo.valueClassName() + ".class.getName());");
+            add0(src, "");
+
+            // Query fields.
+            addQueryFields(src, pojo.fields(), "// Query fields for " + tbl + ".", first);
 
-                    for (Map.Entry<String, IndexItem> grpItem : group.getValue().entrySet()) {
-                        IndexItem idxCol = grpItem.getValue();
+            // Indexes.
+            Collection<QueryIndex> idxs = pojo.indexes();
 
-                        add2(src, "grpItems.put(\"" + grpItem.getKey() + "\", " +
-                            "new IgniteBiTuple<Class<?>, Boolean>(" + javaTypeName(idxCol.type()) + ".class, " +
-                            idxCol.descending() + "));");
+            if (!idxs.isEmpty()) {
+                add2(src, "// Indexes for " + tbl + ".");
+                add2(src, (firstIdxs ? "Collection<QueryIndex> " : "") + "idxs = new ArrayList<>();");
+                add0(src, "");
+
+                firstIdxs = false;
+
+                for (QueryIndex idx : idxs) {
+                    if (idx.getFields().size() == 1) {
+                        Map.Entry<String, Boolean> fld = F.first(idx.getFields().entrySet());
+
+                        add2(src, "idxs.add(new QueryIndex(\"" + fld.getKey() + "\", " + fld.getValue() + ", \"" +
+                            idx.getName()  + "\"));");
+                        add0(src, "");
                     }
+                    else {
+                        add2(src, (firstIdx ? "QueryIndex " : "") + "idx = new QueryIndex();");
+                        add0(src, "");
 
-                    add0(src, "");
-                    add2(src, "grps.put(\"" + group.getKey() + "\", grpItems);");
-                    add0(src, "");
+                        add2(src, "idx.setName(\"" + idx.getName() + "\");");
+                        add0(src, "");
 
-                    firstGrp = false;
+                        add2(src, (firstIdx ? "LinkedHashMap<String, Boolean> " : "") +
+                            "idxFlds = new LinkedHashMap<>();");
+                        add0(src, "");
+
+                        for (Map.Entry<String, Boolean> idxFld : idx.getFields().entrySet())
+                            add2(src, "idxFlds.put(\"" + idxFld.getKey()  + "\", " + idxFld.getValue() + ");");
+
+                        add0(src, "");
+
+                        add2(src, "idx.setFields(idxFlds);");
+                        add0(src, "");
+
+                        add2(src, "idxs.add(idx);");
+                        add0(src, "");
+
+                        firstIdx = false;
+                    }
                 }
 
-                add2(src, "type.setGroups(grps);");
+                add2(src, "qryEntity.setIndexes(idxs);");
                 add0(src, "");
             }
 
-            add2(src, "ccfg.setTypeMetadata(meta);");
+            add2(src, "ccfg.setQueryEntities(qryEntities);");
             add0(src, "");
 
             first = false;

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
index bc9bab7..547e7b0 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/generator/XmlGenerator.java
@@ -35,10 +35,11 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-import org.apache.ignite.cache.CacheTypeFieldMetadata;
-import org.apache.ignite.cache.CacheTypeMetadata;
-import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.schema.model.IndexItem;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
+import org.apache.ignite.cache.store.jdbc.JdbcType;
+import org.apache.ignite.cache.store.jdbc.JdbcTypeField;
 import org.apache.ignite.schema.model.PojoDescriptor;
 import org.apache.ignite.schema.model.PojoField;
 import org.apache.ignite.schema.ui.ConfirmCallable;
@@ -166,20 +167,20 @@ public class XmlGenerator {
      * @param name Property name.
      * @param fields Collection of POJO fields.
      */
-    private static void addFields(Document doc, Node parent, String name, Collection<PojoField> fields) {
+    private static void addJdbcFields(Document doc, Node parent, String name, Collection<PojoField> fields) {
         if (!fields.isEmpty()) {
             Element prop = addProperty(doc, parent, name, null);
 
             Element list = addElement(doc, prop, "list");
 
             for (PojoField field : fields) {
-                Element item = addBean(doc, list, CacheTypeFieldMetadata.class);
+                Element item = addBean(doc, list, JdbcTypeField.class);
 
-                addProperty(doc, item, "databaseName", field.dbName());
-                Element dbType = addProperty(doc, item, "databaseType", null);
+                Element dbType = addProperty(doc, item, "databaseFieldType", null);
                 addElement(doc, dbType, "util:constant", "static-field", "java.sql.Types." + field.dbTypeName());
-                addProperty(doc, item, "javaName", field.javaName());
-                addProperty(doc, item, "javaType", field.javaTypeName());
+                addProperty(doc, item, "databaseFieldName", field.dbName());
+                addProperty(doc, item, "javaFieldType", field.javaTypeName());
+                addProperty(doc, item, "javaFieldName", field.javaName());
             }
         }
     }
@@ -189,14 +190,13 @@ public class XmlGenerator {
      *
      * @param doc XML document.
      * @param parent Parent XML node.
-     * @param name Property name.
      * @param fields Map with fields.
      */
-    private static void addQueryFields(Document doc, Node parent, String name, Collection<PojoField> fields) {
+    private static void addQueryFields(Document doc, Node parent, Collection<PojoField> fields) {
         if (!fields.isEmpty()) {
-            Element prop = addProperty(doc, parent, name, null);
+            Element prop = addProperty(doc, parent, "fields", null);
 
-            Element map = addElement(doc, prop, "map");
+            Element map = addElement(doc, prop, "util:map", "map-class", "java.util.LinkedHashMap");
 
             for (PojoField field : fields)
                 addElement(doc, map, "entry", "key", field.javaName(), "value", field.javaTypeName());
@@ -208,47 +208,45 @@ public class XmlGenerator {
      *
      * @param doc XML document.
      * @param parent Parent XML node.
-     * @param groups Map with indexes.
+     * @param idxs Indexes.
      */
-    private static void addQueryGroups(Document doc, Node parent,
-        Map<String, Map<String, IndexItem>> groups) {
-        if (!groups.isEmpty()) {
-            Element prop = addProperty(doc, parent, "groups", null);
+    private static void addQueryIndexes(Document doc, Node parent, Collection<QueryIndex> idxs) {
+        if (!idxs.isEmpty()) {
+            Element prop = addProperty(doc, parent, "indexes", null);
 
-            Element map = addElement(doc, prop, "map");
+            Element list = addElement(doc, prop, "list");
 
-            for (Map.Entry<String, Map<String, IndexItem>> group : groups.entrySet()) {
-                Element entry1 = addElement(doc, map, "entry", "key", group.getKey());
+            for (QueryIndex idx : idxs) {
+                Element idxBean = addBean(doc, list, QueryIndex.class);
 
-                Element val1 = addElement(doc, entry1, "map");
+                addProperty(doc, idxBean, "name", idx.getName());
 
-                Map<String, IndexItem> grpItems = group.getValue();
+                Element idxType = addProperty(doc, idxBean, "indexType", null);
+                addElement(doc, idxType, "util:constant", "static-field", "org.apache.ignite.cache.QueryIndexType." + idx.getIndexType());
 
-                for (Map.Entry<String, IndexItem> grpItem : grpItems.entrySet()) {
-                    Element entry2 = addElement(doc, val1, "entry", "key", grpItem.getKey());
+                Element flds = addProperty(doc, idxBean, "fields", null);
 
-                    Element val2 = addBean(doc, entry2, IgniteBiTuple.class);
+                Element fldsMap = addElement(doc, flds, "map");
 
-                    IndexItem idxCol = grpItem.getValue();
+                Map<String, Boolean> idxFlds = idx.getFields();
 
-                    addElement(doc, val2, "constructor-arg", null, null, "value", idxCol.type());
-                    addElement(doc, val2, "constructor-arg", null, null, "value", String.valueOf(idxCol.descending()));
-                }
+                for (Map.Entry<String, Boolean> fld : idxFlds.entrySet())
+                    addElement(doc, fldsMap, "entry", "key", fld.getKey(), "value", fld.getValue().toString());
             }
         }
     }
 
     /**
-     * Add element with type metadata to XML document.
+     * Add element with JDBC POJO store factory to XML document.
      *
      * @param doc XML document.
      * @param parent Parent XML node.
      * @param pkg Package fo types.
      * @param pojo POJO descriptor.
      */
-    private static void addTypeMetadata(Document doc, Node parent, String pkg, PojoDescriptor pojo,
+    private static void addJdbcPojoStoreFactory(Document doc, Node parent, String pkg, PojoDescriptor pojo,
         boolean includeKeys) {
-        Element bean = addBean(doc, parent, CacheTypeMetadata.class);
+        Element bean = addBean(doc, parent, JdbcType.class);
 
         addProperty(doc, bean, "databaseSchema", pojo.schema());
 
@@ -258,17 +256,29 @@ public class XmlGenerator {
 
         addProperty(doc, bean, "valueType", pkg + "." + pojo.valueClassName());
 
-        addFields(doc, bean, "keyFields", pojo.keyFields());
+        addJdbcFields(doc, bean, "keyFields", pojo.keyFields());
 
-        addFields(doc, bean, "valueFields", pojo.valueFields(includeKeys));
+        addJdbcFields(doc, bean, "valueFields", pojo.valueFields(includeKeys));
+    }
 
-        addQueryFields(doc, bean, "queryFields", pojo.fields());
+    /**
+     * Add element with query entity to XML document.
+     *
+     * @param doc XML document.
+     * @param parent Parent XML node.
+     * @param pkg Package fo types.
+     * @param pojo POJO descriptor.
+     */
+    private static void addQueryEntity(Document doc, Node parent, String pkg, PojoDescriptor pojo) {
+        Element bean = addBean(doc, parent, QueryEntity.class);
+
+        addProperty(doc, bean, "keyType", pkg + "." + pojo.keyClassName());
 
-        addQueryFields(doc, bean, "ascendingFields", pojo.ascendingFields());
+        addProperty(doc, bean, "valueType", pkg + "." + pojo.valueClassName());
 
-        addQueryFields(doc, bean, "descendingFields", pojo.descendingFields());
+        addQueryFields(doc, bean, pojo.fields());
 
-        addQueryGroups(doc, bean, pojo.groups());
+        addQueryIndexes(doc, bean, pojo.indexes());
     }
 
     /**
@@ -333,8 +343,15 @@ public class XmlGenerator {
                 "http://www.springframework.org/schema/util " +
                 "http://www.springframework.org/schema/util/spring-util.xsd");
 
+            Element factoryBean = addBean(doc, beans, CacheJdbcPojoStoreFactory.class);
+            Element typesElem = addProperty(doc, factoryBean, "types", null);
+            Element typesItemsElem = addElement(doc, typesElem, "list");
+
+            for (PojoDescriptor pojo : pojos)
+                addJdbcPojoStoreFactory(doc, typesItemsElem, pkg, pojo, includeKeys);
+
             for (PojoDescriptor pojo : pojos)
-                addTypeMetadata(doc, beans, pkg, pojo, includeKeys);
+                addQueryEntity(doc, beans, pkg, pojo);
 
             TransformerFactory transformerFactory = TransformerFactory.newInstance();
 
@@ -361,4 +378,4 @@ public class XmlGenerator {
             throw new IllegalStateException(e);
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/model/IndexItem.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/IndexItem.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/model/IndexItem.java
deleted file mode 100644
index d51ec8f..0000000
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/IndexItem.java
+++ /dev/null
@@ -1,54 +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.ignite.schema.model;
-
-/**
- * Index item descriptor.
- */
-public class IndexItem {
-    /** Column type. */
-    private final String type;
-
-    /** Sort direction. */
-    private final Boolean desc;
-
-    /**
-     * Constructor.
-     *
-     * @param type Column type.
-     * @param desc Sort direction.
-     */
-    public IndexItem(String type, Boolean desc) {
-        this.type = type;
-        this.desc = desc;
-    }
-
-    /**
-     * @return Column type.
-     */
-    public String type() {
-        return type;
-    }
-
-    /**
-     * @return Sort direction.
-     */
-    public Boolean descending() {
-        return desc;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/model/PojoDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/PojoDescriptor.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/model/PojoDescriptor.java
index d84643b..5053b07 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/PojoDescriptor.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/model/PojoDescriptor.java
@@ -21,12 +21,8 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.SimpleStringProperty;
@@ -35,6 +31,7 @@ import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.schema.parser.DbColumn;
 import org.apache.ignite.schema.parser.DbTable;
 
@@ -99,9 +96,6 @@ public class PojoDescriptor {
     /** Java class fields. */
     private final ObservableList<PojoField> fields;
 
-    /** Fields map for quick access. */
-    private final Map<String, PojoField> fieldsMap;
-
     /**
      * Constructor of POJO descriptor.
      *
@@ -125,8 +119,6 @@ public class PojoDescriptor {
 
         List<PojoField> flds = new ArrayList<>(cols.size());
 
-        fieldsMap = new HashMap<>(cols.size());
-
         for (DbColumn col : cols) {
             String colName = col.name();
 
@@ -137,8 +129,6 @@ public class PojoDescriptor {
             fld.owner(this);
 
             flds.add(fld);
-
-            fieldsMap.put(colName, fld);
         }
 
         fields = FXCollections.observableList(flds);
@@ -308,64 +298,12 @@ public class PojoDescriptor {
     }
 
     /**
-     * @return Ascending fields.
-     */
-    public Collection<PojoField> ascendingFields() {
-        Collection<PojoField> res = new ArrayList<>();
-
-        Set<String> asc = tbl.ascendingColumns();
-
-        for (PojoField field : fields)
-            if (field.use() && asc.contains(field.dbName()))
-                res.add(field);
-
-        return res;
-    }
-
-    /**
-     * @return Descending fields.
-     */
-    public Collection<PojoField> descendingFields() {
-        Collection<PojoField> res = new ArrayList<>();
-
-        Set<String> desc = tbl.descendingColumns();
-
-        for (PojoField field : fields)
-            if (field.use() && desc.contains(field.dbName()))
-                res.add(field);
-
-        return res;
-    }
-
-    /**
-     * Gets indexes groups.
+     * Gets indexes indexes.
      *
-     * @return Map with indexes.
+     * @return Collection with indexes.
      */
-    public Map<String, Map<String, IndexItem>> groups() {
-        Map<String, Map<String, Boolean>> idxs = tbl.indexes();
-
-        Map<String, Map<String, IndexItem>> groups = new LinkedHashMap<>(idxs.size());
-
-        for (Map.Entry<String, Map<String, Boolean>> idx : idxs.entrySet()) {
-            Map<String, Boolean> idxCols = idx.getValue();
-
-            if (idxCols.size() > 1) {
-                String idxName = idx.getKey();
-
-                Map<String, IndexItem> grp = new LinkedHashMap<>();
-
-                groups.put(idxName, grp);
-
-                for (Map.Entry<String, Boolean> idxCol : idxCols.entrySet()) {
-                    PojoField fld = fieldsMap.get(idxCol.getKey());
-
-                    grp.put(fld.javaName(), new IndexItem(fld.javaTypeName(), idxCol.getValue()));
-                }
-            }
-        }
-
-        return groups;
+    public Collection<QueryIndex> indexes() {
+        return tbl.indexes();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/model/SchemaDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/SchemaDescriptor.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/model/SchemaDescriptor.java
index 1dc66f2..7de2247 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/model/SchemaDescriptor.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/model/SchemaDescriptor.java
@@ -55,8 +55,8 @@ public class SchemaDescriptor {
         return selected;
     }
 
-    @Override
-    public String toString() {
+    /** {@inheritDoc} */
+    @Override public String toString() {
         return schema;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
index 3ecee53..b68f90d 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DatabaseMetadataParser.java
@@ -30,6 +30,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.schema.model.PojoDescriptor;
 import org.apache.ignite.schema.model.SchemaDescriptor;
 import org.apache.ignite.schema.parser.dialect.DB2MetadataDialect;
@@ -59,7 +60,7 @@ public class DatabaseMetadataParser {
                 return new OracleMetadataDialect();
             else if (dbProductName.startsWith("DB2/"))
                 return new DB2MetadataDialect();
-            else if (dbProductName.equals("MySQL"))
+            else if ("MySQL".equals(dbProductName))
                 return new MySQLMetadataDialect();
             else
                 return new JdbcMetadataDialect();
@@ -76,7 +77,7 @@ public class DatabaseMetadataParser {
      *
      * @param conn Connection to database.
      * @return List of schema descriptors.
-     * @throws SQLException If shemas loading failed.
+     * @throws SQLException If schemas loading failed.
      */
     public static ObservableList<SchemaDescriptor> schemas(Connection conn) throws SQLException  {
         List<String> dbSchemas = dialect(conn).schemas(conn);
@@ -93,7 +94,7 @@ public class DatabaseMetadataParser {
      * Parse database metadata.
      *
      * @param conn Connection to database.
-     * @param schemas Collention of schema names to load.
+     * @param schemas Collection of schema names to load.
      * @param tblsOnly If {@code true} then process tables only else process tables and views.
      * @return Collection of POJO descriptors.
      * @throws SQLException If parsing failed.
@@ -114,8 +115,7 @@ public class DatabaseMetadataParser {
 
             if (parent == null) {
                 parent = new PojoDescriptor(null, new DbTable(schema, "", Collections.<DbColumn>emptyList(),
-                    Collections.<String>emptySet(), Collections.<String>emptySet(),
-                    Collections.<String, Map<String, Boolean>>emptyMap()));
+                    Collections.<QueryIndex>emptyList()));
 
                 children = new ArrayList<>();
 
@@ -148,4 +148,4 @@ public class DatabaseMetadataParser {
 
         return FXCollections.observableList(res);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java
index c54bfd8..39f6f7b 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/DbTable.java
@@ -17,9 +17,9 @@
 
 package org.apache.ignite.schema.parser;
 
+import org.apache.ignite.cache.QueryIndex;
+
 import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * Database table.
@@ -34,14 +34,8 @@ public class DbTable {
     /** Columns. */
     private final Collection<DbColumn> cols;
 
-    /** Columns in ascending order. */
-    private final Set<String> ascCols;
-
-    /** Columns in descending order. */
-    private final Set<String> descCols;
-
     /** Indexes. */
-    private final Map<String, Map<String, Boolean>> idxs;
+    private final Collection<QueryIndex> idxs;
 
     /**
      * Default columns.
@@ -49,17 +43,12 @@ public class DbTable {
      * @param schema Schema name.
      * @param tbl Table name.
      * @param cols Columns.
-     * @param ascCols Columns in ascending order.
-     * @param descCols Columns in descending order.
      * @param idxs Indexes;
      */
-    public DbTable(String schema, String tbl, Collection<DbColumn> cols, Set<String> ascCols, Set<String> descCols,
-        Map<String, Map<String, Boolean>> idxs) {
+    public DbTable(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex> idxs) {
         this.schema = schema;
         this.tbl = tbl;
         this.cols = cols;
-        this.ascCols = ascCols;
-        this.descCols = descCols;
         this.idxs = idxs;
     }
 
@@ -85,23 +74,9 @@ public class DbTable {
     }
 
     /**
-     * @return Fields in ascending order
-     */
-    public Set<String> ascendingColumns() {
-        return ascCols;
-    }
-
-    /**
-     * @return Fields in descending order
-     */
-    public Set<String> descendingColumns() {
-        return descCols;
-    }
-
-    /**
      * @return Indexes.
      */
-    public Map<String, Map<String, Boolean>> indexes() {
+    public Collection<QueryIndex> indexes() {
         return idxs;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java
index 5d3a0fd..bdf309b 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/DatabaseMetadataDialect.java
@@ -21,10 +21,10 @@ import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
+
+import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.schema.parser.DbColumn;
 import org.apache.ignite.schema.parser.DbTable;
 
@@ -45,7 +45,7 @@ public abstract class DatabaseMetadataDialect {
      * Gets tables from database.
      *
      * @param conn Database connection.
-     * @param schemas Collention of schema names to load.
+     * @param schemas Collection of schema names to load.
      * @param tblsOnly If {@code true} then gets only tables otherwise gets tables and views.
      * @return Collection of table descriptors.
      * @throws SQLException If failed to get tables.
@@ -69,27 +69,7 @@ public abstract class DatabaseMetadataDialect {
      * @param idxs Table indexes.
      * @return New {@code DbTable} instance.
      */
-    protected DbTable table(String schema, String tbl, Collection<DbColumn> cols, Map<String, Map<String, Boolean>>idxs) {
-        Set<String> ascCols = new HashSet<>();
-
-        Set<String> descCols = new HashSet<>();
-
-        for (Map<String, Boolean> idx : idxs.values()) {
-            if (idx.size() == 1)
-                for (Map.Entry<String, Boolean> idxCol : idx.entrySet()) {
-                    String colName = idxCol.getKey();
-
-                    Boolean desc = idxCol.getValue();
-
-                    if (desc != null) {
-                        if (desc)
-                            descCols.add(colName);
-                        else
-                            ascCols.add(colName);
-                    }
-                }
-        }
-
-        return new DbTable(schema, tbl, cols, ascCols, descCols, idxs);
+    protected DbTable table(String schema, String tbl, Collection<DbColumn> cols, Collection<QueryIndex>idxs) {
+        return new DbTable(schema, tbl, cols, idxs);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java
index 6f41195..45f0f9f 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/JdbcMetadataDialect.java
@@ -28,6 +28,9 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.schema.parser.DbColumn;
 import org.apache.ignite.schema.parser.DbTable;
 
@@ -115,7 +118,7 @@ public class JdbcMetadataDialect extends DatabaseMetadataDialect {
 
         Collection<DbTable> tbls = new ArrayList<>();
 
-        if (schemas.size() == 0)
+        if (schemas.isEmpty())
             schemas.add(null);
 
         for (String toSchema: schemas) {
@@ -154,7 +157,7 @@ public class JdbcMetadataDialect extends DatabaseMetadataDialect {
                         }
                     }
 
-                    Map<String, Map<String, Boolean>> idxs = new LinkedHashMap<>();
+                    Map<String, QueryIndex> idxs = new LinkedHashMap<>();
 
                     try (ResultSet idxRs = dbMeta.getIndexInfo(tblCatalog, tblSchema, tblName, false, true)) {
                         while (idxRs.next()) {
@@ -165,27 +168,30 @@ public class JdbcMetadataDialect extends DatabaseMetadataDialect {
                             if (idxName == null || colName == null)
                                 continue;
 
-                            Map<String, Boolean> idx = idxs.get(idxName);
+                            QueryIndex idx = idxs.get(idxName);
 
                             if (idx == null) {
-                                idx = new LinkedHashMap<>();
+                                idx = new QueryIndex();
+                                idx.setName(idxName);
+                                idx.setIndexType(QueryIndexType.SORTED);
+                                idx.setFields(new LinkedHashMap<String, Boolean>());
 
                                 idxs.put(idxName, idx);
                             }
 
                             String askOrDesc = idxRs.getString(IDX_ASC_OR_DESC_IDX);
 
-                            Boolean desc = askOrDesc != null ? "D".equals(askOrDesc) : null;
+                            Boolean asc = askOrDesc == null || "A".equals(askOrDesc);
 
-                            idx.put(colName, desc);
+                            idx.getFields().put(colName, asc);
                         }
                     }
 
-                    tbls.add(table(schema, tblName, cols, idxs));
+                    tbls.add(table(schema, tblName, cols, idxs.values()));
                 }
             }
         }
 
         return tbls;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
index cf7e979..0d4e8d6 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
@@ -31,6 +31,9 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.QueryIndexType;
 import org.apache.ignite.schema.parser.DbColumn;
 import org.apache.ignite.schema.parser.DbTable;
 
@@ -252,12 +255,12 @@ public class OracleMetadataDialect extends DatabaseMetadataDialect {
      * @param stmt Prepared SQL statement to execute.
      * @param owner DB owner.
      * @param tbl Table name.
-     * @return Index columns.
+     * @return Indexes.
      * @throws SQLException If failed to retrieve indexes columns.
      */
-    private Map<String, Map<String, Boolean>> indexes(PreparedStatement stmt, String owner, String tbl)
+    private Collection<QueryIndex> indexes(PreparedStatement stmt, String owner, String tbl)
         throws SQLException {
-        Map<String, Map<String, Boolean>> idxs = new LinkedHashMap<>();
+        Map<String, QueryIndex> idxs = new LinkedHashMap<>();
 
         stmt.setString(1, owner);
         stmt.setString(2, tbl);
@@ -266,10 +269,13 @@ public class OracleMetadataDialect extends DatabaseMetadataDialect {
             while (idxsRs.next()) {
                 String idxName = idxsRs.getString(IDX_NAME_IDX);
 
-                Map<String, Boolean> idx = idxs.get(idxName);
+                QueryIndex idx = idxs.get(idxName);
 
                 if (idx == null) {
-                    idx = new LinkedHashMap<>();
+                    idx = new QueryIndex();
+                    idx.setName(idxName);
+                    idx.setIndexType(QueryIndexType.SORTED);
+                    idx.setFields(new LinkedHashMap<String, Boolean>());
 
                     idxs.put(idxName, idx);
                 }
@@ -278,11 +284,11 @@ public class OracleMetadataDialect extends DatabaseMetadataDialect {
 
                 String col = expr == null ? idxsRs.getString(IDX_COL_NAME_IDX) : expr.replaceAll("\"", "");
 
-                idx.put(col, "DESC".equals(idxsRs.getString(IDX_COL_DESCEND_IDX)));
+                idx.getFields().put(col, !"DESC".equals(idxsRs.getString(IDX_COL_DESCEND_IDX)));
             }
         }
 
-        return idxs;
+        return idxs.values();
     }
 
     /** {@inheritDoc} */
@@ -294,7 +300,7 @@ public class OracleMetadataDialect extends DatabaseMetadataDialect {
 
         PreparedStatement idxStmt = conn.prepareStatement(SQL_INDEXES);
 
-        if (schemas.size() == 0)
+        if (schemas.isEmpty())
             schemas.add(null);
 
         Set<String> sysSchemas = systemSchemas();
@@ -307,7 +313,7 @@ public class OracleMetadataDialect extends DatabaseMetadataDialect {
                 Collection<DbColumn> cols = new ArrayList<>();
 
                 Set<String> pkCols = Collections.emptySet();
-                Map<String, Map<String, Boolean>> idxs = Collections.emptyMap();
+                Collection<QueryIndex> idxs = Collections.emptyList();
 
                 String sql = String.format(SQL_COLUMNS,
                         tblsOnly ? "INNER JOIN all_tables b on a.table_name = b.table_name and a.owner = b.owner" : "",

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
index 29c8a49..a1e34a1 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/ModalDialog.java
@@ -34,8 +34,8 @@ public abstract class ModalDialog extends Stage {
     protected ModalDialog(Stage owner, int width, int height) {
         this.owner = owner;
 
-        this.setWidth(width);
-        this.setHeight(height);
+        setWidth(width);
+        setHeight(height);
     }
 
     /**
@@ -47,4 +47,4 @@ public abstract class ModalDialog extends Stage {
 
         showAndWait();
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
index 4f419e6..495c316 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/SchemaImportApp.java
@@ -313,6 +313,7 @@ public class SchemaImportApp extends Application {
     /** */
     private ProgressIndicator pi;
 
+    /** */
     private ObservableList<SchemaDescriptor> schemas = FXCollections.emptyObservableList();
 
     /** List with POJOs descriptors. */
@@ -425,7 +426,7 @@ public class SchemaImportApp extends Application {
             if (schema.selected().getValue())
                 selSchemas.add(schema.schema());
 
-        if (selSchemas.size() == 0)
+        if (selSchemas.isEmpty())
             if (!MessageBox.confirmDialog(owner, "No schemas selected.\nExtract tables for all available schemas?"))
                 return;
 
@@ -944,8 +945,8 @@ public class SchemaImportApp extends Application {
         schemaPnl.wrap();
 
         schemaPnl.add(button("Load schemas", "Load schemas for specified database", new EventHandler<ActionEvent>() {
-            @Override
-            public void handle(ActionEvent evt) {
+            /** {@inheritDoc} */
+            @Override public void handle(ActionEvent evt) {
                 loadSchemas();
             }
         }));
@@ -1827,8 +1828,8 @@ public class SchemaImportApp extends Application {
      * Special list view cell to select loaded schemas.
      */
     private static class SchemaCell implements Callback<SchemaDescriptor, ObservableValue<Boolean>> {
-        @Override
-        public ObservableValue<Boolean> call(SchemaDescriptor item) {
+        /** {@inheritDoc} */
+        @Override public ObservableValue<Boolean> call(SchemaDescriptor item) {
             return item.selected();
         }
     }
@@ -1947,4 +1948,4 @@ public class SchemaImportApp extends Application {
             }
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
index 8c2b046..bf0f94a 100644
--- a/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
+++ b/modules/schema-import/src/test/java/org/apache/ignite/schema/test/AbstractSchemaImportTest.java
@@ -48,7 +48,7 @@ public abstract class AbstractSchemaImportTest extends TestCase {
     protected static final String OUT_DIR_PATH = System.getProperty("java.io.tmpdir") + "/ignite-schema-import/out";
 
     /** Auto confirmation of file conflicts. */
-    protected ConfirmCallable askOverwrite = new ConfirmCallable(null, "") {
+    protected final ConfirmCallable askOverwrite = new ConfirmCallable(null, "") {
         @Override public MessageBox.Result confirm(String msg) {
             return YES_TO_ALL;
         }
@@ -141,4 +141,4 @@ public abstract class AbstractSchemaImportTest extends TestCase {
             return false;
         }
     }
-}
\ No newline at end of file
+}


[4/4] ignite git commit: IGNITE-1753 Refactored usages of deprectaed CacheTypeMetadata to JdbcType.

Posted by ak...@apache.org.
IGNITE-1753 Refactored usages of deprectaed CacheTypeMetadata to JdbcType.


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

Branch: refs/heads/ignite-1.5
Commit: d71f6129bc737539e61206c391fc25c776f36242
Parents: 19d2dd0
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Nov 23 18:20:50 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Nov 23 18:20:50 2015 +0700

----------------------------------------------------------------------
 examples/schema-import/bin/db-init.sql          |   3 +-
 .../org/apache/ignite/schema/CacheConfig.java   |   7 +-
 .../java/org/apache/ignite/schema/Demo.java     |  20 +-
 .../org/apache/ignite/cache/QueryIndex.java     |  53 +-
 .../store/jdbc/CacheAbstractJdbcStore.java      | 638 ++++++++++++-------
 .../store/jdbc/CacheJdbcBlobStoreFactory.java   |  14 +-
 .../cache/store/jdbc/CacheJdbcPojoStore.java    | 444 +++++++++----
 .../store/jdbc/CacheJdbcPojoStoreFactory.java   | 277 +++++++-
 .../ignite/cache/store/jdbc/JdbcType.java       | 255 ++++++++
 .../cache/store/jdbc/JdbcTypeDefaultHasher.java |  43 ++
 .../ignite/cache/store/jdbc/JdbcTypeField.java  | 172 +++++
 .../ignite/cache/store/jdbc/JdbcTypeHasher.java |  34 +
 .../processors/query/GridQueryProcessor.java    |   6 +-
 .../ignite/internal/visor/cache/VisorCache.java |   4 +-
 .../CacheJdbcPojoStoreAbstractSelfTest.java     | 395 ++++++++++++
 ...dbcPojoStoreOptimizedMarshallerSelfTest.java |  31 +
 ...JdbcPojoStorePortableMarshallerSelfTest.java |  85 +++
 .../store/jdbc/CacheJdbcPojoStoreTest.java      | 200 +++---
 ...eJdbcStoreAbstractMultithreadedSelfTest.java |   2 +-
 .../ignite/testsuites/IgniteCacheTestSuite.java |   6 +-
 modules/schema-import/README.txt                | 176 ++---
 .../ignite/schema/generator/CodeGenerator.java  | 198 +++---
 .../ignite/schema/generator/XmlGenerator.java   | 101 +--
 .../apache/ignite/schema/model/IndexItem.java   |  54 --
 .../ignite/schema/model/PojoDescriptor.java     |  72 +--
 .../ignite/schema/model/SchemaDescriptor.java   |   6 +-
 .../schema/parser/DatabaseMetadataParser.java   |  12 +-
 .../apache/ignite/schema/parser/DbTable.java    |  37 +-
 .../parser/dialect/DatabaseMetadataDialect.java |  32 +-
 .../parser/dialect/JdbcMetadataDialect.java     |  22 +-
 .../parser/dialect/OracleMetadataDialect.java   |  24 +-
 .../apache/ignite/schema/ui/ModalDialog.java    |   6 +-
 .../ignite/schema/ui/SchemaImportApp.java       |  13 +-
 .../schema/test/AbstractSchemaImportTest.java   |   4 +-
 .../schema/test/model/ignite-type-metadata.xml  | 610 +++++++++---------
 .../yardstick/config/ignite-store-config.xml    |  50 +-
 36 files changed, 2844 insertions(+), 1262 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/examples/schema-import/bin/db-init.sql
----------------------------------------------------------------------
diff --git a/examples/schema-import/bin/db-init.sql b/examples/schema-import/bin/db-init.sql
index f02236a..8a91a6a 100644
--- a/examples/schema-import/bin/db-init.sql
+++ b/examples/schema-import/bin/db-init.sql
@@ -17,7 +17,8 @@
 
 -- Script of database initialization for Schema Import Demo.
 drop table PERSON;
-create table PERSON(id integer not null, first_name varchar(50), last_name varchar(50), salary double not null, PRIMARY KEY(id));
+
+create table PERSON(id integer not null PRIMARY KEY, first_name varchar(50), last_name varchar(50), salary double not null);
 
 insert into PERSON(id, first_name, last_name, salary) values(1, 'Johannes', 'Kepler', 1000);
 insert into PERSON(id, first_name, last_name, salary) values(2, 'Galileo', 'Galilei', 2000);

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/examples/schema-import/src/main/java/org/apache/ignite/schema/CacheConfig.java
----------------------------------------------------------------------
diff --git a/examples/schema-import/src/main/java/org/apache/ignite/schema/CacheConfig.java b/examples/schema-import/src/main/java/org/apache/ignite/schema/CacheConfig.java
index cb316c5..c5801cc 100644
--- a/examples/schema-import/src/main/java/org/apache/ignite/schema/CacheConfig.java
+++ b/examples/schema-import/src/main/java/org/apache/ignite/schema/CacheConfig.java
@@ -17,8 +17,7 @@
 
 package org.apache.ignite.schema;
 
-import javax.cache.configuration.Factory;
-import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
 import org.apache.ignite.configuration.CacheConfiguration;
 
 /**
@@ -31,7 +30,7 @@ public class CacheConfig {
      * @param name Cache name.
      * @param storeFactory Cache store factory.
      */
-    public static <K, V> CacheConfiguration<K, V> cache(String name, Factory<CacheStore<K, V>> storeFactory) {
+    public static <K, V> CacheConfiguration<K, V> cache(String name, CacheJdbcPojoStoreFactory<K, V> storeFactory) {
         throw new IllegalStateException("Please run Ignite Schema Import Utility as described in README.txt");
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/examples/schema-import/src/main/java/org/apache/ignite/schema/Demo.java
----------------------------------------------------------------------
diff --git a/examples/schema-import/src/main/java/org/apache/ignite/schema/Demo.java b/examples/schema-import/src/main/java/org/apache/ignite/schema/Demo.java
index cade7f1..a981f5a 100644
--- a/examples/schema-import/src/main/java/org/apache/ignite/schema/Demo.java
+++ b/examples/schema-import/src/main/java/org/apache/ignite/schema/Demo.java
@@ -18,13 +18,13 @@
 package org.apache.ignite.schema;
 
 import javax.cache.Cache;
-import javax.cache.configuration.Factory;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
-import org.apache.ignite.cache.store.CacheStore;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStore;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory;
+import org.apache.ignite.cache.store.jdbc.dialect.H2Dialect;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.transactions.Transaction;
 import org.h2.jdbcx.JdbcConnectionPool;
@@ -38,16 +38,14 @@ import org.h2.jdbcx.JdbcConnectionPool;
  */
 public class Demo {
     /**
-     * Constructs and returns a fully configured instance of a {@link CacheJdbcPojoStore}.
+     * Constructs and returns a fully configured instance of a {@link CacheJdbcPojoStoreFactory}.
      */
-    private static class H2DemoStoreFactory<K, V> implements Factory<CacheStore<K, V>> {
-        /** {@inheritDoc} */
-        @Override public CacheStore<K, V> create() {
-            CacheJdbcPojoStore<K, V> store = new CacheJdbcPojoStore<>();
+    private static class H2DemoStoreFactory<K, V> extends CacheJdbcPojoStoreFactory<K, V> {
+        /** Default constructor. */
+        H2DemoStoreFactory() {
+            setDialect(new H2Dialect());
 
-            store.setDataSource(JdbcConnectionPool.create("jdbc:h2:tcp://localhost/~/schema-import/demo", "sa", ""));
-
-            return store;
+            setDataSource(JdbcConnectionPool.create("jdbc:h2:tcp://localhost/~/schema-import/demo", "sa", ""));
         }
     }
 
@@ -144,4 +142,4 @@ public class Demo {
 
         System.out.println(">>> Updated person: " + cache.get(key));
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
index f12044d..af11999 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/QueryIndex.java
@@ -50,20 +50,33 @@ public class QueryIndex implements Serializable {
     /**
      * Creates single-field sorted ascending index.
      *
-     * @param name Field name.
+     * @param field Field name.
      */
-    public QueryIndex(String name) {
-        this(name, QueryIndexType.SORTED, true);
+    public QueryIndex(String field) {
+        this(field, QueryIndexType.SORTED, true);
     }
 
     /**
      * Creates single-field sorted index.
      *
-     * @param name Field name.
+     * @param field Field name.
      * @param asc Ascending flag.
      */
-    public QueryIndex(String name, boolean asc) {
-        this(name, QueryIndexType.SORTED, asc);
+    public QueryIndex(String field, boolean asc) {
+        this(field, QueryIndexType.SORTED, asc);
+    }
+
+    /**
+     * Creates single-field sorted index.
+     *
+     * @param field Field name.
+     * @param asc Ascending flag.
+     * @param name Index name.
+     */
+    public QueryIndex(String field, boolean asc, String name) {
+        this(field, QueryIndexType.SORTED, asc);
+
+        this.name = name;
     }
 
     /**
@@ -71,14 +84,20 @@ public class QueryIndex implements Serializable {
      * If index is sorted, then ascending sorting is used by default.
      * To specify sort order, use the next method.
      * This constructor should also have a corresponding setter method.
+     *
+     * @param field Field name.
+     * @param type Index type.
      */
     public QueryIndex(String field, QueryIndexType type) {
         this(Arrays.asList(field), type);
     }
 
     /**
-     * Creates index for one field. The last boolean parameter
-     * is ignored for non-sorted indexes.
+     * Creates index for one field. The last boolean parameter is ignored for non-sorted indexes.
+     *
+     * @param field Field name.
+     * @param type Index type.
+     * @param asc Ascending flag.
      */
     public QueryIndex(String field, QueryIndexType type, boolean asc) {
         fields = new LinkedHashMap<>();
@@ -88,6 +107,22 @@ public class QueryIndex implements Serializable {
     }
 
     /**
+     * Creates index for one field. The last boolean parameter is ignored for non-sorted indexes.
+     *
+     * @param field Field name.
+     * @param type Index type.
+     * @param asc Ascending flag.
+     * @param name Index name.
+     */
+    public QueryIndex(String field, QueryIndexType type, boolean asc, String name) {
+        fields = new LinkedHashMap<>();
+        fields.put(field, asc);
+
+        this.type = type;
+        this.name = name;
+    }
+
+    /**
      * Creates index for a collection of fields. If index is sorted, fields will be sorted in
      * ascending order.
      *
@@ -189,4 +224,4 @@ public class QueryIndex implements Serializable {
     public void setIndexType(QueryIndexType type) {
         this.type = type;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
index 6e19234..6dc413b 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
@@ -30,6 +30,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.Callable;
@@ -66,6 +68,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiInClosure;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.marshaller.portable.BinaryMarshaller;
 import org.apache.ignite.resources.CacheStoreSessionResource;
 import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.resources.LoggerResource;
@@ -75,6 +78,10 @@ import org.jetbrains.annotations.Nullable;
 import static java.sql.Statement.EXECUTE_FAILED;
 import static java.sql.Statement.SUCCESS_NO_INFO;
 
+import static org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory.DFLT_BATCH_SIZE;
+import static org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory.DFLT_WRITE_ATTEMPTS;
+import static org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory.DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD;
+
 /**
  * Implementation of {@link CacheStore} backed by JDBC.
  * <p>
@@ -99,35 +106,43 @@ import static java.sql.Statement.SUCCESS_NO_INFO;
  * <h2 class="header">Java Example</h2>
  * <pre name="code" class="java">
  *    ...
- *    CacheConfiguration ccfg = new CacheConfiguration&lt;&gt;();
- *
- *    // Configure cache store.
- *    ccfg.setCacheStoreFactory(new FactoryBuilder.SingletonFactory(ConfigurationSnippet.store()));
+ *    // Create store factory.
+ *    CacheJdbcPojoStoreFactory storeFactory = new CacheJdbcPojoStoreFactory();
+ *    storeFactory.setDataSourceBean("your_data_source_name");
+ *    storeFactory.setDialect(new H2Dialect());
+ *    storeFactory.setTypes(array_with_your_types);
+ *    ...
+ *    ccfg.setCacheStoreFactory(storeFactory);
  *    ccfg.setReadThrough(true);
  *    ccfg.setWriteThrough(true);
  *
- *    // Configure cache types metadata.
- *    ccfg.setTypeMetadata(ConfigurationSnippet.typeMetadata());
- *
  *    cfg.setCacheConfiguration(ccfg);
  *    ...
  * </pre>
  */
 public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>, LifecycleAware {
-    /** Max attempt write count. */
-    protected static final int MAX_ATTEMPT_WRITE_COUNT = 2;
-
-    /** Default batch size for put and remove operations. */
-    protected static final int DFLT_BATCH_SIZE = 512;
-
-    /** Default batch size for put and remove operations. */
-    protected static final int DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD = 512;
-
     /** Connection attribute property name. */
     protected static final String ATTR_CONN_PROP = "JDBC_STORE_CONNECTION";
 
-    /** Empty column value. */
-    protected static final Object[] EMPTY_COLUMN_VALUE = new Object[] { null };
+    /** Built in Java types names. */
+    protected static final Collection<String> BUILT_IN_TYPES = new HashSet<>();
+
+    static {
+        BUILT_IN_TYPES.add("java.math.BigDecimal");
+        BUILT_IN_TYPES.add("java.lang.Boolean");
+        BUILT_IN_TYPES.add("java.lang.Byte");
+        BUILT_IN_TYPES.add("java.lang.Character");
+        BUILT_IN_TYPES.add("java.lang.Double");
+        BUILT_IN_TYPES.add("java.util.Date");
+        BUILT_IN_TYPES.add("java.sql.Date");
+        BUILT_IN_TYPES.add("java.lang.Float");
+        BUILT_IN_TYPES.add("java.lang.Integer");
+        BUILT_IN_TYPES.add("java.lang.Long");
+        BUILT_IN_TYPES.add("java.lang.Short");
+        BUILT_IN_TYPES.add("java.lang.String");
+        BUILT_IN_TYPES.add("java.sql.Timestamp");
+        BUILT_IN_TYPES.add("java.util.UUID");
+    }
 
     /** Auto-injected store session. */
     @CacheStoreSessionResource
@@ -135,7 +150,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
     /** Auto injected ignite instance. */
     @IgniteInstanceResource
-    private Ignite ignite;
+    protected Ignite ignite;
 
     /** Auto-injected logger instance. */
     @LoggerResource
@@ -151,30 +166,40 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     /** Cache with entry mapping description. (cache name, (key id, mapping description)). */
     protected volatile Map<String, Map<Object, EntryMapping>> cacheMappings = Collections.emptyMap();
 
+    /** Maximum batch size for writeAll and deleteAll operations. */
+    private int batchSize = DFLT_BATCH_SIZE;
+
     /** Database dialect. */
     protected JdbcDialect dialect;
 
-    /** Max workers thread count. These threads are responsible for load cache. */
-    private int maxPoolSz = Runtime.getRuntime().availableProcessors();
+    /** Maximum write attempts in case of database error. */
+    private int maxWrtAttempts = DFLT_WRITE_ATTEMPTS;
 
-    /** Maximum batch size for writeAll and deleteAll operations. */
-    private int batchSz = DFLT_BATCH_SIZE;
+    /** Max workers thread count. These threads are responsible for load cache. */
+    private int maxPoolSize = Runtime.getRuntime().availableProcessors();
 
     /** Parallel load cache minimum threshold. If {@code 0} then load sequentially. */
     private int parallelLoadCacheMinThreshold = DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD;
 
+    /** Types that store could process. */
+    private JdbcType[] types;
+
+    /** Hash calculator.  */
+    protected JdbcTypeHasher hasher = JdbcTypeDefaultHasher.INSTANCE;
+
     /**
      * Get field value from object for use as query parameter.
      *
      * @param cacheName Cache name.
      * @param typeName Type name.
+     * @param typeKind Type kind.
      * @param fieldName Field name.
      * @param obj Cache object.
      * @return Field value from object.
      * @throws CacheException in case of error.
      */
-    @Nullable protected abstract Object extractParameter(@Nullable String cacheName, String typeName, String fieldName,
-        Object obj) throws CacheException;
+    @Nullable protected abstract Object extractParameter(@Nullable String cacheName, String typeName, TypeKind typeKind,
+        String fieldName, Object obj) throws CacheException;
 
     /**
      * Construct object from query result.
@@ -182,33 +207,36 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * @param <R> Type of result object.
      * @param cacheName Cache name.
      * @param typeName Type name.
-     * @param fields Fields descriptors.
+     * @param typeKind Type kind.
+     * @param flds Fields descriptors.
+     * @param hashFlds Field names for hash code calculation.
      * @param loadColIdxs Select query columns index.
      * @param rs ResultSet.
      * @return Constructed object.
      * @throws CacheLoaderException If failed to construct cache object.
      */
-    protected abstract <R> R buildObject(@Nullable String cacheName, String typeName,
-        Collection<CacheTypeFieldMetadata> fields, Map<String, Integer> loadColIdxs, ResultSet rs)
+    protected abstract <R> R buildObject(@Nullable String cacheName, String typeName, TypeKind typeKind,
+        JdbcTypeField[] flds, Collection<String> hashFlds, Map<String, Integer> loadColIdxs, ResultSet rs)
         throws CacheLoaderException;
 
     /**
-     * Extract key type id from key object.
+     * Calculate type ID for object.
      *
-     * @param key Key object.
-     * @return Key type id.
-     * @throws CacheException If failed to get type key id from object.
+     * @param obj Object to calculate type ID for.
+     * @return Type ID.
+     * @throws CacheException If failed to calculate type ID for given object.
      */
-    protected abstract Object keyTypeId(Object key) throws CacheException;
+    protected abstract Object typeIdForObject(Object obj) throws CacheException;
 
     /**
-     * Extract key type id from key class name.
+     * Calculate type ID for given type name.
      *
-     * @param type String description of key type.
-     * @return Key type id.
-     * @throws CacheException If failed to get type key id from object.
+     * @param kind If {@code true} then calculate type ID for POJO otherwise for binary object .
+     * @param typeName String description of type name.
+     * @return Type ID.
+     * @throws CacheException If failed to get type ID for given type name.
      */
-    protected abstract Object keyTypeId(String type) throws CacheException;
+    protected abstract Object typeIdForTypeName(TypeKind kind, String typeName) throws CacheException;
 
     /**
      * Prepare internal store specific builders for provided types metadata.
@@ -217,7 +245,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * @param types Collection of types.
      * @throws CacheException If failed to prepare internal builders for types.
      */
-    protected abstract void prepareBuilders(@Nullable String cacheName, Collection<CacheTypeMetadata> types)
+    protected abstract void prepareBuilders(@Nullable String cacheName, Collection<JdbcType> types)
         throws CacheException;
 
     /**
@@ -480,23 +508,23 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                         ? em.loadCacheQry
                         : em.loadCacheRangeQuery(lowerBound != null, upperBound != null));
 
-                    int ix = 1;
+                    int idx = 1;
 
                     if (lowerBound != null)
                         for (int i = lowerBound.length; i > 0; i--)
                             for (int j = 0; j < i; j++)
-                                stmt.setObject(ix++, lowerBound[j]);
+                                stmt.setObject(idx++, lowerBound[j]);
 
                     if (upperBound != null)
                         for (int i = upperBound.length; i > 0; i--)
                             for (int j = 0; j < i; j++)
-                                stmt.setObject(ix++, upperBound[j]);
+                                stmt.setObject(idx++, upperBound[j]);
 
                     ResultSet rs = stmt.executeQuery();
 
                     while (rs.next()) {
-                        K key = buildObject(em.cacheName, em.keyType(), em.keyColumns(), em.loadColIdxs, rs);
-                        V val = buildObject(em.cacheName, em.valueType(), em.valueColumns(), em.loadColIdxs, rs);
+                        K key = buildObject(em.cacheName, em.keyType(), em.keyKind(), em.keyColumns(), em.keyCols, em.loadColIdxs, rs);
+                        V val = buildObject(em.cacheName, em.valueType(), em.valueKind(), em.valueColumns(), null, em.loadColIdxs, rs);
 
                         clo.apply(key, val);
                     }
@@ -527,58 +555,86 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     }
 
     /**
-     * Object is a simple type.
+     * Checks if type configured properly.
      *
-     * @param cls Class.
-     * @return {@code True} if object is a simple type.
-     */
-    protected static boolean simpleType(Class<?> cls) {
-        return (Number.class.isAssignableFrom(cls) || String.class.isAssignableFrom(cls) ||
-            java.util.Date.class.isAssignableFrom(cls) || Boolean.class.isAssignableFrom(cls) ||
-            UUID.class.isAssignableFrom(cls));
-    }
-
-    /**
      * @param cacheName Cache name to check mapping for.
-     * @param clsName Class name.
-     * @param fields Fields descriptors.
-     * @throws CacheException If failed to check type metadata.
+     * @param typeName Type name.
+     * @param flds Fields descriptors.
+     * @throws CacheException If failed to check type configuration.
      */
-    private static void checkMapping(@Nullable String cacheName, String clsName,
-        Collection<CacheTypeFieldMetadata> fields) throws CacheException {
+    private void checkTypeConfiguration(@Nullable String cacheName, TypeKind kind, String typeName,
+        JdbcTypeField[] flds) throws CacheException {
         try {
-            Class<?> cls = Class.forName(clsName);
-
-            if (simpleType(cls)) {
-                if (fields.size() != 1)
-                    throw new CacheException("More than one field for simple type [cache name=" + cacheName
-                        + ", type=" + clsName + " ]");
+            if (kind == TypeKind.BUILT_IN) {
+                if (flds.length != 1)
+                    throw new CacheException("More than one field for built in type [cache=" +  U.maskName(cacheName) +
+                        ", type=" + typeName + " ]");
 
-                CacheTypeFieldMetadata field = F.first(fields);
+                JdbcTypeField field = flds[0];
 
-                if (field.getDatabaseName() == null)
-                    throw new CacheException("Missing database name in mapping description [cache name=" + cacheName
-                        + ", type=" + clsName + " ]");
+                if (field.getDatabaseFieldName() == null)
+                    throw new CacheException("Missing database name in mapping description [cache=" +
+                        U.maskName(cacheName) + ", type=" + typeName + " ]");
 
-                field.setJavaType(cls);
+                field.setJavaFieldType(Class.forName(typeName));
             }
             else
-                for (CacheTypeFieldMetadata field : fields) {
-                    if (field.getDatabaseName() == null)
-                        throw new CacheException("Missing database name in mapping description [cache name=" + cacheName
-                            + ", type=" + clsName + " ]");
-
-                    if (field.getJavaName() == null)
-                        throw new CacheException("Missing field name in mapping description [cache name=" + cacheName
-                            + ", type=" + clsName + " ]");
-
-                    if (field.getJavaType() == null)
-                        throw new CacheException("Missing field type in mapping description [cache name=" + cacheName
-                            + ", type=" + clsName + " ]");
+                for (JdbcTypeField field : flds) {
+                    if (field.getDatabaseFieldName() == null)
+                        throw new CacheException("Missing database name in mapping description [cache=" +
+                            U.maskName(cacheName) + ", type=" + typeName + " ]");
+
+                    if (field.getJavaFieldName() == null)
+                        throw new CacheException("Missing field name in mapping description [cache=" +
+                            U.maskName(cacheName) + ", type=" + typeName + " ]");
+
+                    if (field.getJavaFieldType() == null)
+                        throw new CacheException("Missing field type in mapping description [cache=" +
+                            U.maskName(cacheName) + ", type=" + typeName + " ]");
                 }
         }
         catch (ClassNotFoundException e) {
-            throw new CacheException("Failed to find class: " + clsName, e);
+            throw new CacheException("Failed to find class: " + typeName, e);
+        }
+    }
+
+    /**
+     * For backward compatibility translate old field type descriptors to new format.
+     *
+     * @param oldFlds Fields in old format.
+     * @return Fields in new format.
+     */
+    @Deprecated
+    private JdbcTypeField[] translateFields(Collection<CacheTypeFieldMetadata> oldFlds) {
+        JdbcTypeField[] newFlds = new JdbcTypeField[oldFlds.size()];
+
+        int idx = 0;
+
+        for (CacheTypeFieldMetadata oldField : oldFlds) {
+            newFlds[idx] = new JdbcTypeField(oldField.getDatabaseType(), oldField.getDatabaseName(),
+                oldField.getJavaType(), oldField.getJavaName());
+
+            idx++;
+        }
+
+        return newFlds;
+    }
+
+    /**
+     * @param type Type name to check.
+     * @return {@code True} if class not found.
+     */
+    protected TypeKind kindForName(String type) {
+        if (BUILT_IN_TYPES.contains(type))
+            return TypeKind.BUILT_IN;
+
+        try {
+            Class.forName(type);
+
+            return TypeKind.POJO;
+        }
+        catch(ClassNotFoundException ignored) {
+            return TypeKind.BINARY;
         }
     }
 
@@ -587,46 +643,104 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * @return Type mappings for specified cache name.
      * @throws CacheException If failed to initialize cache mappings.
      */
-    private Map<Object, EntryMapping> cacheMappings(@Nullable String cacheName) throws CacheException {
+    private Map<Object, EntryMapping> getOrCreateCacheMappings(@Nullable String cacheName) throws CacheException {
         Map<Object, EntryMapping> entryMappings = cacheMappings.get(cacheName);
 
         if (entryMappings != null)
             return entryMappings;
 
         cacheMappingsLock.lock();
-
         try {
             entryMappings = cacheMappings.get(cacheName);
 
             if (entryMappings != null)
                 return entryMappings;
 
-            CacheConfiguration ccfg = ignite().cache(cacheName).getConfiguration(CacheConfiguration.class);
+            // If no types configured, check CacheTypeMetadata for backward compatibility.
+            if (types == null) {
+                CacheConfiguration ccfg = ignite.cache(cacheName).getConfiguration(CacheConfiguration.class);
+
+                Collection<CacheTypeMetadata> oldTypes = ccfg.getTypeMetadata();
+
+                types = new JdbcType[oldTypes.size()];
+
+                int idx = 0;
+
+                for (CacheTypeMetadata oldType : oldTypes) {
+                    JdbcType newType = new JdbcType();
 
-            Collection<CacheTypeMetadata> types = ccfg.getTypeMetadata();
+                    newType.setCacheName(cacheName);
 
-            entryMappings = U.newHashMap(types.size());
+                    newType.setDatabaseSchema(oldType.getDatabaseSchema());
+                    newType.setDatabaseTable(oldType.getDatabaseTable());
 
-            for (CacheTypeMetadata type : types) {
-                Object keyTypeId = keyTypeId(type.getKeyType());
+                    newType.setKeyType(oldType.getKeyType());
+                    newType.setKeyFields(translateFields(oldType.getKeyFields()));
 
-                if (entryMappings.containsKey(keyTypeId))
-                    throw new CacheException("Key type must be unique in type metadata [cache name=" + cacheName +
-                        ", key type=" + type.getKeyType() + "]");
+                    newType.setValueType(oldType.getValueType());
+                    newType.setValueFields(translateFields(oldType.getValueFields()));
 
-                checkMapping(cacheName, type.getKeyType(), type.getKeyFields());
-                checkMapping(cacheName, type.getValueType(), type.getValueFields());
+                    types[idx] = newType;
 
-                entryMappings.put(keyTypeId(type.getKeyType()), new EntryMapping(cacheName, dialect, type));
+                    idx++;
+                }
             }
 
-            Map<String, Map<Object, EntryMapping>> mappings = new HashMap<>(cacheMappings);
+            List<JdbcType> cacheTypes = new ArrayList<>(types.length);
+
+            for (JdbcType type : types)
+                if ((cacheName != null && cacheName.equals(type.getCacheName())) ||
+                    (cacheName == null && type.getCacheName() == null))
+                    cacheTypes.add(type);
+
+            entryMappings = U.newHashMap(cacheTypes.size());
+
+            if (!cacheTypes.isEmpty()) {
+                boolean binarySupported = ignite.configuration().getMarshaller() instanceof BinaryMarshaller;
+
+                for (JdbcType type : cacheTypes) {
+                    String keyType = type.getKeyType();
+                    String valType = type.getValueType();
+
+                    TypeKind keyKind = kindForName(keyType);
+
+                    if (!binarySupported && keyKind == TypeKind.BINARY)
+                        throw new CacheException("Key type has no class [cache=" + U.maskName(cacheName) +
+                            ", type=" + keyType + "]");
+
+                    checkTypeConfiguration(cacheName, keyKind, keyType, type.getKeyFields());
+
+                    Object keyTypeId = typeIdForTypeName(keyKind, keyType);
 
-            mappings.put(cacheName, entryMappings);
+                    if (entryMappings.containsKey(keyTypeId))
+                        throw new CacheException("Key type must be unique in type metadata [cache=" +
+                            U.maskName(cacheName) + ", type=" + keyType + "]");
 
-            prepareBuilders(cacheName, types);
+                    TypeKind valKind = kindForName(valType);
 
-            cacheMappings = mappings;
+                    checkTypeConfiguration(cacheName, valKind, valType, type.getValueFields());
+
+                    entryMappings.put(keyTypeId, new EntryMapping(cacheName, dialect, type, keyKind, valKind));
+
+                    // Add one more binding to binary typeId for POJOs,
+                    // because object could be passed to store in binary format.
+                    if (binarySupported && keyKind == TypeKind.POJO) {
+                        keyTypeId = typeIdForTypeName(TypeKind.BINARY, keyType);
+
+                        valKind = valKind == TypeKind.POJO ? TypeKind.BINARY : valKind;
+
+                        entryMappings.put(keyTypeId, new EntryMapping(cacheName, dialect, type, TypeKind.BINARY, valKind));
+                    }
+                }
+
+                Map<String, Map<Object, EntryMapping>> mappings = new HashMap<>(cacheMappings);
+
+                mappings.put(cacheName, entryMappings);
+
+                prepareBuilders(cacheName, cacheTypes);
+
+                cacheMappings = mappings;
+            }
 
             return entryMappings;
         }
@@ -637,19 +751,21 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
     /**
      * @param cacheName Cache name.
-     * @param keyTypeId Key type id.
-     * @param key Key object.
+     * @param typeId Type id.
      * @return Entry mapping.
      * @throws CacheException If mapping for key was not found.
      */
-    private EntryMapping entryMapping(String cacheName, Object keyTypeId, Object key) throws CacheException {
-        EntryMapping em = cacheMappings(cacheName).get(keyTypeId);
+    private EntryMapping entryMapping(String cacheName, Object typeId) throws CacheException {
+        Map<Object, EntryMapping> mappings = getOrCreateCacheMappings(cacheName);
+
+        EntryMapping em = mappings.get(typeId);
 
         if (em == null) {
             String maskedCacheName = U.maskName(cacheName);
 
-            throw new CacheException("Failed to find mapping description [key=" + key +
-                ", cache=" + maskedCacheName + "]. Please configure CacheTypeMetadata to associate '" + maskedCacheName + "' with JdbcPojoStore.");
+            throw new CacheException("Failed to find mapping description [cache=" + maskedCacheName +
+                ", typeId=" + typeId + "]. Please configure JdbcType to associate cache '" + maskedCacheName +
+                "' with JdbcPojoStore.");
         }
 
         return em;
@@ -663,34 +779,37 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         String cacheName = session().cacheName();
 
         try {
-            pool = Executors.newFixedThreadPool(maxPoolSz);
+            pool = Executors.newFixedThreadPool(maxPoolSize);
 
             Collection<Future<?>> futs = new ArrayList<>();
 
+            Map<Object, EntryMapping> mappings = getOrCreateCacheMappings(cacheName);
+
             if (args != null && args.length > 0) {
                 if (args.length % 2 != 0)
                     throw new CacheLoaderException("Expected even number of arguments, but found: " + args.length);
 
                 if (log.isDebugEnabled())
-                    log.debug("Start loading entries from db using user queries from arguments");
+                    log.debug("Start loading entries from db using user queries from arguments...");
 
                 for (int i = 0; i < args.length; i += 2) {
                     String keyType = args[i].toString();
 
                     String selQry = args[i + 1].toString();
 
-                    EntryMapping em = entryMapping(cacheName, keyTypeId(keyType), keyType);
+                    EntryMapping em = entryMapping(cacheName, typeIdForTypeName(kindForName(keyType), keyType));
 
                     futs.add(pool.submit(new LoadCacheCustomQueryWorker<>(em, selQry, clo)));
                 }
             }
             else {
-                Collection<EntryMapping> entryMappings = cacheMappings(session().cacheName()).values();
+                Collection<EntryMapping> entryMappings = mappings.values();
 
                 for (EntryMapping em : entryMappings) {
                     if (parallelLoadCacheMinThreshold > 0) {
-                        log.debug("Multithread loading entries from db [cache name=" + cacheName +
-                            ", key type=" + em.keyType() + " ]");
+                        if (log.isDebugEnabled())
+                            log.debug("Multithread loading entries from db [cache=" +  U.maskName(cacheName) +
+                                ", keyType=" + em.keyType() + " ]");
 
                         Connection conn = null;
 
@@ -738,8 +857,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                     }
                     else {
                         if (log.isDebugEnabled())
-                            log.debug("Single thread loading entries from db [cache name=" + cacheName +
-                                ", key type=" + em.keyType() + " ]");
+                            log.debug("Single thread loading entries from db [cache=" +  U.maskName(cacheName) +
+                                ", keyType=" + em.keyType() + " ]");
 
                         futs.add(pool.submit(loadCacheFull(em, clo)));
                     }
@@ -750,10 +869,10 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 U.get(fut);
 
             if (log.isDebugEnabled())
-                log.debug("Cache loaded from db: " + cacheName);
+                log.debug("Cache loaded from db: " +  U.maskName(cacheName));
         }
         catch (IgniteCheckedException e) {
-            throw new CacheLoaderException("Failed to load cache: " + cacheName, e.getCause());
+            throw new CacheLoaderException("Failed to load cache: " + U.maskName(cacheName), e.getCause());
         }
         finally {
             U.shutdownNow(getClass(), pool, log);
@@ -764,7 +883,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     @Nullable @Override public V load(K key) throws CacheLoaderException {
         assert key != null;
 
-        EntryMapping em = entryMapping(session().cacheName(), keyTypeId(key), key);
+        EntryMapping em = entryMapping(session().cacheName(), typeIdForObject(key));
 
         if (log.isDebugEnabled())
             log.debug("Load value from db [table= " + em.fullTableName() + ", key=" + key + "]");
@@ -783,7 +902,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
             ResultSet rs = stmt.executeQuery();
 
             if (rs.next())
-                return buildObject(em.cacheName, em.valueType(), em.valueColumns(), em.loadColIdxs, rs);
+                return buildObject(em.cacheName, em.valueType(), em.valueKind(), em.valueColumns(), null, em.loadColIdxs, rs);
         }
         catch (SQLException e) {
             throw new CacheLoaderException("Failed to load object [table=" + em.fullTableName() +
@@ -807,14 +926,14 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
             String cacheName = session().cacheName();
 
-            Map<Object, LoadWorker<K, V>> workers = U.newHashMap(cacheMappings(cacheName).size());
+            Map<Object, LoadWorker<K, V>> workers = U.newHashMap(getOrCreateCacheMappings(cacheName).size());
 
             Map<K, V> res = new HashMap<>();
 
             for (K key : keys) {
-                Object keyTypeId = keyTypeId(key);
+                Object keyTypeId = typeIdForObject(key);
 
-                EntryMapping em = entryMapping(cacheName, keyTypeId, key);
+                EntryMapping em = entryMapping(cacheName, keyTypeId);
 
                 LoadWorker<K, V> worker = workers.get(keyTypeId);
 
@@ -852,7 +971,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         try {
             CacheWriterException we = null;
 
-            for (int attempt = 0; attempt < MAX_ATTEMPT_WRITE_COUNT; attempt++) {
+            for (int attempt = 0; attempt < maxWrtAttempts; attempt++) {
                 int paramIdx = fillValueParameters(updStmt, 1, em, entry.getValue());
 
                 fillKeyParameters(updStmt, paramIdx, em, entry.getKey());
@@ -921,7 +1040,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
         K key = entry.getKey();
 
-        EntryMapping em = entryMapping(session().cacheName(), keyTypeId(key), key);
+        EntryMapping em = entryMapping(session().cacheName(), typeIdForObject(key));
 
         if (log.isDebugEnabled())
             log.debug("Start write entry to database [table=" + em.fullTableName() + ", entry=" + entry + "]");
@@ -937,9 +1056,9 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 try {
                     stmt = conn.prepareStatement(em.mergeQry);
 
-                    int i = fillKeyParameters(stmt, em, key);
+                    int idx = fillKeyParameters(stmt, em, key);
 
-                    fillValueParameters(stmt, i, em, entry.getValue());
+                    fillValueParameters(stmt, idx, em, entry.getValue());
 
                     int updCnt = stmt.executeUpdate();
 
@@ -1010,15 +1129,15 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                     for (Cache.Entry<? extends K, ? extends V> entry : entries) {
                         K key = entry.getKey();
 
-                        Object keyTypeId = keyTypeId(key);
+                        Object keyTypeId = typeIdForObject(key);
 
-                        em = entryMapping(cacheName, keyTypeId, key);
+                        em = entryMapping(cacheName, keyTypeId);
 
                         if (currKeyTypeId == null || !currKeyTypeId.equals(keyTypeId)) {
                             if (mergeStmt != null) {
                                 if (log.isDebugEnabled())
-                                    log.debug("Write entries to db [cache name=" + cacheName +
-                                        ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                                    log.debug("Write entries to db [cache=" +  U.maskName(cacheName) +
+                                        ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                                 executeBatch(em, mergeStmt, "writeAll", fromIdx, prepared, lazyEntries);
 
@@ -1034,16 +1153,16 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                             prepared = 0;
                         }
 
-                        int i = fillKeyParameters(mergeStmt, em, key);
+                        int idx = fillKeyParameters(mergeStmt, em, key);
 
-                        fillValueParameters(mergeStmt, i, em, entry.getValue());
+                        fillValueParameters(mergeStmt, idx, em, entry.getValue());
 
                         mergeStmt.addBatch();
 
-                        if (++prepared % batchSz == 0) {
+                        if (++prepared % batchSize == 0) {
                             if (log.isDebugEnabled())
-                                log.debug("Write entries to db [cache name=" + cacheName +
-                                    ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                                log.debug("Write entries to db [cache=" +  U.maskName(cacheName) +
+                                    ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                             executeBatch(em, mergeStmt, "writeAll", fromIdx, prepared, lazyEntries);
 
@@ -1053,10 +1172,10 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                         }
                     }
 
-                    if (mergeStmt != null && prepared % batchSz != 0) {
+                    if (mergeStmt != null && prepared % batchSize != 0) {
                         if (log.isDebugEnabled())
-                            log.debug("Write entries to db [cache name=" + cacheName +
-                                ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                            log.debug("Write entries to db [cache=" +  U.maskName(cacheName) +
+                                ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                         executeBatch(em, mergeStmt, "writeAll", fromIdx, prepared, lazyEntries);
 
@@ -1067,8 +1186,9 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 }
             }
             else {
-                log.debug("Write entries to db one by one using update and insert statements [cache name=" +
-                    cacheName + ", count=" + entries.size() + "]");
+                if (log.isDebugEnabled())
+                    log.debug("Write entries to db one by one using update and insert statements [cache=" +
+                        U.maskName(cacheName) + ", cnt=" + entries.size() + "]");
 
                 PreparedStatement insStmt = null;
 
@@ -1078,9 +1198,9 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                     for (Cache.Entry<? extends K, ? extends V> entry : entries) {
                         K key = entry.getKey();
 
-                        Object keyTypeId = keyTypeId(key);
+                        Object keyTypeId = typeIdForObject(key);
 
-                        EntryMapping em = entryMapping(cacheName, keyTypeId, key);
+                        EntryMapping em = entryMapping(cacheName, keyTypeId);
 
                         if (currKeyTypeId == null || !currKeyTypeId.equals(keyTypeId)) {
                             U.closeQuiet(insStmt);
@@ -1116,7 +1236,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     @Override public void delete(Object key) throws CacheWriterException {
         assert key != null;
 
-        EntryMapping em = entryMapping(session().cacheName(), keyTypeId(key), key);
+        EntryMapping em = entryMapping(session().cacheName(), typeIdForObject(key));
 
         if (log.isDebugEnabled())
             log.debug("Remove value from db [table=" + em.fullTableName() + ", key=" + key + "]");
@@ -1220,9 +1340,9 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
             int fromIdx = 0, prepared = 0;
 
             for (Object key : keys) {
-                Object keyTypeId = keyTypeId(key);
+                Object keyTypeId = typeIdForObject(key);
 
-                em = entryMapping(cacheName, keyTypeId, key);
+                em = entryMapping(cacheName, keyTypeId);
 
                 if (delStmt == null) {
                     delStmt = conn.prepareStatement(em.remQry);
@@ -1232,8 +1352,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
                 if (!currKeyTypeId.equals(keyTypeId)) {
                     if (log.isDebugEnabled())
-                        log.debug("Delete entries from db [cache name=" + cacheName +
-                            ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                        log.debug("Delete entries from db [cache=" +  U.maskName(cacheName) +
+                            ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                     executeBatch(em, delStmt, "deleteAll", fromIdx, prepared, lazyKeys);
 
@@ -1248,10 +1368,10 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
                 delStmt.addBatch();
 
-                if (++prepared % batchSz == 0) {
+                if (++prepared % batchSize == 0) {
                     if (log.isDebugEnabled())
-                        log.debug("Delete entries from db [cache name=" + cacheName +
-                            ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                        log.debug("Delete entries from db [cache=" +  U.maskName(cacheName) +
+                            ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                     executeBatch(em, delStmt, "deleteAll", fromIdx, prepared, lazyKeys);
 
@@ -1261,10 +1381,10 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 }
             }
 
-            if (delStmt != null && prepared % batchSz != 0) {
+            if (delStmt != null && prepared % batchSize != 0) {
                 if (log.isDebugEnabled())
-                    log.debug("Delete entries from db [cache name=" + cacheName +
-                        ", key type=" + em.keyType() + ", count=" + prepared + "]");
+                    log.debug("Delete entries from db [cache=" +  U.maskName(cacheName) +
+                        ", keyType=" + em.keyType() + ", cnt=" + prepared + "]");
 
                 executeBatch(em, delStmt, "deleteAll", fromIdx, prepared, lazyKeys);
             }
@@ -1281,17 +1401,17 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * Sets the value of the designated parameter using the given object.
      *
      * @param stmt Prepare statement.
-     * @param i Index for parameters.
+     * @param idx Index for parameters.
      * @param field Field descriptor.
      * @param fieldVal Field value.
      * @throws CacheException If failed to set statement parameter.
      */
-    protected void fillParameter(PreparedStatement stmt, int i, CacheTypeFieldMetadata field, @Nullable Object fieldVal)
+    protected void fillParameter(PreparedStatement stmt, int idx, JdbcTypeField field, @Nullable Object fieldVal)
         throws CacheException {
         try {
             if (fieldVal != null) {
-                if (field.getJavaType() == UUID.class) {
-                    switch (field.getDatabaseType()) {
+                if (field.getJavaFieldType() == UUID.class) {
+                    switch (field.getDatabaseFieldType()) {
                         case Types.BINARY:
                             fieldVal = U.uuidToBytes((UUID)fieldVal);
 
@@ -1304,13 +1424,13 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                     }
                 }
 
-                stmt.setObject(i, fieldVal);
+                stmt.setObject(idx, fieldVal);
             }
             else
-                stmt.setNull(i, field.getDatabaseType());
+                stmt.setNull(idx, field.getDatabaseFieldType());
         }
         catch (SQLException e) {
-            throw new CacheException("Failed to set statement parameter name: " + field.getDatabaseName(), e);
+            throw new CacheException("Failed to set statement parameter name: " + field.getDatabaseFieldName(), e);
         }
     }
 
@@ -1324,8 +1444,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      */
     protected int fillKeyParameters(PreparedStatement stmt, int idx, EntryMapping em,
         Object key) throws CacheException {
-        for (CacheTypeFieldMetadata field : em.keyColumns()) {
-            Object fieldVal = extractParameter(em.cacheName, em.keyType(), field.getJavaName(), key);
+        for (JdbcTypeField field : em.keyColumns()) {
+            Object fieldVal = extractParameter(em.cacheName, em.keyType(), em.keyKind(), field.getJavaFieldName(), key);
 
             fillParameter(stmt, idx++, field, fieldVal);
         }
@@ -1354,8 +1474,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      */
     protected int fillValueParameters(PreparedStatement stmt, int idx, EntryMapping em, Object val)
         throws CacheWriterException {
-        for (CacheTypeFieldMetadata field : em.uniqValFields) {
-            Object fieldVal = extractParameter(em.cacheName, em.valueType(), field.getJavaName(), val);
+        for (JdbcTypeField field : em.uniqValFlds) {
+            Object fieldVal = extractParameter(em.cacheName, em.valueType(), em.valueKind(), field.getJavaFieldName(), val);
 
             fillParameter(stmt, idx++, field, fieldVal);
         }
@@ -1401,16 +1521,70 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * @return Max workers thread count.
      */
     public int getMaximumPoolSize() {
-        return maxPoolSz;
+        return maxPoolSize;
     }
 
     /**
      * Set Max workers thread count. These threads are responsible for execute query.
      *
-     * @param maxPoolSz Max workers thread count.
+     * @param maxPoolSize Max workers thread count.
      */
-    public void setMaximumPoolSize(int maxPoolSz) {
-        this.maxPoolSz = maxPoolSz;
+    public void setMaximumPoolSize(int maxPoolSize) {
+        this.maxPoolSize = maxPoolSize;
+    }
+
+    /**
+     * Gets maximum number of write attempts in case of database error.
+     *
+     * @return Maximum number of write attempts.
+     */
+    public int getMaximumWriteAttempts() {
+        return maxWrtAttempts;
+    }
+
+    /**
+     * Sets maximum number of write attempts in case of database error.
+     *
+     * @param maxWrtAttempts Number of write attempts.
+     */
+    public void setMaximumWriteAttempts(int maxWrtAttempts) {
+        this.maxWrtAttempts = maxWrtAttempts;
+    }
+
+    /**
+     * Gets types known by store.
+     *
+     * @return Types known by store.
+     */
+    public JdbcType[] getTypes() {
+        return types;
+    }
+
+    /**
+     * Sets store configurations.
+     *
+     * @param types Store should process.
+     */
+    public void setTypes(JdbcType... types) {
+        this.types = types;
+    }
+
+    /**
+     * Gets hash code calculator.
+     *
+     * @return Hash code calculator.
+     */
+    public JdbcTypeHasher getHasher() {
+        return hasher;
+    }
+
+    /**
+     * Sets hash code calculator.
+     *
+     * @param hasher Hash code calculator.
+     */
+    public void setHasher(JdbcTypeHasher hasher) {
+        this.hasher = hasher;
     }
 
     /**
@@ -1419,16 +1593,16 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
      * @return Maximum batch size.
      */
     public int getBatchSize() {
-        return batchSz;
+        return batchSize;
     }
 
     /**
      * Set maximum batch size for write and delete operations.
      *
-     * @param batchSz Maximum batch size.
+     * @param batchSize Maximum batch size.
      */
-    public void setBatchSize(int batchSz) {
-        this.batchSz = batchSz;
+    public void setBatchSize(int batchSize) {
+        this.batchSize = batchSize;
     }
 
     /**
@@ -1464,6 +1638,18 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     }
 
     /**
+     * Type kind.
+     */
+    protected enum TypeKind {
+        /** Type is known as Java built in type, like {@link String} */
+        BUILT_IN,
+        /** Class for this type is available. */
+        POJO,
+        /** Class for this type is not available. */
+        BINARY
+    }
+
+    /**
      * Entry mapping description.
      */
     protected static class EntryMapping {
@@ -1510,10 +1696,16 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         private final Map<String, Integer> loadColIdxs;
 
         /** Unique value fields. */
-        private final Collection<CacheTypeFieldMetadata> uniqValFields;
+        private final Collection<JdbcTypeField> uniqValFlds;
 
         /** Type metadata. */
-        private final CacheTypeMetadata typeMeta;
+        private final JdbcType typeMeta;
+
+        /** Key type kind. */
+        private final TypeKind keyKind;
+
+        /** Value type kind. */
+        private final TypeKind valKind;
 
         /** Full table name. */
         private final String fullTblName;
@@ -1523,22 +1715,27 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
          * @param dialect JDBC dialect.
          * @param typeMeta Type metadata.
          */
-        public EntryMapping(@Nullable String cacheName, JdbcDialect dialect, CacheTypeMetadata typeMeta) {
+        public EntryMapping(@Nullable String cacheName, JdbcDialect dialect, JdbcType typeMeta,
+            TypeKind keyKind, TypeKind valKind) {
             this.cacheName = cacheName;
 
             this.dialect = dialect;
 
             this.typeMeta = typeMeta;
 
-            Collection<CacheTypeFieldMetadata> keyFields = typeMeta.getKeyFields();
+            this.keyKind = keyKind;
+
+            this.valKind = valKind;
+
+            JdbcTypeField[] keyFields = typeMeta.getKeyFields();
 
-            Collection<CacheTypeFieldMetadata> valFields = typeMeta.getValueFields();
+            JdbcTypeField[] valFields = typeMeta.getValueFields();
 
-            keyCols = databaseColumns(keyFields);
+            keyCols = databaseColumns(F.asList(keyFields));
 
-            uniqValFields = F.view(valFields, new IgnitePredicate<CacheTypeFieldMetadata>() {
-                @Override public boolean apply(CacheTypeFieldMetadata col) {
-                    return !keyCols.contains(col.getDatabaseName());
+            uniqValFlds = F.view(F.asList(valFields), new IgnitePredicate<JdbcTypeField>() {
+                @Override public boolean apply(JdbcTypeField col) {
+                    return !keyCols.contains(col.getDatabaseFieldName());
                 }
             });
 
@@ -1548,7 +1745,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
 
             fullTblName = F.isEmpty(schema) ? tblName : schema + "." + tblName;
 
-            Collection<String> uniqValCols = databaseColumns(uniqValFields);
+            Collection<String> uniqValCols = databaseColumns(uniqValFlds);
 
             cols = F.concat(false, keyCols, uniqValCols);
 
@@ -1579,21 +1776,49 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         }
 
         /**
-         * Extract database column names from {@link CacheTypeFieldMetadata}.
+         * Extract database column names from {@link JdbcTypeField}.
          *
-         * @param dsc collection of {@link CacheTypeFieldMetadata}.
+         * @param dsc collection of {@link JdbcTypeField}.
          * @return Collection with database column names.
          */
-        private static Collection<String> databaseColumns(Collection<CacheTypeFieldMetadata> dsc) {
-            return F.transform(dsc, new C1<CacheTypeFieldMetadata, String>() {
+        private static Collection<String> databaseColumns(Collection<JdbcTypeField> dsc) {
+            return F.transform(dsc, new C1<JdbcTypeField, String>() {
                 /** {@inheritDoc} */
-                @Override public String apply(CacheTypeFieldMetadata col) {
-                    return col.getDatabaseName();
+                @Override public String apply(JdbcTypeField col) {
+                    return col.getDatabaseFieldName();
                 }
             });
         }
 
         /**
+         * @return Key type.
+         */
+        protected String keyType() {
+            return typeMeta.getKeyType();
+        }
+
+        /**
+         * @return Key type kind.
+         */
+        protected TypeKind keyKind() {
+            return keyKind;
+        }
+
+        /**
+         * @return Value type.
+         */
+        protected String valueType() {
+            return typeMeta.getValueType();
+        }
+
+        /**
+         * @return Value type kind.
+         */
+        protected TypeKind valueKind() {
+            return valKind;
+        }
+
+        /**
          * Construct query for select values with key count less or equal {@code maxKeysPerStmt}
          *
          * @param keyCnt Key count.
@@ -1623,25 +1848,11 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         }
 
         /**
-         * @return Key type.
-         */
-        protected String keyType() {
-            return typeMeta.getKeyType();
-        }
-
-        /**
-         * @return Value type.
-         */
-        protected String valueType() {
-            return typeMeta.getValueType();
-        }
-
-        /**
          * Gets key columns.
          *
          * @return Key columns.
          */
-        protected Collection<CacheTypeFieldMetadata> keyColumns() {
+        protected JdbcTypeField[] keyColumns() {
             return typeMeta.getKeyFields();
         }
 
@@ -1650,7 +1861,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
          *
          * @return Value columns.
          */
-        protected Collection<CacheTypeFieldMetadata> valueColumns() {
+        protected JdbcTypeField[] valueColumns() {
             return typeMeta.getValueFields();
         }
 
@@ -1694,8 +1905,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         /** {@inheritDoc} */
         @Override public Void call() throws Exception {
             if (log.isDebugEnabled())
-                log.debug("Load cache using custom query [cache name= " + em.cacheName +
-                    ", key type=" + em.keyType() + ", query=" + qry + "]");
+                log.debug("Load cache using custom query [cache= " + U.maskName(em.cacheName) +
+                    ", keyType=" + em.keyType() + ", query=" + qry + "]");
 
             Connection conn = null;
 
@@ -1716,8 +1927,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                     colIdxs.put(meta.getColumnLabel(i), i);
 
                 while (rs.next()) {
-                    K1 key = buildObject(em.cacheName, em.keyType(), em.keyColumns(), colIdxs, rs);
-                    V1 val = buildObject(em.cacheName, em.valueType(), em.valueColumns(), colIdxs, rs);
+                    K1 key = buildObject(em.cacheName, em.keyType(), em.keyKind(), em.keyColumns(), em.keyCols, colIdxs, rs);
+                    V1 val = buildObject(em.cacheName, em.valueType(), em.valueKind(), em.valueColumns(), null, colIdxs, rs);
 
                     clo.apply(key, val);
                 }
@@ -1790,8 +2001,7 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
         /** {@inheritDoc} */
         @Override public Map<K1, V1> call() throws Exception {
             if (log.isDebugEnabled())
-                log.debug("Load values from db [table= " + em.fullTableName() +
-                    ", key count=" + keys.size() + "]");
+                log.debug("Load values from db [table= " + em.fullTableName() + ", keysCnt=" + keys.size() + "]");
 
             PreparedStatement stmt = null;
 
@@ -1801,8 +2011,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 int idx = 1;
 
                 for (Object key : keys)
-                    for (CacheTypeFieldMetadata field : em.keyColumns()) {
-                        Object fieldVal = extractParameter(em.cacheName, em.keyType(), field.getJavaName(), key);
+                    for (JdbcTypeField field : em.keyColumns()) {
+                        Object fieldVal = extractParameter(em.cacheName, em.keyType(), em.keyKind(), field.getJavaFieldName(), key);
 
                         fillParameter(stmt, idx++, field, fieldVal);
                     }
@@ -1812,8 +2022,8 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
                 Map<K1, V1> entries = U.newHashMap(keys.size());
 
                 while (rs.next()) {
-                    K1 key = buildObject(em.cacheName, em.keyType(), em.keyColumns(), em.loadColIdxs, rs);
-                    V1 val = buildObject(em.cacheName, em.valueType(), em.valueColumns(), em.loadColIdxs, rs);
+                    K1 key = buildObject(em.cacheName, em.keyType(), em.keyKind(), em.keyColumns(), em.keyCols, em.loadColIdxs, rs);
+                    V1 val = buildObject(em.cacheName, em.valueType(), em.valueKind(), em.valueColumns(), null, em.loadColIdxs, rs);
 
                     entries.put(key, val);
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d71f6129/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStoreFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStoreFactory.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStoreFactory.java
index 74ab30b..6a46619 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStoreFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcBlobStoreFactory.java
@@ -35,7 +35,7 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
  *
  * <h2 class="header">Spring Example</h2>
  * <pre name="code" class="xml">
- *     &lt;bean id= "simpleDataSource" class="org.h2.jdbcx.JdbcDataSource"/&gt;
+ *     &lt;bean id= "myDataSource" class="org.h2.jdbcx.JdbcDataSource"/&gt;
  *
  *     &lt;bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"&gt;
  *          ...
@@ -46,7 +46,7 @@ import org.apache.ignite.resources.SpringApplicationContextResource;
  *                      &lt;property name="cacheStoreFactory"&gt;
  *                          &lt;bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory"&gt;
  *                              &lt;property name="user" value = "Ignite" /&gt;
- *                              &lt;property name="dataSourceBean" value = "simpleDataSource" /&gt;
+ *                              &lt;property name="dataSourceBean" value = "myDataSource" /&gt;
  *                          &lt;/bean&gt;
  *                      &lt;/property&gt;
  *                  &lt;/bean&gt;
@@ -99,7 +99,7 @@ public class CacheJdbcBlobStoreFactory<K, V> implements Factory<CacheJdbcBlobSto
 
     /** Application context. */
     @SpringApplicationContextResource
-    private Object appContext;
+    private Object appCtx;
 
     /** {@inheritDoc} */
     @Override public CacheJdbcBlobStore<K, V> create() {
@@ -118,7 +118,7 @@ public class CacheJdbcBlobStoreFactory<K, V> implements Factory<CacheJdbcBlobSto
         if (dataSrc != null)
             store.setDataSource(dataSrc);
         else if (dataSrcBean != null) {
-            if (appContext == null)
+            if (appCtx == null)
                 throw new IgniteException("Spring application context resource is not injected.");
 
             IgniteSpringHelper spring;
@@ -126,13 +126,13 @@ public class CacheJdbcBlobStoreFactory<K, V> implements Factory<CacheJdbcBlobSto
             try {
                 spring = IgniteComponentType.SPRING.create(false);
 
-                DataSource data = spring.loadBeanFromAppContext(appContext, dataSrcBean);
+                DataSource data = spring.loadBeanFromAppContext(appCtx, dataSrcBean);
 
                 store.setDataSource(data);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException("Failed to load bean in application context [beanName=" + dataSrcBean +
-                    ", igniteConfig=" + appContext + ']');
+                    ", igniteConfig=" + appCtx + ']');
             }
         }
 
@@ -287,4 +287,4 @@ public class CacheJdbcBlobStoreFactory<K, V> implements Factory<CacheJdbcBlobSto
     @Override public String toString() {
         return S.toString(CacheJdbcBlobStoreFactory.class, this);
     }
-}
\ No newline at end of file
+}