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

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

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
+}