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/01/19 03:25:15 UTC

[3/3] incubator-ignite git commit: # IGNITE-32 WIP: Reworked store after review.

# IGNITE-32 WIP: Reworked store after review.


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

Branch: refs/heads/ignite-32
Commit: 79f3a5f793bb7d50369c6713fd9fca4063e2edf1
Parents: d5fd7c2
Author: AKuznetsov <ak...@gridgain.com>
Authored: Mon Jan 19 09:25:33 2015 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Mon Jan 19 09:25:33 2015 +0700

----------------------------------------------------------------------
 .../grid/cache/store/auto/AutoCacheStore.java   | 491 +++++++++++--------
 .../grid/cache/store/auto/H2PojoCacheStore.java |  30 --
 .../grid/cache/store/auto/JdbcMapper.java       |  40 --
 .../grid/cache/store/auto/PojoCacheStore.java   | 169 ++++++-
 .../grid/cache/store/auto/PojoJdbcMapper.java   | 160 ------
 .../cache/store/auto/dialect/H2Dialect.java     |  31 ++
 .../cache/store/auto/dialect/JdbcDialect.java   | 244 +++++++++
 .../store/auto/AutoCacheStoreSelfTest.java      |   7 +-
 8 files changed, 728 insertions(+), 444 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/AutoCacheStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/AutoCacheStore.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/AutoCacheStore.java
index ee56152..6e5af2b 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/AutoCacheStore.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/AutoCacheStore.java
@@ -1,10 +1,18 @@
-/* @java.file.header */
-
-/*  _________        _____ __________________        _____
- *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
- *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
- *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
- *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+/*
+ * 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.gridgain.grid.cache.store.auto;
@@ -15,6 +23,7 @@ import org.apache.ignite.resources.*;
 import org.apache.ignite.transactions.*;
 import org.gridgain.grid.cache.query.*;
 import org.gridgain.grid.cache.store.*;
+import org.gridgain.grid.cache.store.auto.dialect.*;
 import org.gridgain.grid.kernal.processors.spring.*;
 import org.gridgain.grid.util.tostring.*;
 import org.gridgain.grid.util.typedef.*;
@@ -36,9 +45,12 @@ import static org.gridgain.grid.kernal.GridComponentType.*;
  */
 public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     /**
-     * Type mapping cache.
+     * Query cache by type.
      */
-    protected class TypeCache {
+    protected static class QueryCache {
+        /** Database dialect. */
+        protected final JdbcDialect dialect;
+
         /** Select all items query. */
         protected final String loadCacheQry;
 
@@ -48,8 +60,14 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         /** Select items query. */
         private final String loadQry;
 
-        /** Put item(s) query. */
-        protected final String putQry;
+        /** Merge item(s) query. */
+        protected final String mergeQry;
+
+        /** Update item query. */
+        protected final String insQry;
+
+        /** Update item query. */
+        protected final String updQry;
 
         /** Remove item(s) query. */
         protected final String remQry;
@@ -57,63 +75,71 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         /** Max key count for load query per statement. */
         protected final int maxKeysPerStmt;
 
-        /** Database table name. */
-        private final String tblName;
-
-        /** Database key columns. */
+        /** Database key columns.  */
         private final Collection<String> keyCols;
 
-        /** Database value columns. */
+        /** Database value columns.  */
         private final Collection<String> valCols;
 
-        /** Database unique columns.  */
-        private final Set<String> uniqCols;
+        /** Database unique value columns.  */
+        private final Collection<String> uniqValCols;
 
-        /** Mapper for key. */
-        protected final JdbcMapper<K> keyMapper;
+        /** Type metadata. */
+        private final GridCacheQueryTypeMetadata typeMetadata;
 
-        /** Mapper for value. */
-        protected final JdbcMapper<V> valMapper;
+        private final Collection<GridCacheQueryTypeDescriptor> uniqValFields;
 
         /**
-         *
-         * @param m Type metadata.
-         * @param keyMapper Mapper for key.
-         * @param valMapper Mapper for value.
+         * @param typeMetadata Type metadata.
          */
-        protected TypeCache(GridCacheQueryTypeMetadata m, JdbcMapper<K> keyMapper, JdbcMapper<V> valMapper) {
-            keyCols = databaseColumns(m.getKeyDescriptors());
+        protected QueryCache(JdbcDialect dialect, GridCacheQueryTypeMetadata typeMetadata) {
+            this.dialect = dialect;
+
+            this.typeMetadata = typeMetadata;
+
+            final Collection<GridCacheQueryTypeDescriptor> keyFields = typeMetadata.getKeyDescriptors();
+
+            Collection<GridCacheQueryTypeDescriptor> valFields = typeMetadata.getValueDescriptors();
+
+            uniqValFields = F.view(typeMetadata.getValueDescriptors(),
+                new IgnitePredicate<GridCacheQueryTypeDescriptor>() {
+                    @Override public boolean apply(GridCacheQueryTypeDescriptor desc) {
+                        return !keyFields.contains(desc);
+                    }
+                });
 
-            valCols = databaseColumns(m.getValueDescriptors());
+            String schema = typeMetadata.getSchema();
 
-            uniqCols = U.newLinkedHashSet(keyCols.size() + valCols.size());
-            uniqCols.addAll(keyCols);
-            uniqCols.addAll(valCols);
+            String tblName = typeMetadata.getTableName();
 
-            tblName = String.format("%s.%s", m.getSchema(), m.getTableName());
+            keyCols = databaseColumns(keyFields);
 
-            loadCacheQry = loadCacheQuery(tblName, uniqCols);
+            valCols = databaseColumns(valFields);
 
-            loadQrySingle = loadQuery(tblName, keyCols, valCols, 1);
+            uniqValCols = databaseColumns(uniqValFields);
 
-            maxKeysPerStmt = maxParamsCnt / keyCols.size();
+            loadCacheQry = dialect.loadCacheQuery(schema, tblName, F.concat(false, keyCols, uniqValCols));
 
-            loadQry = loadQuery(tblName, keyCols, uniqCols, maxKeysPerStmt);
+            loadQrySingle = dialect.loadQuery(schema, tblName, keyCols, valCols, 1);
 
-            putQry = putQuery(tblName, keyCols, uniqCols);
+            maxKeysPerStmt = dialect.getMaxParamsCnt() / keyCols.size();
 
-            remQry = removeQuery(tblName, keyCols);
+            loadQry = dialect.loadQuery(schema, tblName, keyCols, uniqValCols, maxKeysPerStmt);
 
-            this.keyMapper = keyMapper;
+            insQry = dialect.insertQuery(schema, tblName, keyCols, uniqValCols);
 
-            this.valMapper = valMapper;
+            updQry = dialect.updateQuery(schema, tblName, keyCols, uniqValCols);
+
+            mergeQry = dialect.mergeQuery(schema, tblName, keyCols, uniqValCols);
+
+            remQry = dialect.removeQuery(schema, tblName, keyCols);
         }
 
         /**
          * Construct query for select values with key count less or equal {@code maxKeysPerStmt}
          * @param keyCnt Key count.
          */
-        protected String loadQueryLast(int keyCnt) {
+        protected String loadQuery(int keyCnt) {
             assert keyCnt >= maxKeysPerStmt;
 
             if (keyCnt == maxKeysPerStmt)
@@ -122,12 +148,37 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
             if (keyCnt == 1)
                 return loadQrySingle;
 
-            return loadQuery(tblName, keyCols, uniqCols, keyCnt);
+            return dialect.loadQuery(typeMetadata.getSchema(), typeMetadata.getSchema(), keyCols, uniqValCols, keyCnt);
+        }
+
+        /** Key type. */
+        protected String keyType() {
+            return typeMetadata.getKeyType();
         }
-    }
 
-    /** Default max query parameters count. */
-    protected static final int DFLT_MAX_PARAMS_CNT = 2000;
+        /** Value type. */
+        protected String valueType() {
+            return typeMetadata.getType();
+        }
+
+        /**
+         *  Gets key fields type descriptors.
+         *
+         * @return Key fields type descriptors.
+         */
+        protected Collection<GridCacheQueryTypeDescriptor> keyDescriptors() {
+            return typeMetadata.getKeyDescriptors();
+        }
+
+        /**
+         * Gets value fields type descriptors.
+         *
+         * @return Key value type descriptors.
+         */
+        protected Collection<GridCacheQueryTypeDescriptor> valueDescriptors() {
+            return typeMetadata.getValueDescriptors();
+        }
+    }
 
     /** Default batch size for put and remove operations. */
     protected static final int DFLT_BATCH_SIZE = 512;
@@ -176,15 +227,15 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     /** Type mapping description. */
     protected Collection<GridCacheQueryTypeMetadata> typeMetadata;
 
-    /** Type cache. */
-    protected Map<Object, TypeCache> typesCache;
+    /** Cache with query by type. */
+    protected Map<Object, QueryCache> entryQtyCache;
+
+    /** Database dialect. */
+    protected JdbcDialect dialect = new JdbcDialect();
 
     /** Max workers thread count. These threads are responsible for execute query. */
     protected int maxPoolSz = Runtime.getRuntime().availableProcessors();
 
-    /** Max query parameters count. */
-    protected int maxParamsCnt = DFLT_MAX_PARAMS_CNT;
-
     /** Maximum batch size for put and remove operations. */
     protected int batchSz = DFLT_BATCH_SIZE;
 
@@ -340,6 +391,28 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     }
 
     /**
+     * Get field value from object.
+     *
+     * @param typeName Type name.
+     * @param fieldName Field name.
+     * @param obj Cache object.
+     * @return Field value from object.
+     */
+    @Nullable protected abstract Object extractField(String typeName, String fieldName, Object obj) throws IgniteCheckedException;
+
+    /**
+     * Construct object from query result.
+     *
+     * @param <R> Type of result object.
+     * @param typeName Type name.
+     * @param fields Fields descriptors.
+     * @param rs ResultSet.
+     * @return Constructed object.
+     */
+    protected abstract <R> R buildObject(String typeName, Collection<GridCacheQueryTypeDescriptor> fields, ResultSet rs)
+        throws IgniteCheckedException;
+
+    /**
      * Concatenates elements using provided separator.
      *
      * @param elems Concatenated elements.
@@ -436,81 +509,6 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     }
 
     /**
-     * Construct load cache query.
-     *
-     * @param tblName Database table name.
-     * @param uniqCols Database unique columns.
-     * @return Load cache query.
-     */
-    protected String loadCacheQuery(String tblName, Iterable<String> uniqCols) {
-        return String.format("SELECT %s FROM %s", mkString(uniqCols, ","), tblName);
-    }
-
-    /**
-     * Construct load query.
-     *
-     * @param tblName Database table name.
-     * @param keyCols Database key columns.
-     * @param valCols Database value columns.
-     * @param keyCnt Key count.
-     * @return Load query.
-     */
-    protected String loadQuery(String tblName, Collection<String> keyCols, Iterable<String> valCols, int keyCnt) {
-        assert !keyCols.isEmpty();
-
-        assert keyCols.size() * keyCnt <= maxParamsCnt;
-
-        SB sb = new SB(String.format("SELECT %s FROM %s WHERE ", mkString(valCols, ","), tblName));
-
-        if (keyCols.size() == 1) {
-            String keyCol = keyCols.iterator().next();
-
-            if (keyCnt == 1)
-                sb.a(keyCol+ "=?");
-            else
-                sb.a(repeat("?", keyCnt, keyCol + " IN (", ",", ")"));
-        }
-        else {
-            String keyParams = mkString(keyCols, new C1<String, String>() {
-                @Override public String apply(String s) {
-                    return s + "=?";
-                }
-            }, "(", " AND ", ")");
-
-            sb.a(repeat(keyParams, keyCnt, "", " OR ", ""));
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * Construct put query.
-     *
-     * @param tblName Database table name.
-     * @param keyCols Database key columns.
-     * @param uniqCols Database unique columns.
-     * @return Put query.
-     */
-    protected abstract String putQuery(String tblName, Collection<String> keyCols, Collection<String> uniqCols);
-
-    /**
-     * Construct remove query.
-     *
-     * @param tblName Database table name.
-     * @param keyCols Database key columns.
-     * @return Remove query.
-     */
-    protected String removeQuery(String tblName, Iterable<String> keyCols) {
-        String whereParams = mkString(keyCols, new C1<String, String>() {
-            @Override public String apply(String s) {
-                return s + "=?";
-            }
-        }, "", " AND ", "");
-
-        return String.format("DELETE FROM %s WHERE %s", tblName, whereParams);
-    }
-
-    /**
      * Extract type key from object.
      *
      * @param key Key object.
@@ -525,7 +523,6 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
      */
     protected abstract void buildTypeCache() throws IgniteCheckedException;
 
-
     /** {@inheritDoc} */
     @Override public void loadCache(final IgniteBiInClosure<K, V> clo, @Nullable Object... args)
         throws IgniteCheckedException {
@@ -536,7 +533,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
         Collection<Future<?>> futs = new ArrayList<>();
 
-        for (final TypeCache type : typesCache.values())
+        for (final QueryCache type : entryQtyCache.values())
             futs.add(exec.submit(new Callable<Void>() {
                 @Override public Void call() throws Exception {
                 Connection conn = null;
@@ -552,8 +549,8 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
                         ResultSet rs = stmt.executeQuery();
 
                         while (rs.next()) {
-                            K key = type.keyMapper.readObject(ignite, rs);
-                            V val = type.valMapper.readObject(ignite, rs);
+                            K key = buildObject(type.keyType(), type.keyDescriptors(), rs);
+                            V val = buildObject(type.valueType(), type.valueDescriptors(), rs);
 
                             clo.apply(key, val);
                         }
@@ -577,11 +574,72 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
             U.get(fut);
     }
 
+    /**
+     * @param stmt Prepare statement.
+     * @param i Start index for parameters.
+     * @param type Type description.
+     * @param key Key object.
+     * @return Next index for parameters.
+     */
+    protected int fillKeyParameters(PreparedStatement stmt, int i, QueryCache type, K key) throws IgniteCheckedException {
+        for (GridCacheQueryTypeDescriptor field : type.keyDescriptors()) {
+            Object fieldVal = extractField(type.keyType(), field.getJavaName(), key);
+
+            try {
+                if (fieldVal != null)
+                    stmt.setObject(i++, fieldVal);
+                else
+                    stmt.setNull(i++, field.getDbType());
+            }
+            catch (SQLException e) {
+                throw new IgniteCheckedException("Failed to set statement parameter name: " + field.getDbName(), e);
+            }
+        }
+
+        return i;
+    }
+
+    /**
+     * @param stmt Prepare statement.
+     * @param type Type description.
+     * @param key Key object.
+     * @return Next index for parameters.
+     */
+    protected int fillKeyParameters(PreparedStatement stmt, QueryCache type, K key) throws IgniteCheckedException {
+        return fillKeyParameters(stmt, 1, type, key);
+    }
+
+    /**
+     * @param stmt Prepare statement.
+     * @param i Start index for parameters.
+     * @param type Type description.
+     * @param val Value object.
+     * @return Next index for parameters.
+     */
+    protected int fillValueParameters(PreparedStatement stmt, int i, QueryCache type, V val)
+        throws IgniteCheckedException {
+        for (GridCacheQueryTypeDescriptor field : type.uniqValFields) {
+            Object fieldVal = extractField(type.valueType(), field.getJavaName(), val);
+
+            try {
+                if (fieldVal != null)
+                    stmt.setObject(i++, fieldVal);
+                else
+                    stmt.setNull(i++, field.getDbType());
+            }
+            catch (SQLException e) {
+                throw new IgniteCheckedException("Failed to set statement parameter name: " + field.getDbName(), e);
+            }
+        }
+
+        return i;
+    }
+
     /** {@inheritDoc} */
     @Nullable @Override public V load(@Nullable IgniteTx tx, K key) throws IgniteCheckedException {
         init();
 
-        TypeCache type = typesCache.get(key.getClass());
+        QueryCache type = entryQtyCache.get(key.getClass());
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find mapping description for type: " + key.getClass());
@@ -598,12 +656,12 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
             stmt = conn.prepareStatement(type.loadQrySingle);
 
-            type.keyMapper.setParameters(stmt, 1, key);
+            fillKeyParameters(stmt, type, key);
 
             ResultSet rs = stmt.executeQuery();
 
             if (rs.next())
-                return type.valMapper.readObject(ignite, rs);
+                return buildObject(type.valueType(), type.valueDescriptors(), rs);
         }
         catch (SQLException e) {
             throw new IgniteCheckedException("Failed to load object by key: " + key, e);
@@ -628,7 +686,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         IgniteBiInClosure<K, V> c) throws IgniteCheckedException {
         init();
 
-        TypeCache type = typesCache.get(typeKey);
+        QueryCache type = entryQtyCache.get(typeKey);
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find metadata for type: " + typeKey);
@@ -640,26 +698,32 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         try {
             conn = connection(tx);
 
-            stmt = conn.prepareStatement(type.loadQueryLast(keys.size()));
+            stmt = conn.prepareStatement(type.loadQuery(keys.size()));
 
-            int startIdx = 1;
+            int i = 1;
 
-            for (K key : keys)
-                startIdx = type.keyMapper.setParameters(stmt, startIdx, key);
+            for (K key : keys) {
+                for (GridCacheQueryTypeDescriptor field : type.keyDescriptors()) {
+                    Object fieldVal = extractField(type.keyType(), field.getJavaName(), key);
 
-            stmt.executeQuery();
+                    if (fieldVal != null)
+                        stmt.setObject(i++, fieldVal);
+                    else
+                        stmt.setNull(i++, field.getDbType());
+                }
+            }
 
             ResultSet rs = stmt.executeQuery();
 
             while (rs.next()) {
-                K key = type.keyMapper.readObject(ignite, rs);
-                V val = type.valMapper.readObject(ignite, rs);
+                K key = buildObject(type.keyType(), type.keyDescriptors(), rs);
+                V val = buildObject(type.valueType(), type.valueDescriptors(), rs);
 
                 c.apply(key, val);
             }
         }
         catch (SQLException e) {
-            throw new IgniteCheckedException("Failed to put objects", e);
+            throw new IgniteCheckedException("Failed to load objects", e);
         }
         finally {
             end(tx, conn, stmt);
@@ -668,9 +732,10 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
     /** {@inheritDoc} */
     @Override public void loadAll(@Nullable final IgniteTx tx, Collection<? extends K> keys,
-        final IgniteBiInClosure<K, V> c)
-        throws IgniteCheckedException {
-        Map<Object, Collection<K>> splittedKeys = U.newHashMap(typesCache.size());
+        final IgniteBiInClosure<K, V> c) throws IgniteCheckedException {
+        assert keys != null;
+
+        Map<Object, Collection<K>> splittedKeys = U.newHashMap(entryQtyCache.size());
 
         final Collection<Future<?>> futs = new ArrayList<>();
 
@@ -684,7 +749,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
             batch.add(key);
 
-            if (batch.size() == typesCache.get(typeKey).maxKeysPerStmt) {
+            if (batch.size() == entryQtyCache.get(typeKey).maxKeysPerStmt) {
                 final Collection<K> p = splittedKeys.remove(typeKey);
 
                 futs.add(exec.submit(new Callable<Void>() {
@@ -714,7 +779,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     @Override public void put(@Nullable IgniteTx tx, K key, V val) throws IgniteCheckedException {
         init();
 
-        TypeCache type = typesCache.get(key.getClass());
+        QueryCache type = entryQtyCache.get(key.getClass());
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find metadata for type: " + key.getClass());
@@ -729,12 +794,34 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         try {
             conn = connection(tx);
 
-            stmt = conn.prepareStatement(type.putQry);
+            if (dialect.hasMerge()) {
+                stmt = conn.prepareStatement(type.mergeQry);
 
-            int idx = type.keyMapper.setParameters(stmt, 1, key);
-            type.valMapper.setParameters(stmt, idx, val);
+                int i = fillKeyParameters(stmt, type, key);
 
-            stmt.executeUpdate();
+                fillValueParameters(stmt, i, type, val);
+
+                stmt.executeUpdate();
+            }
+            else {
+                stmt = conn.prepareStatement(type.updQry);
+
+                int i = fillValueParameters(stmt, 1, type, val);
+
+                fillKeyParameters(stmt, i, type, key);
+
+                if (stmt.executeUpdate() == 0) {
+                    stmt.close();
+
+                    stmt = conn.prepareStatement(type.insQry);
+
+                    i = fillKeyParameters(stmt, type, key);
+
+                    fillValueParameters(stmt, i, type, val);
+
+                    stmt.executeUpdate();
+                }
+            }
         }
         catch (SQLException e) {
             throw new IgniteCheckedException("Failed to load object by key: " + key, e);
@@ -759,7 +846,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
         init();
 
-        TypeCache type = typesCache.get(typeKey);
+        QueryCache type = entryQtyCache.get(typeKey);
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find metadata for type: " + typeKey);
@@ -771,14 +858,14 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
         try {
             conn = connection(tx);
 
-            stmt = conn.prepareStatement(type.putQry);
+            stmt = conn.prepareStatement(type.mergeQry);
 
             int cnt = 0;
 
             for (Map.Entry<? extends K, ? extends V> entry : map) {
-                int startIdx = type.keyMapper.setParameters(stmt, 1, entry.getKey());
+                int i = fillKeyParameters(stmt, type, entry.getKey());
 
-                type.valMapper.setParameters(stmt, startIdx, entry.getValue());
+                fillValueParameters(stmt, i, type, entry.getValue());
 
                 stmt.addBatch();
 
@@ -800,39 +887,46 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     /** {@inheritDoc} */
     @Override public void putAll(@Nullable final IgniteTx tx, Map<? extends K, ? extends V> map)
         throws IgniteCheckedException {
-        Map<Object, Collection<Map.Entry<? extends K, ? extends V>>> keyByType = U.newHashMap(typesCache.size());
+        assert map != null;
 
-        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
-            Object typeKey = typeKey(entry.getKey());
+        Map<Object, Collection<Map.Entry<? extends K, ? extends V>>> keyByType = U.newHashMap(entryQtyCache.size());
 
-            Collection<Map.Entry<? extends K, ? extends V>> batch = keyByType.get(typeKey);
+        if (dialect.hasMerge()) {
+            for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
+                Object typeKey = typeKey(entry.getKey());
 
-            if (batch == null)
-                keyByType.put(typeKey, batch = new ArrayList<>());
+                Collection<Map.Entry<? extends K, ? extends V>> batch = keyByType.get(typeKey);
 
-            batch.add(entry);
-        }
+                if (batch == null)
+                    keyByType.put(typeKey, batch = new ArrayList<>());
 
-        final Collection<Future<?>> futs = new ArrayList<>();
+                batch.add(entry);
+            }
 
-        for (final Map.Entry<Object, Collection<Map.Entry<? extends K, ? extends V>>> entry : keyByType.entrySet())
-            futs.add(exec.submit(new Callable<Void>() {
-                @Override public Void call() throws Exception {
-                    putAll(tx, entry.getKey(), entry.getValue());
+            final Collection<Future<?>> futs = new ArrayList<>();
 
-                    return null;
-                }
-            }));
+            for (final Map.Entry<Object, Collection<Map.Entry<? extends K, ? extends V>>> entry : keyByType.entrySet())
+                futs.add(exec.submit(new Callable<Void>() {
+                    @Override public Void call() throws Exception {
+                        putAll(tx, entry.getKey(), entry.getValue());
 
-        for (Future<?> fut : futs)
-            U.get(fut);
+                        return null;
+                    }
+                }));
+
+            for (Future<?> fut : futs)
+                U.get(fut);
+        }
+        else
+            for (Map.Entry<? extends K, ? extends V> e : map.entrySet())
+                put(tx, e.getKey(), e.getValue());
     }
 
     /** {@inheritDoc} */
     @Override public void remove(@Nullable IgniteTx tx, K key) throws IgniteCheckedException {
         init();
 
-        TypeCache type = typesCache.get(key.getClass());
+        QueryCache type = entryQtyCache.get(key.getClass());
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find metadata for type: " + key.getClass());
@@ -849,7 +943,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
 
             stmt = conn.prepareStatement(type.remQry);
 
-            type.keyMapper.setParameters(stmt, 1, key);
+            fillKeyParameters(stmt, type, key);
 
             stmt.executeUpdate();
         }
@@ -869,13 +963,14 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
      * @param keys Collection of keys to remove.
      * @throws IgniteCheckedException If remove failed.
      */
-    protected void removeAll(@Nullable IgniteTx tx, Object typeKey, Collection<? extends K> keys) throws IgniteCheckedException {
+    protected void removeAll(@Nullable IgniteTx tx, Object typeKey, Collection<? extends K> keys)
+        throws IgniteCheckedException {
         assert keys != null;
         assert keys.size() > 1;
 
         init();
 
-        TypeCache type = typesCache.get(typeKey);
+        QueryCache type = entryQtyCache.get(typeKey);
 
         if (type == null)
             throw new IgniteCheckedException("Failed to find metadata for type: " + typeKey);
@@ -895,7 +990,7 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
             int cnt = 0;
 
             for (K key : keys) {
-                type.keyMapper.setParameters(stmt, 1, key);
+                fillKeyParameters(stmt, type, key);
 
                 stmt.addBatch();
 
@@ -915,9 +1010,10 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     }
 
     /** {@inheritDoc} */
-    @Override public void removeAll(@Nullable IgniteTx tx, Collection<? extends K> keys)
-        throws IgniteCheckedException {
-        Map<Object, Collection<K>> keyByType = U.newHashMap(typesCache.size());
+    @Override public void removeAll(@Nullable IgniteTx tx, Collection<? extends K> keys) throws IgniteCheckedException {
+        assert keys != null;
+
+        Map<Object, Collection<K>> keyByType = U.newHashMap(entryQtyCache.size());
 
         for (K key : keys) {
             Object typeKey = typeKey(key);
@@ -1016,39 +1112,40 @@ public abstract class AutoCacheStore<K, V> implements GridCacheStore<K, V> {
     }
 
     /**
-     * Get Max workers thread count. These threads are responsible for execute query.
+     * Get database dialect.
      *
-     * @return Max workers thread count.
+     * @return Database dialect.
      */
-    public int getMaxPoolSize() {
-        return maxPoolSz;
+    public JdbcDialect getDialect() {
+        return dialect;
     }
 
+
     /**
-     * Set Max workers thread count. These threads are responsible for execute query.
+     * Set database dialect.
      *
-     * @param maxPoolSz Max workers thread count.
+     * @param dialect Database dialect.
      */
-    public void setMaxPoolSize(int maxPoolSz) {
-        this.maxPoolSz = maxPoolSz;
+    public void setDialect(JdbcDialect dialect) {
+        this.dialect = dialect;
     }
 
     /**
-     * Get max query parameters count.
+     * Get Max workers thread count. These threads are responsible for execute query.
      *
-     * @return Max query parameters count.
+     * @return Max workers thread count.
      */
-    public int getMaxParamsCnt() {
-        return maxParamsCnt;
+    public int getMaxPoolSize() {
+        return maxPoolSz;
     }
 
     /**
-     * Set max query parameters count.
+     * Set Max workers thread count. These threads are responsible for execute query.
      *
-     * @param maxParamsCnt Max query parameters count.
+     * @param maxPoolSz Max workers thread count.
      */
-    public void setMaxParamsCnt(int maxParamsCnt) {
-        this.maxParamsCnt = maxParamsCnt;
+    public void setMaxPoolSize(int maxPoolSz) {
+        this.maxPoolSz = maxPoolSz;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/H2PojoCacheStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/H2PojoCacheStore.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/H2PojoCacheStore.java
deleted file mode 100644
index 7198e8a..0000000
--- a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/H2PojoCacheStore.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/* @java.file.header */
-
-/*  _________        _____ __________________        _____
- *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
- *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
- *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
- *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
- */
-
-package org.gridgain.grid.cache.store.auto;
-
-import org.gridgain.grid.util.typedef.internal.*;
-
-import java.util.*;
-
-/**
-  * Store implementation for H2 database.
- */
-public class H2PojoCacheStore extends PojoCacheStore {
-    /** {@inheritDoc} */
-    @Override protected String putQuery(String tblName, Collection<String> keyCols, Collection<String> uniqCols) {
-        return String.format("MERGE INTO %s (%s) KEY (%s) VALUES(%s)", tblName, mkString(uniqCols, ","),
-            mkString(keyCols, ","), repeat("?", uniqCols.size(), "",", ",""));
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(H2PojoCacheStore.class, this, "passwd", passwd != null ? "*" : null);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/JdbcMapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/JdbcMapper.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/JdbcMapper.java
deleted file mode 100644
index 2d0c98e..0000000
--- a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/JdbcMapper.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* @java.file.header */
-
-/*  _________        _____ __________________        _____
- *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
- *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
- *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
- *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
- */
-
-package org.gridgain.grid.cache.store.auto;
-
-import org.apache.ignite.*;
-
-import java.sql.*;
-
-/**
- * Mapper between JDBC objects and cache objects.
- */
-public interface JdbcMapper<T> {
-    /**
-     * Set parameters in prepare statement from cache object.
-     *
-     * @param stmt Prepare statement.
-     * @param startIdx Start index for set parameters in prepare statement.
-     * @param obj Cache object.
-     * @return Last parameter index.
-     * @throws IgniteCheckedException If failed.
-     */
-    public int setParameters(PreparedStatement stmt, int startIdx, T obj) throws IgniteCheckedException;
-
-    /**
-     * Read cache object from result set.
-     *
-     * @param ignite Grid.
-     * @param rs Result set.
-     * @return cache object.
-     * @throws IgniteCheckedException If failed.
-     */
-    public T readObject(Ignite ignite, ResultSet rs) throws IgniteCheckedException;
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoCacheStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoCacheStore.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoCacheStore.java
index a349cb9..d3892c3 100644
--- a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoCacheStore.java
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoCacheStore.java
@@ -1,10 +1,18 @@
-/* @java.file.header */
-
-/*  _________        _____ __________________        _____
- *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
- *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
- *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
- *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+/*
+ * 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.gridgain.grid.cache.store.auto;
@@ -13,7 +21,10 @@ import org.apache.ignite.*;
 import org.gridgain.grid.cache.query.*;
 import org.gridgain.grid.cache.store.*;
 import org.gridgain.grid.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
 
+import java.lang.reflect.*;
+import java.sql.*;
 import java.util.*;
 
 /**
@@ -21,22 +32,150 @@ import java.util.*;
  *
  * This implementation stores objects in underlying database using java beans mapping description via reflection.
  */
-public abstract class PojoCacheStore extends AutoCacheStore<Object, Object> {
+public class PojoCacheStore extends AutoCacheStore<Object, Object> {
+    /**
+     * POJO methods cache.
+     */
+    protected static class PojoMethodsCache {
+        /** POJO class. */
+        protected final Class<?> cls;
+
+        /** Constructor for POJO object. */
+        private final Constructor ctor;
+
+        /** Cached setters for POJO object. */
+        private final Map<String, Method> getters;
+
+        /** Cached getters for POJO object. */
+        private final Map<String, Method> setters;
+
+        /**
+         * POJO methods cache.
+         *
+         * @param clsName Class name.
+         * @param fields Fields.
+         */
+        public PojoMethodsCache(String clsName, Collection<GridCacheQueryTypeDescriptor> fields) throws IgniteCheckedException {
+
+            try {
+                cls = Class.forName(clsName);
+
+                ctor = cls.getDeclaredConstructor();
+
+                if (!ctor.isAccessible())
+                    ctor.setAccessible(true);
+            }
+            catch (ClassNotFoundException e) {
+                throw new IgniteCheckedException("Failed to find class: " + clsName, e);
+            }
+            catch (NoSuchMethodException e) {
+                throw new IgniteCheckedException("Failed to find empty constructor for class: " + clsName, e);
+            }
+
+            setters = U.newHashMap(fields.size());
+
+            getters = U.newHashMap(fields.size());
+
+            for (GridCacheQueryTypeDescriptor field : fields) {
+                String prop = capitalFirst(field.getJavaName());
+
+                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 IgniteCheckedException("Failed to find getter for property " + field.getJavaName() +
+                            " of class: " + cls.getName(), e);
+                    }
+                }
+
+                try {
+                    setters.put(field.getJavaName(), cls.getMethod("set" + prop, field.getJavaType()));
+                }
+                catch (NoSuchMethodException e) {
+                    throw new IgniteCheckedException("Failed to find setter for property " + field.getJavaName() +
+                        " of class: " + clsName, 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);
+        }
+
+        /**
+         * Construct new instance of pojo object.
+         *
+         * @return pojo object.
+         * @throws IgniteCheckedException If construct new instance failed.
+         */
+        protected Object newInstance() throws IgniteCheckedException {
+            try {
+                return ctor.newInstance();
+            }
+            catch (Exception e) {
+                throw new IgniteCheckedException("Failed to create new instance for class: " + cls, e);
+            }
+        }
+    }
+
+    Map<String, PojoMethodsCache> mtdsCache;
+
     /** {@inheritDoc} */
     @Override protected void buildTypeCache() throws IgniteCheckedException {
-        typesCache = U.newHashMap(typeMetadata.size());
+        entryQtyCache = U.newHashMap(typeMetadata.size());
+
+        mtdsCache = U.newHashMap(typeMetadata.size() * 2);
 
         for (GridCacheQueryTypeMetadata type : typeMetadata) {
-            Collection<String> excludeValCols = new LinkedHashSet<>(databaseColumns(type.getValueDescriptors()));
+            PojoMethodsCache keyCache = new PojoMethodsCache(type.getKeyType(), type.getKeyDescriptors());
+
+            mtdsCache.put(type.getKeyType(), keyCache);
+
+            entryQtyCache.put(keyCache.cls, new QueryCache(dialect, type));
+
+            mtdsCache.put(type.getType(), new PojoMethodsCache(type.getType(), type.getValueDescriptors()));
+        }
+    }
 
-            excludeValCols.retainAll(databaseColumns(type.getKeyDescriptors()));
+    /** {@inheritDoc} */
+    @Override protected <R> R buildObject(String typeName, Collection<GridCacheQueryTypeDescriptor> fields,
+        ResultSet rs) throws IgniteCheckedException {
+        PojoMethodsCache t = mtdsCache.get(typeName);
 
-            PojoJdbcMapper keyMapper = new PojoJdbcMapper(type.getKeyType(), type.getKeyDescriptors(),
-                Collections.<String>emptyList());
+        Object obj = t.newInstance();
 
-            PojoJdbcMapper valMapper = new PojoJdbcMapper(type.getType(), type.getValueDescriptors(), excludeValCols);
+        try {
+            for (GridCacheQueryTypeDescriptor field : fields)
+                t.setters.get(field.getJavaName()).invoke(obj, rs.getObject(field.getDbName()));
 
-            typesCache.put(keyMapper.cls, new TypeCache(type, keyMapper, valMapper));
+            return (R)obj;
+        }
+        catch (Exception e) {
+            throw new IgniteCheckedException("Failed to read object of class: " + typeName, e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected Object extractField(String typeName, String fieldName, Object obj)
+        throws IgniteCheckedException {
+        try {
+            PojoMethodsCache t = mtdsCache.get(typeName);
+
+            return t.getters.get(fieldName).invoke(obj);
+        }
+        catch (Exception e) {
+            throw new IgniteCheckedException("Failed to read object of class: " + typeName, e);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoJdbcMapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoJdbcMapper.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoJdbcMapper.java
deleted file mode 100644
index f1544a9..0000000
--- a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/PojoJdbcMapper.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/* @java.file.header */
-
-/*  _________        _____ __________________        _____
- *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
- *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
- *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
- *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
- */
-
-package org.gridgain.grid.cache.store.auto;
-
-import org.apache.ignite.*;
-import org.gridgain.grid.cache.query.*;
-import org.jetbrains.annotations.*;
-
-import java.lang.reflect.*;
-import java.sql.*;
-import java.util.*;
-
-/**
- * Mapper between JDBC objects and POJO.
- */
-public class PojoJdbcMapper implements JdbcMapper<Object> {
-    /** POJO class. */
-    protected final Class<?> cls;
-
-    /** Constructor for POJO object. */
-    private final Constructor ctor;
-
-    /** Database column names. */
-    private final String[] colNames;
-
-    /** Cached setters for POJO object. */
-    private final Method[] setters;
-
-    /** Cached getters for POJO object. */
-    private final Method[] getters;
-
-    /**
-     * @param clsName POJO class name.
-     * @param descs Fields descriptors.
-     * @param excludeCols Columns for exclude from set parameters.
-     */
-    protected PojoJdbcMapper(String clsName, Collection<GridCacheQueryTypeDescriptor> descs,
-        Collection<String> excludeCols) throws IgniteCheckedException {
-        assert descs != null && !descs.isEmpty();
-        assert excludeCols != null;
-
-        try {
-            cls = Class.forName(clsName);
-
-            ctor = cls.getDeclaredConstructor();
-
-            if (!ctor.isAccessible())
-                ctor.setAccessible(true);
-        }
-        catch (ClassNotFoundException e) {
-            throw new IgniteCheckedException("Failed to find class: " + clsName, e);
-        }
-        catch (NoSuchMethodException e) {
-            throw new IgniteCheckedException("Failed to find empty constructor for class: " + clsName, e);
-        }
-
-        colNames = new String[descs.size()];
-
-        List<Method> getters = new ArrayList<>(descs.size() - excludeCols.size());
-
-        setters = new Method[descs.size()];
-
-        int i = 0;
-
-        for (GridCacheQueryTypeDescriptor desc : descs) {
-            colNames[i] = desc.getDbName();
-
-            String prop = capitalFirst(desc.getJavaName());
-
-            try {
-                setters[i] = cls.getMethod("set" + prop, desc.getJavaType());
-            }
-            catch (NoSuchMethodException e) {
-                throw new IgniteCheckedException("Failed to find setter for property " + desc.getJavaName() +
-                    " of class: " + clsName, e);
-            }
-
-            if (!excludeCols.contains(colNames[i])) {
-                try {
-                    getters.add(cls.getMethod("get" + prop));
-                }
-                catch (NoSuchMethodException ignored) {
-                    try {
-                        getters.add(cls.getMethod("is" + prop));
-                    }
-                    catch (NoSuchMethodException e) {
-                        throw new IgniteCheckedException("Failed to find getter for property " + desc.getJavaName() +
-                            " of class: " + cls.getName(), e);
-                    }
-                }
-            }
-
-            i++;
-        }
-
-        this.getters = getters.toArray(new Method[getters.size()]);
-    }
-
-    /**
-     * Capitalizes the first character of the given string.
-     *
-     * @param str String.
-     * @return String with capitalized first character.
-     */
-    private String capitalFirst(@Nullable String str) {
-        return str == null ? null :
-            str.isEmpty() ? "" : Character.toUpperCase(str.charAt(0)) + str.substring(1);
-    }
-
-    /**
-     * Construct new instance of pojo object.
-     *
-     * @return pojo object.
-     * @throws IgniteCheckedException If construct new instance failed.
-     */
-    private Object newInstance() throws IgniteCheckedException {
-        try {
-            return ctor.newInstance();
-        }
-        catch (Exception e) {
-            throw new IgniteCheckedException("Failed to create new instance for class: " + cls, e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public int setParameters(PreparedStatement stmt, int startIdx, Object obj)
-        throws IgniteCheckedException {
-        try {
-            for (int i = 0; i < getters.length; i++)
-                stmt.setObject(startIdx  + i, getters[i].invoke(obj));
-
-            return startIdx + getters.length;
-        }
-        catch (Exception e) {
-            throw new IgniteCheckedException("Failed to set parameters for query.", e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object readObject(Ignite ignite, ResultSet rs) throws IgniteCheckedException {
-        Object obj = newInstance();
-
-        try {
-            for (int i = 0; i < setters.length; i++)
-                setters[i].invoke(obj, rs.getObject(colNames[i]));
-
-            return obj;
-        }
-        catch (Exception e) {
-            throw new IgniteCheckedException("Failed to read object of class: " + cls, e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/H2Dialect.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/H2Dialect.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/H2Dialect.java
new file mode 100644
index 0000000..c9c3710
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/H2Dialect.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.gridgain.grid.cache.store.auto.dialect;
+
+import java.util.*;
+
+/**
+ *
+ */
+public class H2Dialect extends JdbcDialect {
+    /** {@inheritDoc} */
+    @Override public String mergeQuery(String schema, String tblName, Collection<String> keyCols, Collection<String> uniqCols) {
+        return String.format("MERGE INTO %s (%s) KEY (%s) VALUES(%s)", tblName, mkString(uniqCols, ","),
+            mkString(keyCols, ","), repeat("?", uniqCols.size(), "",", ",""));
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/JdbcDialect.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/JdbcDialect.java b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/JdbcDialect.java
new file mode 100644
index 0000000..3f65971
--- /dev/null
+++ b/modules/core/src/main/java/org/gridgain/grid/cache/store/auto/dialect/JdbcDialect.java
@@ -0,0 +1,244 @@
+/*
+ * 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.gridgain.grid.cache.store.auto.dialect;
+
+import org.gridgain.grid.util.typedef.*;
+import org.gridgain.grid.util.typedef.internal.*;
+
+import java.util.*;
+
+/**
+ *
+ */
+public class JdbcDialect {
+    /** Default max query parameters count. */
+    protected static final int DFLT_MAX_PARAMS_CNT = 2000;
+
+    /** Max query parameters count. */
+    protected int maxParamsCnt = DFLT_MAX_PARAMS_CNT;
+
+    /**
+     * Concatenates elements using provided separator.
+     *
+     * @param elems Concatenated elements.
+     * @param f closure used for transform element.
+     * @param start Start string.
+     * @param sep Separator.
+     * @param end End string.
+     * @return Concatenated string.
+     */
+    protected static <T> String mkString(Iterable<T> elems, C1<T, String> f, String start, String sep, String end) {
+        SB sb = new SB(start);
+
+        boolean first = true;
+
+        for (T elem : elems) {
+            if (!first)
+                sb.a(sep);
+
+            sb.a(f.apply(elem));
+
+            first = false;
+        }
+
+        return sb.a(end).toString();
+    }
+
+    /**
+     * Concatenates elements using provided separator.
+     *
+     * @param strs Concatenated string.
+     * @param start Start string.
+     * @param sep Delimiter.
+     * @param end End string.
+     * @return Concatenated string.
+     */
+    protected static String mkString(Iterable<String> strs, String start, String sep, String end) {
+        return mkString(strs, new C1<String, String>() {
+            @Override public String apply(String s) {
+                return s;
+            }
+        }, start, sep, end);
+    }
+
+    /**
+     * Concatenates strings using provided separator.
+     *
+     * @param strs Concatenated string.
+     * @param sep Separator.
+     * @return Concatenated string.
+     */
+    protected static String mkString(Iterable<String> strs, String sep) {
+        return mkString(strs, new C1<String, String>() {
+            @Override public String apply(String s) {
+                return s;
+            }
+        }, "", sep, "");
+    }
+
+    /**
+     * Concatenates elements using provided delimiter.
+     *
+     * @param str Repeated string.
+     * @param cnt Repeat count.
+     * @param start Start string.
+     * @param sep Separator.
+     * @param end End string.
+     */
+    protected static String repeat(String str, int cnt, String start, String sep, String end) {
+        SB sb = new SB(str.length() * cnt + sep.length() * (cnt - 1) + start.length() + end.length());
+
+        sb.a(start);
+
+        for (int i = 0; i < cnt; i++) {
+            if (i > 0)
+                sb.a(sep);
+
+            sb.a(str);
+        }
+
+        return sb.a(end).toString();
+    }
+
+    protected static String where(Collection<String> keyCols, int keyCnt) {
+        SB sb = new SB();
+
+        if (keyCols.size() == 1) {
+            String keyCol = keyCols.iterator().next();
+
+            if (keyCnt == 1)
+                sb.a(keyCol+ "=?");
+            else
+                sb.a(repeat("?", keyCnt, keyCol + " IN (", ",", ")"));
+        }
+        else {
+            String keyParams = mkString(keyCols, new C1<String, String>() {
+                @Override public String apply(String s) {
+                    return s + "=?";
+                }
+            }, "(", " AND ", ")");
+
+            sb.a(repeat(keyParams, keyCnt, "", " OR ", ""));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Construct load cache query.
+     *
+     * @param schema Database schema name.
+     * @param tblName Database table name.
+     * @param uniqCols Database unique columns.
+     * @return Load cache query.
+     */
+    public String loadCacheQuery(String schema, String tblName, Iterable<String> uniqCols) {
+        return String.format("SELECT %s FROM %s.%s", mkString(uniqCols, ","), schema, tblName);
+    }
+
+    /**
+     * Construct load query.
+     *
+     * @param schema Database schema name.
+     * @param tblName Database table name.
+     * @param keyCols Database key columns.
+     * @param valCols Database value columns.
+     * @param keyCnt Key count.
+     * @return Load query.
+     */
+    public String loadQuery(String schema, String tblName, Collection<String> keyCols, Iterable<String> valCols,
+        int keyCnt) {
+        assert !keyCols.isEmpty();
+
+        String params = where(keyCols, keyCnt);
+
+        return  String.format("SELECT %s FROM %s.%s WHERE %s", mkString(valCols, ","), schema, tblName, params);
+    }
+
+    public String insertQuery(String schema, String tblName, Collection<String> keyCols, Collection<String> valCols) {
+        Collection<String> cols = F.concat(false, keyCols, valCols);
+
+        return String.format("INSERT INTO %s.%s(%s) VALUES(%s)", schema, tblName, mkString(cols, ","),
+            repeat("?", cols.size(), "", ",", ""));
+    }
+
+    public String updateQuery(String schema, String tblName, Collection<String> keyCols, final Iterable<String> valCols) {
+        String params = mkString(valCols, new C1<String, String>() {
+            @Override public String apply(String s) {
+                return s + "=?";
+            }
+        }, "", ",", "");
+
+        return String.format("UPDATE %s.%s SET %s WHERE %s", schema, tblName, params, where(keyCols, 1));
+    }
+
+    /**
+     * @return {@code True} if database support merge operation.
+     */
+    public boolean hasMerge() {
+        return false;
+    }
+
+    /**
+     * Construct merge query.
+     * @param schema Database schema name.
+     * @param tblName Database table name.
+     * @param keyCols Database key columns.
+     * @param uniqCols Database unique columns.
+     * @return Put query.
+     */
+    public String mergeQuery(String schema, String tblName, Collection<String> keyCols, Collection<String> uniqCols) {
+        return "";
+    }
+
+    /**
+     * Construct remove query.
+     *
+     * @param schema Database schema name.
+     * @param tblName Database table name.
+     * @param keyCols Database key columns.
+     * @return Remove query.
+     */
+    public String removeQuery(String schema, String tblName, Iterable<String> keyCols) {
+        String whereParams = mkString(keyCols, new C1<String, String>() {
+            @Override public String apply(String s) {
+                return s + "=?";
+            }
+        }, "", " AND ", "");
+
+        return String.format("DELETE FROM %s.%s WHERE %s", schema, tblName, whereParams);
+    }
+
+    /**
+     * Get max query parameters count.
+     *
+     * @return Max query parameters count.
+     */
+    public int getMaxParamsCnt() {
+        return maxParamsCnt;
+    }
+
+    /**
+     * Set max query parameters count.
+     *
+     * @param maxParamsCnt Max query parameters count.
+     */
+    public void setMaxParamsCnt(int maxParamsCnt) {
+        this.maxParamsCnt = maxParamsCnt;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/79f3a5f7/modules/schema-load/src/test/java/org/gridgain/grid/cache/store/auto/AutoCacheStoreSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/schema-load/src/test/java/org/gridgain/grid/cache/store/auto/AutoCacheStoreSelfTest.java b/modules/schema-load/src/test/java/org/gridgain/grid/cache/store/auto/AutoCacheStoreSelfTest.java
index 71abc2f..0fd4e7e 100644
--- a/modules/schema-load/src/test/java/org/gridgain/grid/cache/store/auto/AutoCacheStoreSelfTest.java
+++ b/modules/schema-load/src/test/java/org/gridgain/grid/cache/store/auto/AutoCacheStoreSelfTest.java
@@ -17,6 +17,7 @@
 
 package org.gridgain.grid.cache.store.auto;
 
+import org.gridgain.grid.cache.store.auto.dialect.*;
 import org.gridgain.grid.util.typedef.*;
 
 /**
@@ -32,8 +33,10 @@ public class AutoCacheStoreSelfTest extends AbstractAutoCacheStoreSelfTest {
     /**
      * @return Store.
      */
-    @Override protected H2PojoCacheStore store() {
-        H2PojoCacheStore store = new H2PojoCacheStore();
+    @Override protected PojoCacheStore store() {
+        PojoCacheStore store = new PojoCacheStore();
+
+        store.setDialect(new H2Dialect());
 
         store.setConnUrl("jdbc:h2:mem:test");
         store.setUser("sa");