You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/04/26 13:25:49 UTC

[38/50] [abbrv] ignite git commit: ignite-1794 Refactored hibernate modules, switched to hibernate 5.1

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/CacheHibernateStoreSessionListenerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/CacheHibernateStoreSessionListenerSelfTest.java b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/CacheHibernateStoreSessionListenerSelfTest.java
new file mode 100644
index 0000000..0010425
--- /dev/null
+++ b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/CacheHibernateStoreSessionListenerSelfTest.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.store.hibernate;
+
+import java.io.Serializable;
+import java.util.Map;
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import javax.cache.integration.CacheLoaderException;
+import javax.cache.integration.CacheWriterException;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.cache.store.CacheStoreSession;
+import org.apache.ignite.cache.store.CacheStoreSessionListener;
+import org.apache.ignite.cache.store.CacheStoreSessionListenerAbstractSelfTest;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcStoreSessionListener;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.resources.CacheStoreSessionResource;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.resource.transaction.spi.TransactionStatus;
+
+/**
+ * Tests for {@link CacheJdbcStoreSessionListener}.
+ */
+public class CacheHibernateStoreSessionListenerSelfTest extends CacheStoreSessionListenerAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected Factory<? extends CacheStore<Integer, Integer>> storeFactory() {
+        return new Factory<CacheStore<Integer, Integer>>() {
+            @Override public CacheStore<Integer, Integer> create() {
+                return new Store();
+            }
+        };
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Factory<CacheStoreSessionListener> sessionListenerFactory() {
+        return new Factory<CacheStoreSessionListener>() {
+            @Override public CacheStoreSessionListener create() {
+                CacheHibernateStoreSessionListener lsnr = new CacheHibernateStoreSessionListener();
+
+                SessionFactory sesFactory = new Configuration().
+                    setProperty("hibernate.connection.url", URL).
+                    addAnnotatedClass(Table1.class).
+                    addAnnotatedClass(Table2.class).
+                    buildSessionFactory();
+
+                lsnr.setSessionFactory(sesFactory);
+
+                return lsnr;
+            }
+        };
+    }
+
+    /**
+     */
+    private static class Store extends CacheStoreAdapter<Integer, Integer> {
+        /** */
+        private static String SES_CONN_KEY = "ses_conn";
+
+        /** */
+        @CacheStoreSessionResource
+        private CacheStoreSession ses;
+
+        /** {@inheritDoc} */
+        @Override public void loadCache(IgniteBiInClosure<Integer, Integer> clo, Object... args) {
+            loadCacheCnt.incrementAndGet();
+
+            checkSession();
+        }
+
+        /** {@inheritDoc} */
+        @Override public Integer load(Integer key) throws CacheLoaderException {
+            loadCnt.incrementAndGet();
+
+            checkSession();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void write(Cache.Entry<? extends Integer, ? extends Integer> entry)
+            throws CacheWriterException {
+            writeCnt.incrementAndGet();
+
+            checkSession();
+
+            if (write.get()) {
+                Session hibSes = ses.attachment();
+
+                switch (ses.cacheName()) {
+                    case "cache1":
+                        hibSes.save(new Table1(entry.getKey(), entry.getValue()));
+
+                        break;
+
+                    case "cache2":
+                        if (fail.get())
+                            throw new CacheWriterException("Expected failure.");
+
+                        hibSes.save(new Table2(entry.getKey(), entry.getValue()));
+
+                        break;
+
+                    default:
+                        throw new CacheWriterException("Wring cache: " + ses.cacheName());
+                }
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void delete(Object key) throws CacheWriterException {
+            deleteCnt.incrementAndGet();
+
+            checkSession();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void sessionEnd(boolean commit) {
+            assertNull(ses.attachment());
+        }
+
+        /**
+         */
+        private void checkSession() {
+            Session hibSes = ses.attachment();
+
+            assertNotNull(hibSes);
+
+            assertTrue(hibSes.isOpen());
+
+            Transaction tx = hibSes.getTransaction();
+
+            assertNotNull(tx);
+
+            if (ses.isWithinTransaction())
+                assertEquals(TransactionStatus.ACTIVE, tx.getStatus());
+            else
+                assertFalse("Unexpected status: " + tx.getStatus(), tx.getStatus() == TransactionStatus.ACTIVE);
+
+            verifySameInstance(hibSes);
+        }
+
+        /**
+         * @param hibSes Session.
+         */
+        private void verifySameInstance(Session hibSes) {
+            Map<String, Session> props = ses.properties();
+
+            Session sesConn = props.get(SES_CONN_KEY);
+
+            if (sesConn == null)
+                props.put(SES_CONN_KEY, hibSes);
+            else {
+                assertSame(hibSes, sesConn);
+
+                reuseCnt.incrementAndGet();
+            }
+        }
+    }
+
+    /**
+     */
+    @Entity
+    @Table(name = "Table1")
+    private static class Table1 implements Serializable {
+        /** */
+        @Id
+        @GeneratedValue(strategy = GenerationType.IDENTITY)
+        @Column(name = "id")
+        private Integer id;
+
+        /** */
+        @Column(name = "key")
+        private int key;
+
+        /** */
+        @Column(name = "value")
+        private int value;
+
+        /**
+         * @param key Key.
+         * @param value Value.
+         */
+        private Table1(int key, int value) {
+            this.key = key;
+            this.value = value;
+        }
+    }
+
+    /**
+     */
+    @Entity
+    @Table(name = "Table2")
+    private static class Table2 implements Serializable {
+        /** */
+        @Id
+        @GeneratedValue(strategy = GenerationType.IDENTITY)
+        @Column(name = "id")
+        private Integer id;
+
+        /** */
+        @Column(name = "key")
+        private int key;
+
+        /** */
+        @Column(name = "value")
+        private int value;
+
+        /**
+         * @param key Key.
+         * @param value Value.
+         */
+        private Table2(int key, int value) {
+            this.key = key;
+            this.value = value;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/hibernate.cfg.xml
----------------------------------------------------------------------
diff --git a/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/hibernate.cfg.xml b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/hibernate.cfg.xml
new file mode 100644
index 0000000..3822b31
--- /dev/null
+++ b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/hibernate.cfg.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+
+<!DOCTYPE hibernate-configuration PUBLIC
+        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+    <session-factory>
+        <!-- Show SQL. -->
+        <property name="show_sql">true</property>
+
+        <!-- Database connection settings (private in-memory database). -->
+        <property name="connection.url">jdbc:h2:mem:example;DB_CLOSE_DELAY=-1</property>
+
+        <!-- Only validate the database schema on startup in production mode. -->
+        <property name="hbm2ddl.auto">update</property>
+
+        <!-- H2 dialect. -->
+        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
+
+        <!-- Mappings. -->
+        <mapping resource="org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml"/>
+    </session-factory>
+</hibernate-configuration>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/package-info.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/package-info.java b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/package-info.java
new file mode 100644
index 0000000..8af9886
--- /dev/null
+++ b/modules/hibernate-5.1/src/test/java/org/apache/ignite/cache/store/hibernate/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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 description. -->
+ * Contains internal tests or test related classes and interfaces.
+ */
+package org.apache.ignite.cache.store.hibernate;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteBinaryHibernate5TestSuite.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteBinaryHibernate5TestSuite.java b/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteBinaryHibernate5TestSuite.java
new file mode 100644
index 0000000..d539511
--- /dev/null
+++ b/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteBinaryHibernate5TestSuite.java
@@ -0,0 +1,37 @@
+/*
+ * 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.testsuites;
+
+import junit.framework.TestSuite;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.testframework.config.GridTestProperties;
+
+/**
+ *
+ */
+public class IgniteBinaryHibernate5TestSuite extends TestSuite {
+    /**
+     * @return Test suite.
+     * @throws Exception If failed.
+     */
+    public static TestSuite suite() throws Exception {
+        GridTestProperties.setProperty(GridTestProperties.MARSH_CLASS_NAME, BinaryMarshaller.class.getName());
+
+        return IgniteHibernate5TestSuite.suite();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteHibernate5TestSuite.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteHibernate5TestSuite.java b/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteHibernate5TestSuite.java
new file mode 100644
index 0000000..3d7c4ee
--- /dev/null
+++ b/modules/hibernate-5.1/src/test/java/org/apache/ignite/testsuites/IgniteHibernate5TestSuite.java
@@ -0,0 +1,57 @@
+/*
+ * 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.testsuites;
+
+import junit.framework.TestSuite;
+import org.apache.ignite.cache.hibernate.HibernateL2CacheConfigurationSelfTest;
+import org.apache.ignite.cache.hibernate.HibernateL2CacheSelfTest;
+import org.apache.ignite.cache.hibernate.HibernateL2CacheTransactionalSelfTest;
+import org.apache.ignite.cache.hibernate.HibernateL2CacheTransactionalUseSyncSelfTest;
+import org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreNodeRestartTest;
+import org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreSelfTest;
+import org.apache.ignite.cache.store.hibernate.CacheHibernateStoreFactorySelfTest;
+import org.apache.ignite.cache.store.hibernate.CacheHibernateStoreSessionListenerSelfTest;
+
+/**
+ * Hibernate integration tests.
+ */
+public class IgniteHibernate5TestSuite extends TestSuite {
+    /**
+     * @return Test suite.
+     * @throws Exception Thrown in case of the failure.
+     */
+    public static TestSuite suite() throws Exception {
+        TestSuite suite = new TestSuite("Hibernate5 Integration Test Suite");
+
+        // Hibernate L2 cache.
+        suite.addTestSuite(HibernateL2CacheSelfTest.class);
+        suite.addTestSuite(HibernateL2CacheTransactionalSelfTest.class);
+        suite.addTestSuite(HibernateL2CacheTransactionalUseSyncSelfTest.class);
+        suite.addTestSuite(HibernateL2CacheConfigurationSelfTest.class);
+
+        suite.addTestSuite(CacheHibernateBlobStoreSelfTest.class);
+
+        suite.addTestSuite(CacheHibernateBlobStoreNodeRestartTest.class);
+
+        suite.addTestSuite(CacheHibernateStoreSessionListenerSelfTest.class);
+
+        suite.addTestSuite(CacheHibernateStoreFactorySelfTest.class);
+
+        return suite;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/pom.xml b/modules/hibernate-core/pom.xml
new file mode 100644
index 0000000..91ec68b
--- /dev/null
+++ b/modules/hibernate-core/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>ignite-hibernate-core</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+    <url>http://ignite.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-jta</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <testResources>
+            <testResource>
+                <directory>src/main/java</directory>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </testResource>
+            <testResource>
+                <directory>src/test/java</directory>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </testResource>
+        </testResources>
+
+        <plugins>
+            <!-- Generate the OSGi MANIFEST.MF for this bundle. -->
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyAdapter.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyAdapter.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyAdapter.java
new file mode 100644
index 0000000..557b018
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyAdapter.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Common interface used to implement Hibernate L2 cache access strategies.
+ * <p>
+ * The expected sequences of steps related to various CRUD operations executed by Hibernate are:
+ * <p>
+ * Insert:
+ * <ul>
+ *     <li>Start DB transaction.</li>
+ *     <li>Execute database insert.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#insert}.</li>
+ *     <li>Commit DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#afterInsert}.</li>
+ * </ul>
+ * In case if some step fails and DB transaction is rolled back then
+ * {@link HibernateAccessStrategyAdapter#afterInsert} is not called.
+ * <p>
+ * Update:
+ * <ul>
+ *     <li>Start DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#lock}.</li>
+ *     <li>Execute database update.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#update}.</li>
+ *     <li>Commit DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#afterUpdate}.</li>
+ * </ul>
+ * In case if {@link HibernateAccessStrategyAdapter#lock} was called, but some other step fails and DB
+ * transaction is rolled back then {@link HibernateAccessStrategyAdapter#unlock} is called for all locked keys.
+ * <p>
+ * Delete:
+ * <ul>
+ *     <li>Start DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#lock} for removing key.</li>
+ *     <li>Execute database delete.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#remove}.</li>
+ *     <li>Commit DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#unlock}.</li>
+ * </ul>
+ * In case if {@link HibernateAccessStrategyAdapter#lock} was called, but some other step fails and DB
+ * transaction is rolled back then {@link HibernateAccessStrategyAdapter#unlock} is called for all locked keys.
+ * <p>
+ * In case if custom SQL update query is executed Hibernate clears entire cache region,
+ * for this case operations sequence is:
+ * <ul>
+ *     <li>Start DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#lockRegion}.</li>
+ *     <li>Execute database query.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#removeAll}.</li>
+ *     <li>Commit DB transaction.</li>
+ *     <li>Call {@link HibernateAccessStrategyAdapter#unlockRegion}.</li>
+ * </ul>
+ */
+public abstract class HibernateAccessStrategyAdapter {
+    /** */
+    protected final HibernateCacheProxy cache;
+
+    /** */
+    private final HibernateExceptionConverter eConverter;
+
+    /** Grid. */
+    protected final Ignite ignite;
+
+    /** */
+    protected final IgniteLogger log;
+
+    /**
+     * @param ignite Node.
+     * @param cache Cache.
+     * @param eConverter Exception converter.
+     */
+    protected HibernateAccessStrategyAdapter(Ignite ignite,
+        HibernateCacheProxy cache,
+        HibernateExceptionConverter eConverter) {
+        this.cache = cache;
+        this.ignite = ignite;
+        this.eConverter = eConverter;
+
+        log = ignite.log().getLogger(getClass());
+    }
+
+    /**
+     * @param e Exception.
+     * @return Runtime exception to be thrown.
+     */
+    final RuntimeException convertException(Exception e) {
+        return eConverter.convert(e);
+    }
+
+    /**
+     * @param key Key.
+     * @return Cached value.
+     */
+    @Nullable public Object get(Object key) {
+        try {
+            return cache.get(key);
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /**
+     * @param key Key.
+     * @param val Value.
+     * @param minimalPutOverride MinimalPut flag
+     */
+    public void putFromLoad(Object key, Object val, boolean minimalPutOverride) {
+        putFromLoad(key, val);
+    }
+
+    /**
+     * Puts in cache value loaded from the database.
+     *
+     * @param key Key.
+     * @param val Value.
+     */
+    public void putFromLoad(Object key, Object val) {
+        try {
+            cache.put(key, val);
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /**
+     * Called during database transaction execution before Hibernate attempts to update or remove given key.
+     *
+     * @param key Key.
+     */
+    public abstract void lock(Object key);
+
+    /**
+     * Called after Hibernate failed to update or successfully removed given key.
+     *
+     * @param key Key.
+     */
+    public abstract void unlock(Object key);
+
+    /**
+     * Called after Hibernate updated object in the database but before transaction completed.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @return {@code True} if operation updated cache.
+     */
+    public abstract boolean update(Object key, Object val);
+
+    /**
+     * Called after Hibernate updated object in the database and transaction successfully completed.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @return {@code True} if operation updated cache.
+     */
+    public abstract boolean afterUpdate(Object key, Object val);
+
+    /**
+     * Called after Hibernate inserted object in the database but before transaction completed.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @return {@code True} if operation updated cache.
+     */
+    public abstract boolean insert(Object key, Object val);
+
+    /**
+     * Called after Hibernate inserted object in the database and transaction successfully completed.
+     *
+     * @param key Key.
+     * @param val Value.
+     * @return {@code True} if operation updated cache.
+     */
+    public abstract boolean afterInsert(Object key, Object val);
+
+    /**
+     * Called after Hibernate removed object from database but before transaction completed.
+     *
+     * @param key Key,
+     */
+    public abstract void remove(Object key);
+
+    /**
+     * Called to remove object from cache without regard to transaction.
+     *
+     * @param key Key.
+     */
+    public void evict(Object key) {
+        evict(ignite, cache, key);
+    }
+
+    /**
+     * Called to remove all data from cache without regard to transaction.
+     */
+    public void evictAll() {
+        try {
+            evictAll(cache);
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /**
+     * Called during database transaction execution to clear entire cache region after
+     * Hibernate executed database update, but before transaction completed.
+     */
+    public final void removeAll() {
+        evictAll();
+    }
+
+    /**
+     * Called during database transaction execution before Hibernate executed
+     * update operation which should invalidate entire cache region.
+     */
+    public void lockRegion() {
+        // No-op.
+    }
+
+    /**
+     * Called after transaction clearing entire cache region completed.
+     */
+    public void unlockRegion() {
+        // No-op.
+    }
+
+    /**
+     * Called to remove object from cache without regard to transaction.
+     *
+     * @param ignite Grid.
+     * @param cache Cache.
+     * @param key Key.
+     */
+    public static void evict(Ignite ignite, HibernateCacheProxy cache, Object key) {
+        key = cache.keyTransformer().transform(key);
+
+        ignite.compute(ignite.cluster()).call(new ClearKeyCallable(key, cache.name()));
+    }
+
+    /**
+     * Called to remove all data from cache without regard to transaction.
+     *
+     * @param cache Cache.
+     * @throws IgniteCheckedException If failed.
+     */
+    public static void evictAll(IgniteInternalCache<Object, Object> cache) throws IgniteCheckedException {
+        cache.clear();
+    }
+
+    /**
+     * Callable invalidates given key.
+     */
+    private static class ClearKeyCallable implements IgniteCallable<Void>, Externalizable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        @IgniteInstanceResource
+        private Ignite ignite;
+
+        /** */
+        private Object key;
+
+        /** */
+        private String cacheName;
+
+        /**
+         * Empty constructor required by {@link Externalizable}.
+         */
+        public ClearKeyCallable() {
+            // No-op.
+        }
+
+        /**
+         * @param key Key to clear.
+         * @param cacheName Cache name.
+         */
+        private ClearKeyCallable(Object key, String cacheName) {
+            this.key = key;
+            this.cacheName = cacheName;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Void call() throws IgniteCheckedException {
+            IgniteInternalCache<Object, Object> cache = ((IgniteKernal)ignite).getCache(cacheName);
+
+            assert cache != null;
+
+            cache.clearLocally(key);
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject(key);
+
+            U.writeString(out, cacheName);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            key = in.readObject();
+
+            cacheName = U.readString(in);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyFactory.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyFactory.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyFactory.java
new file mode 100644
index 0000000..0226c1c
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateAccessStrategyFactory.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.configuration.TransactionConfiguration;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.typedef.G;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ * Access strategy factory.
+ */
+public class HibernateAccessStrategyFactory {
+    /** */
+    private final HibernateKeyTransformer keyTransformer;
+
+    /** */
+    private final HibernateExceptionConverter eConverter;
+
+    /**
+     * Hibernate L2 cache grid name property name.
+     *
+     * @deprecated Use {@link #IGNITE_INSTANCE_NAME_PROPERTY}.
+     *      If {@link #IGNITE_INSTANCE_NAME_PROPERTY} is specified it takes precedence.
+     */
+    @Deprecated
+    public static final String GRID_NAME_PROPERTY = "org.apache.ignite.hibernate.grid_name";
+
+    /** Hibernate L2 cache Ignite instance name property name. */
+    public static final String IGNITE_INSTANCE_NAME_PROPERTY = "org.apache.ignite.hibernate.ignite_instance_name";
+
+    /** Default cache property name. */
+    public static final String DFLT_CACHE_NAME_PROPERTY = "org.apache.ignite.hibernate.default_cache";
+
+    /** Property prefix used to specify region name to cache name mapping. */
+    public static final String REGION_CACHE_PROPERTY = "org.apache.ignite.hibernate.region_cache.";
+
+    /** */
+    public static final String DFLT_ACCESS_TYPE_PROPERTY = "org.apache.ignite.hibernate.default_access_type";
+
+    /** */
+    public static final String GRID_CONFIG_PROPERTY = "org.apache.ignite.hibernate.grid_config";
+
+    /** Grid providing caches. */
+    private Ignite ignite;
+
+    /** Default cache. */
+    private HibernateCacheProxy dfltCache;
+
+    /** Region name to cache name mapping. */
+    private final Map<String, String> regionCaches = new HashMap<>();
+
+    /** */
+    private final ThreadLocal threadLoc = new ThreadLocal();
+
+    /** */
+    private final ConcurrentHashMap<String, ThreadLocal> threadLocMap = new ConcurrentHashMap<>();
+
+    /**
+     * @param keyTransformer Key transformer.
+     * @param eConverter Exception converter.
+     */
+    HibernateAccessStrategyFactory(HibernateKeyTransformer keyTransformer, HibernateExceptionConverter eConverter) {
+        this.keyTransformer = keyTransformer;
+        this.eConverter = eConverter;
+    }
+
+    /**
+     * @param props Properties.
+     */
+    public void start(Properties props)  {
+        String gridCfg = props.getProperty(GRID_CONFIG_PROPERTY);
+        String igniteInstanceName = props.getProperty(IGNITE_INSTANCE_NAME_PROPERTY);
+
+        if (igniteInstanceName == null)
+            igniteInstanceName = props.getProperty(GRID_NAME_PROPERTY);
+
+        if (gridCfg != null) {
+            try {
+                ignite = G.start(gridCfg);
+            }
+            catch (IgniteException e) {
+                throw eConverter.convert(e);
+            }
+        }
+        else
+            ignite = Ignition.ignite(igniteInstanceName);
+
+        for (Map.Entry<Object, Object> prop : props.entrySet()) {
+            String key = prop.getKey().toString();
+
+            if (key.startsWith(REGION_CACHE_PROPERTY)) {
+                String regionName = key.substring(REGION_CACHE_PROPERTY.length());
+
+                String cacheName = prop.getValue().toString();
+
+                if (((IgniteKernal)ignite).getCache(cacheName) == null)
+                    throw new IllegalArgumentException("Cache '" + cacheName + "' specified for region '" + regionName + "' " +
+                        "is not configured.");
+
+                regionCaches.put(regionName, cacheName);
+            }
+        }
+
+        String dfltCacheName = props.getProperty(DFLT_CACHE_NAME_PROPERTY);
+
+        if (dfltCacheName != null) {
+            IgniteInternalCache<Object, Object> dfltCache = ((IgniteKernal)ignite).getCache(dfltCacheName);
+
+            if (dfltCache == null)
+                throw new IllegalArgumentException("Cache specified as default is not configured: " + dfltCacheName);
+
+            this.dfltCache = new HibernateCacheProxy(dfltCache, keyTransformer);
+        }
+
+        IgniteLogger log = ignite.log().getLogger(getClass());
+
+        if (log.isDebugEnabled())
+            log.debug("HibernateRegionFactory started [igniteInstanceName=" + igniteInstanceName + ']');
+    }
+
+    /**
+     * @return Ignite node.
+     */
+    public Ignite node() {
+        return ignite;
+    }
+
+    /**
+     * @param regionName L2 cache region name.
+     * @return Cache for given region.
+     */
+    HibernateCacheProxy regionCache(String regionName) {
+        String cacheName = regionCaches.get(regionName);
+
+        if (cacheName == null) {
+            if (dfltCache != null)
+                return dfltCache;
+
+            cacheName = regionName;
+        }
+
+        IgniteInternalCache<Object, Object> cache = ((IgniteKernal)ignite).getCache(cacheName);
+
+        if (cache == null)
+            throw new IllegalArgumentException("Cache '" + cacheName + "' for region '" + regionName + "' is not configured.");
+
+        return new HibernateCacheProxy(cache, keyTransformer);
+    }
+
+    /**
+     * @param cache Cache.
+     * @return Access strategy implementation.
+     */
+    HibernateAccessStrategyAdapter createReadOnlyStrategy(HibernateCacheProxy cache) {
+        return new HibernateReadOnlyAccessStrategy(ignite, cache, eConverter);
+    }
+
+    /**
+     * @param cache Cache.
+     * @return Access strategy implementation.
+     */
+    HibernateAccessStrategyAdapter createNonStrictReadWriteStrategy(HibernateCacheProxy cache) {
+        ThreadLocal threadLoc = threadLocMap.get(cache.name());
+
+        if (threadLoc == null) {
+            ThreadLocal old = threadLocMap.putIfAbsent(cache.name(), threadLoc = new ThreadLocal());
+
+            if (old != null)
+                threadLoc = old;
+        }
+
+        return new HibernateNonStrictAccessStrategy(ignite, cache, threadLoc, eConverter);
+    }
+
+    /**
+     * @param cache Cache.
+     * @return Access strategy implementation.
+     */
+    HibernateAccessStrategyAdapter createReadWriteStrategy(HibernateCacheProxy cache) {
+        if (cache.configuration().getAtomicityMode() != TRANSACTIONAL)
+            throw new IllegalArgumentException("Hibernate READ-WRITE access strategy must have Ignite cache with " +
+                "'TRANSACTIONAL' atomicity mode: " + cache.name());
+
+        return new HibernateReadWriteAccessStrategy(ignite, cache, threadLoc, eConverter);
+    }
+
+    /**
+     * @param cache Cache.
+     * @return Access strategy implementation.
+     */
+    HibernateAccessStrategyAdapter createTransactionalStrategy(HibernateCacheProxy cache) {
+        if (cache.configuration().getAtomicityMode() != TRANSACTIONAL)
+            throw new IllegalArgumentException("Hibernate TRANSACTIONAL access strategy must have Ignite cache with " +
+                "'TRANSACTIONAL' atomicity mode: " + cache.name());
+
+        TransactionConfiguration txCfg = ignite.configuration().getTransactionConfiguration();
+
+        if (txCfg == null ||
+            (txCfg.getTxManagerFactory() == null
+                && txCfg.getTxManagerLookupClassName() == null
+                && cache.configuration().getTransactionManagerLookupClassName() == null)) {
+            throw new IllegalArgumentException("Hibernate TRANSACTIONAL access strategy must have Ignite with " +
+                "Factory<TransactionManager> configured (see IgniteConfiguration." +
+                "getTransactionConfiguration().setTxManagerFactory()): " + cache.name());
+        }
+
+        return new HibernateTransactionalAccessStrategy(ignite, cache, eConverter);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
new file mode 100644
index 0000000..3d439dd
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateCacheProxy.java
@@ -0,0 +1,801 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import javax.cache.Cache;
+import javax.cache.expiry.ExpiryPolicy;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.EntryProcessorResult;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheEntry;
+import org.apache.ignite.cache.CacheMetrics;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cluster.ClusterGroup;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
+import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.mxbean.CacheMetricsMXBean;
+import org.apache.ignite.transactions.Transaction;
+import org.apache.ignite.transactions.TransactionConcurrency;
+import org.apache.ignite.transactions.TransactionIsolation;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Hibernate cache proxy used to substitute hibernate keys with ignite keys.
+ */
+public class HibernateCacheProxy implements IgniteInternalCache<Object, Object> {
+    /** Delegate. */
+    private final IgniteInternalCache<Object, Object> delegate;
+
+    /** Transformer. */
+    private final HibernateKeyTransformer keyTransformer;
+
+    /**
+     * @param delegate Delegate.
+     * @param keyTransformer Key keyTransformer.
+     */
+    HibernateCacheProxy(
+        IgniteInternalCache<Object, Object> delegate,
+        HibernateKeyTransformer keyTransformer
+    ) {
+        assert delegate != null;
+        assert keyTransformer != null;
+
+        this.delegate = delegate;
+        this.keyTransformer = keyTransformer;
+    }
+
+    /**
+     * @return HibernateKeyTransformer
+     */
+    public HibernateKeyTransformer keyTransformer(){
+        return keyTransformer;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return delegate.name();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean skipStore() {
+        return delegate.skipStore();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache setSkipStore(boolean skipStore) {
+        return delegate.setSkipStore(skipStore);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean containsKey(Object key) {
+        return delegate.containsKey(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> containsKeyAsync(Object key) {
+        return delegate.containsKeyAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean containsKeys(Collection keys) {
+        return delegate.containsKey(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> containsKeysAsync(Collection keys) {
+        return delegate.containsKeysAsync(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object localPeek(
+        Object key,
+        CachePeekMode[] peekModes,
+        @Nullable IgniteCacheExpiryPolicy plc
+    ) throws IgniteCheckedException {
+        return delegate.localPeek(keyTransformer.transform(key), peekModes, plc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterable<Cache.Entry<Object, Object>> localEntries(
+        CachePeekMode[] peekModes
+    ) throws IgniteCheckedException {
+        return delegate.localEntries(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object get(Object key) throws IgniteCheckedException {
+        return delegate.get(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public CacheEntry getEntry(Object key) throws IgniteCheckedException {
+        return delegate.getEntry(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getAsync(Object key) {
+        return delegate.getAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<CacheEntry<Object, Object>> getEntryAsync(Object key) {
+        return delegate.getEntryAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map getAll(@Nullable Collection keys) throws IgniteCheckedException {
+        return delegate.getAll(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<CacheEntry<Object, Object>> getEntries(
+        @Nullable Collection keys) throws IgniteCheckedException {
+        return delegate.getEntries(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Map<Object, Object>> getAllAsync(@Nullable Collection keys) {
+        return delegate.getAllAsync(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Collection<CacheEntry<Object,Object>>> getEntriesAsync(
+        @Nullable Collection keys
+    ) {
+        return delegate.getEntriesAsync(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object getAndPut(Object key, Object val) throws IgniteCheckedException {
+        return delegate.getAndPut(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getAndPutAsync(Object key, Object val) {
+        return delegate.getAndPutAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean put(Object key, Object val) throws IgniteCheckedException {
+        return delegate.put(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> putAsync(Object key, Object val) {
+        return delegate.putAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object getAndPutIfAbsent(Object key, Object val) throws IgniteCheckedException {
+        return delegate.getAndPutIfAbsent(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getAndPutIfAbsentAsync(Object key, Object val) {
+        return delegate.getAndPutIfAbsentAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean putIfAbsent(Object key, Object val) throws IgniteCheckedException {
+        return delegate.putIfAbsent(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> putIfAbsentAsync(Object key, Object val) {
+        return delegate.putIfAbsentAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object getAndReplace(Object key, Object val) throws IgniteCheckedException {
+        return delegate.getAndReplace(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getAndReplaceAsync(Object key, Object val) {
+        return delegate.getAndReplaceAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean replace(Object key, Object val) throws IgniteCheckedException {
+        return delegate.replace(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> replaceAsync(Object key, Object val) {
+        return delegate.replaceAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean replace(Object key, Object oldVal, Object newVal) throws IgniteCheckedException {
+        return delegate.replace(keyTransformer.transform(key), oldVal, newVal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> replaceAsync(Object key, Object oldVal, Object newVal) {
+        return delegate.replaceAsync(keyTransformer.transform(key), oldVal, newVal);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putAll(@Nullable Map m) throws IgniteCheckedException {
+        delegate.putAll(transform(m));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> putAllAsync(@Nullable Map m) {
+        return delegate.putAllAsync(transform(m));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set keySet() {
+        return delegate.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set keySetx() {
+        return delegate.keySetx();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set primaryKeySet() {
+        return delegate.primaryKeySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterable values() {
+        return delegate.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<Cache.Entry<Object, Object>> entrySet() {
+        return delegate.entrySet();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Set<Cache.Entry<Object,Object>> entrySet(int part) {
+        return delegate.entrySet(part);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<Cache.Entry<Object, Object>> entrySetx(CacheEntryPredicate... filter) {
+        return delegate.entrySetx(filter);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Transaction txStart(
+        TransactionConcurrency concurrency,
+        TransactionIsolation isolation
+    ) {
+        return delegate.txStart(concurrency, isolation);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridNearTxLocal txStartEx(
+        TransactionConcurrency concurrency,
+        TransactionIsolation isolation
+    ) {
+        return delegate.txStartEx(concurrency, isolation);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Transaction txStart(
+        TransactionConcurrency concurrency,
+        TransactionIsolation isolation,
+        long timeout,
+        int txSize
+    ) {
+        return delegate.txStart(concurrency, isolation, timeout, txSize);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridNearTxLocal tx() {
+        return delegate.tx();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean evict(Object key) {
+        return delegate.evict(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void evictAll(@Nullable Collection keys) {
+        delegate.evictAll(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearLocally(boolean srv, boolean near, boolean readers) {
+        delegate.clearLocally(srv, near, readers);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean clearLocally(Object key) {
+        return delegate.clearLocally(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearLocallyAll(Set keys, boolean srv, boolean near, boolean readers) {
+        delegate.clearLocallyAll((Set<?>)transform(keys), srv, near, readers);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clear(Object key) throws IgniteCheckedException {
+        delegate.clear(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearAll(Set keys) throws IgniteCheckedException {
+        delegate.clearAll((Set<?>)transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clear() throws IgniteCheckedException {
+        delegate.clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> clearAsync() {
+        return delegate.clearAsync();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> clearAsync(Object key) {
+        return delegate.clearAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> clearAllAsync(Set keys) {
+        return delegate.clearAllAsync((Set<?>)transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object getAndRemove(Object key) throws IgniteCheckedException {
+        return delegate.getAndRemove(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getAndRemoveAsync(Object key) {
+        return delegate.getAndRemoveAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean remove(Object key) throws IgniteCheckedException {
+        return delegate.remove(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> removeAsync(Object key) {
+        return delegate.removeAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean remove(Object key, Object val) throws IgniteCheckedException {
+        return delegate.remove(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> removeAsync(Object key, Object val) {
+        return delegate.removeAsync(keyTransformer.transform(key), val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeAll(@Nullable Collection keys) throws IgniteCheckedException {
+        delegate.removeAll(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> removeAllAsync(@Nullable Collection keys) {
+        return delegate.removeAllAsync(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeAll() throws IgniteCheckedException {
+        delegate.removeAll();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> removeAllAsync() {
+        return delegate.removeAllAsync();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean lock(Object key, long timeout) throws IgniteCheckedException {
+        return delegate.lock(keyTransformer.transform(key), timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> lockAsync(Object key, long timeout) {
+        return delegate.lockAsync(keyTransformer.transform(key), timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean lockAll(@Nullable Collection keys, long timeout) throws IgniteCheckedException {
+        return delegate.lockAll(transform(keys), timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Boolean> lockAllAsync(@Nullable Collection keys, long timeout) {
+        return delegate.lockAllAsync(transform(keys), timeout);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void unlock(Object key) throws IgniteCheckedException {
+        delegate.unlock(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void unlockAll(@Nullable Collection keys) throws IgniteCheckedException {
+        delegate.unlockAll(transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isLocked(Object key) {
+        return delegate.isLocked(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isLockedByThread(Object key) {
+        return delegate.isLockedByThread(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        return delegate.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long sizeLong() {
+        return delegate.sizeLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int localSize(CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.localSize(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long localSizeLong(CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.localSizeLong(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long localSizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.localSizeLong(partition, peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size(CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.size(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long sizeLong(CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.sizeLong(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long sizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        return delegate.sizeLong(partition, peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Integer> sizeAsync(CachePeekMode[] peekModes) {
+        return delegate.sizeAsync(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Long> sizeLongAsync(CachePeekMode[] peekModes) {
+        return delegate.sizeLongAsync(peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Long> sizeLongAsync(int partition, CachePeekMode[] peekModes) {
+        return delegate.sizeLongAsync(partition, peekModes);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int nearSize() {
+        return delegate.nearSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int primarySize() {
+        return delegate.primarySize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long primarySizeLong() {
+        return delegate.primarySizeLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheConfiguration configuration() {
+        return delegate.configuration();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Affinity affinity() {
+        return delegate.affinity();
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheMetrics clusterMetrics() {
+        return delegate.clusterMetrics();
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheMetrics clusterMetrics(ClusterGroup grp) {
+        return delegate.clusterMetrics(grp);
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheMetrics localMetrics() {
+        return delegate.localMetrics();
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheMetricsMXBean clusterMxBean() {
+        return delegate.clusterMxBean();
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheMetricsMXBean localMxBean() {
+        return delegate.localMxBean();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long offHeapEntriesCount() {
+        return delegate.offHeapEntriesCount();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long offHeapAllocatedSize() {
+        return delegate.offHeapAllocatedSize();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> rebalance() {
+        return delegate.rebalance();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache forSubjectId(UUID subjId) {
+        return delegate.forSubjectId(subjId);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Object getForcePrimary(Object key) throws IgniteCheckedException {
+        return delegate.getForcePrimary(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture getForcePrimaryAsync(Object key) {
+        return delegate.getForcePrimaryAsync(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map getAllOutTx(Set keys) throws IgniteCheckedException {
+        return delegate.getAllOutTx((Set<?>)transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Map<Object, Object>> getAllOutTxAsync(Set keys) {
+        return delegate.getAllOutTxAsync((Set<?>)transform(keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isIgfsDataCache() {
+        return delegate.isIgfsDataCache();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long igfsDataSpaceUsed() {
+        return delegate.igfsDataSpaceUsed();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isMongoDataCache() {
+        return delegate.isMongoDataCache();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isMongoMetaCache() {
+        return delegate.isMongoMetaCache();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public ExpiryPolicy expiry() {
+        return delegate.expiry();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache withExpiryPolicy(ExpiryPolicy plc) {
+        return delegate.withExpiryPolicy(plc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache withNoRetries() {
+        return delegate.withNoRetries();
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridCacheContext context() {
+        return delegate.context();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void localLoadCache(
+        @Nullable IgniteBiPredicate p,
+        @Nullable Object... args
+    ) throws IgniteCheckedException {
+        delegate.localLoadCache(p, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> localLoadCacheAsync(
+        @Nullable IgniteBiPredicate p,
+        @Nullable Object... args
+    ) {
+        return delegate.localLoadCacheAsync(p, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getTopologySafe(Object key) throws IgniteCheckedException {
+        return delegate.getTopologySafe(keyTransformer.transform(key));
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<Integer> lostPartitions() {
+        return delegate.lostPartitions();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public EntryProcessorResult invoke(
+        @Nullable AffinityTopologyVersion topVer,
+        Object key,
+        EntryProcessor entryProcessor,
+        Object... args
+    ) throws IgniteCheckedException {
+        return delegate.invoke(topVer, key, entryProcessor, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Map> invokeAllAsync(Map map, Object... args) {
+        return delegate.invokeAllAsync(map, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map invokeAll(Map map, Object... args) throws IgniteCheckedException {
+        return delegate.invokeAll(map, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Map> invokeAllAsync(Set keys, EntryProcessor entryProcessor, Object... args) {
+        return delegate.invokeAllAsync((Set<?>)transform(keys), entryProcessor, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map invokeAll(Set keys, EntryProcessor entryProcessor, Object... args) throws IgniteCheckedException {
+        return delegate.invokeAll((Set<?>)transform(keys), entryProcessor, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<EntryProcessorResult> invokeAsync(
+        Object key,
+        EntryProcessor entryProcessor,
+        Object... args
+    ) {
+        return delegate.invokeAsync(keyTransformer.transform(key), entryProcessor, args);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public EntryProcessorResult invoke(
+        Object key,
+        EntryProcessor entryProcessor,
+        Object... args
+    ) throws IgniteCheckedException {
+        return delegate.invoke(keyTransformer.transform(key), entryProcessor, args);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterator<Cache.Entry<Object,Object>> scanIterator(
+        boolean keepBinary,
+        @Nullable IgniteBiPredicate p
+    ) throws IgniteCheckedException {
+        return delegate.scanIterator(keepBinary, p);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> removeAllConflictAsync(Map drMap) throws IgniteCheckedException {
+        return delegate.removeAllConflictAsync(drMap);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeAllConflict(Map drMap) throws IgniteCheckedException {
+        delegate.removeAllConflictAsync(drMap);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<?> putAllConflictAsync(Map drMap) throws IgniteCheckedException {
+        return delegate.putAllConflictAsync(drMap);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putAllConflict(Map drMap) throws IgniteCheckedException {
+        delegate.putAllConflict(drMap);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache keepBinary() {
+        return delegate.keepBinary();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteInternalCache cache() {
+        return delegate.cache();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterator iterator() {
+        return delegate.iterator();
+    }
+
+    /**
+     * @param keys Keys.
+     */
+    private Collection<Object> transform(Collection<Object> keys) {
+        Collection<Object> res = new LinkedList<>();
+
+        for (Object o : keys)
+            res.add(keyTransformer.transform(o));
+
+        return res;
+    }
+
+    /**
+     * @param map Map.
+     */
+    private Map<Object, Object> transform(Map<Object, Object> map) {
+        Map<Object, Object> res = new HashMap<>();
+
+        Set<Map.Entry<Object, Object>> ents = map.entrySet();
+
+        for (Map.Entry<Object, Object> e : ents)
+            res.put(keyTransformer.transform(e.getKey()), e.getValue());
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateExceptionConverter.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateExceptionConverter.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateExceptionConverter.java
new file mode 100644
index 0000000..110bec5
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateExceptionConverter.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+/**
+ * Converts Ignite errors into Hibernate runtime exceptions.
+ */
+public interface HibernateExceptionConverter {
+    /**
+     * @param e Exception.
+     * @return Converted exception.
+     */
+    public RuntimeException convert(Exception e);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateKeyTransformer.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateKeyTransformer.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateKeyTransformer.java
new file mode 100644
index 0000000..97fc0e9
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateKeyTransformer.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+/**
+ * An interface for transforming hibernate keys to Ignite keys.
+ */
+public interface HibernateKeyTransformer {
+    /**
+     * @param key Hibernate key.
+     * @return Transformed key.
+     */
+    public Object transform(Object key);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
new file mode 100644
index 0000000..06c6f3d
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.util.GridLeanSet;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * Implementation of NONSTRICT_READ_WRITE cache access strategy.
+ * <p>
+ * Configuration of L2 cache and per-entity cache access strategy can be set in the
+ * Hibernate configuration file:
+ * <pre name="code" class="xml">
+ * &lt;hibernate-configuration&gt;
+ *     &lt;!-- Enable L2 cache. --&gt;
+ *     &lt;property name="cache.use_second_level_cache"&gt;true&lt;/property&gt;
+ *
+ *     &lt;!-- Use Ignite as L2 cache provider. --&gt;
+ *     &lt;property name="cache.region.factory_class"&gt;org.apache.ignite.cache.hibernate.HibernateRegionFactory&lt;/property&gt;
+ *
+ *     &lt;!-- Specify entity. --&gt;
+ *     &lt;mapping class="com.example.Entity"/&gt;
+ *
+ *     &lt;!-- Enable L2 cache with nonstrict-read-write access strategy for entity. --&gt;
+ *     &lt;class-cache class="com.example.Entity" usage="nonstrict-read-write"/&gt;
+ * &lt;/hibernate-configuration&gt;
+ * </pre>
+ * Also cache access strategy can be set using annotations:
+ * <pre name="code" class="java">
+ * &#064;javax.persistence.Entity
+ * &#064;javax.persistence.Cacheable
+ * &#064;org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+ * public class Entity { ... }
+ * </pre>
+ */
+public class HibernateNonStrictAccessStrategy extends HibernateAccessStrategyAdapter {
+    /** */
+    private final ThreadLocal<WriteContext> writeCtx;
+
+    /**
+     * @param ignite Grid.
+     * @param cache Cache.
+     * @param writeCtx Thread local instance used to track updates done during one Hibernate transaction.
+     * @param eConverter Exception converter.
+     */
+    HibernateNonStrictAccessStrategy(Ignite ignite,
+        HibernateCacheProxy cache,
+        ThreadLocal writeCtx,
+        HibernateExceptionConverter eConverter) {
+        super(ignite, cache, eConverter);
+
+        this.writeCtx = (ThreadLocal<WriteContext>)writeCtx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void lock(Object key) {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx == null)
+            writeCtx.set(ctx = new WriteContext());
+
+        ctx.locked(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void unlock(Object key) {
+        try {
+            WriteContext ctx = writeCtx.get();
+
+            if (ctx != null && ctx.unlocked(key)) {
+                writeCtx.remove();
+
+                ctx.updateCache(cache);
+            }
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean update(Object key, Object val) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean afterUpdate(Object key, Object val) {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx != null) {
+            ctx.updated(key, val);
+
+            unlock(key);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean insert(Object key, Object val) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean afterInsert(Object key, Object val) {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void remove(Object key) {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx != null)
+            ctx.removed(key);
+    }
+
+    /**
+     * Information about updates done during single database transaction.
+     */
+    @SuppressWarnings("TypeMayBeWeakened")
+    private static class WriteContext {
+        /** */
+        @GridToStringInclude
+        private Map<Object, Object> updates;
+
+        /** */
+        @GridToStringInclude
+        private Set<Object> rmvs;
+
+        /** */
+        @GridToStringInclude
+        private Set<Object> locked = new GridLeanSet<>();
+
+        /**
+         * Marks key as locked.
+         *
+         * @param key Key.
+         */
+        void locked(Object key) {
+            locked.add(key);
+        }
+
+        /**
+         * Marks key as unlocked.
+         *
+         * @param key Key.
+         * @return {@code True} if last locked key was unlocked.
+         */
+        boolean unlocked(Object key) {
+            locked.remove(key);
+
+            return locked.isEmpty();
+        }
+
+        /**
+         * Marks key as updated.
+         *
+         * @param key Key.
+         * @param val Value.
+         */
+        void updated(Object key, Object val) {
+            if (updates == null)
+                updates = new LinkedHashMap<>();
+
+            updates.put(key, val);
+        }
+
+        /**
+         * Marks key as removed.
+         *
+         * @param key Key.
+         */
+        void removed(Object key) {
+            if (rmvs == null)
+                rmvs = new GridLeanSet<>();
+
+            rmvs.add(key);
+        }
+
+        /**
+         * Updates cache.
+         *
+         * @param cache Cache.
+         * @throws IgniteCheckedException If failed.
+         */
+        void updateCache(HibernateCacheProxy cache) throws IgniteCheckedException {
+            if (!F.isEmpty(rmvs))
+                cache.removeAll(rmvs);
+
+            if (!F.isEmpty(updates))
+                cache.putAll(updates);
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(WriteContext.class, this);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1b19d3/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
new file mode 100644
index 0000000..a0957fd
--- /dev/null
+++ b/modules/hibernate-core/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.hibernate;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+
+/**
+ * Implementation of READ_ONLY cache access strategy.
+ * <p>
+ * Configuration of L2 cache and per-entity cache access strategy can be set in the
+ * Hibernate configuration file:
+ * <pre name="code" class="xml">
+ * &lt;hibernate-configuration&gt;
+ *     &lt;!-- Enable L2 cache. --&gt;
+ *     &lt;property name="cache.use_second_level_cache"&gt;true&lt;/property&gt;
+ *
+ *     &lt;!-- Use Ignite as L2 cache provider. --&gt;
+ *     &lt;property name="cache.region.factory_class"&gt;org.apache.ignite.cache.hibernate.HibernateRegionFactory&lt;/property&gt;
+ *
+ *     &lt;!-- Specify entity. --&gt;
+ *     &lt;mapping class="com.example.Entity"/&gt;
+ *
+ *     &lt;!-- Enable L2 cache with read-only access strategy for entity. --&gt;
+ *     &lt;class-cache class="com.example.Entity" usage="read-only"/&gt;
+ * &lt;/hibernate-configuration&gt;
+ * </pre>
+ * Also cache access strategy can be set using annotations:
+ * <pre name="code" class="java">
+ * &#064;javax.persistence.Entity
+ * &#064;javax.persistence.Cacheable
+ * &#064;org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
+ * public class Entity { ... }
+ * </pre>
+ *
+ */
+public class HibernateReadOnlyAccessStrategy extends HibernateAccessStrategyAdapter {
+    /**
+     * @param ignite Node.
+     * @param cache Cache.
+     * @param eConverter Exception converter.
+     */
+    public HibernateReadOnlyAccessStrategy(Ignite ignite,
+        HibernateCacheProxy cache,
+        HibernateExceptionConverter eConverter) {
+        super(ignite, cache, eConverter);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean insert(Object key, Object val) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean afterInsert(Object key, Object val) {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw convertException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void lock(Object key) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public void unlock(Object key) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public void remove(Object key) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean update(Object key, Object val) {
+        throw new UnsupportedOperationException("Updates are not supported for read-only access strategy.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean afterUpdate(Object key, Object val) {
+        throw new UnsupportedOperationException("Updates are not supported for read-only access strategy.");
+    }
+}
\ No newline at end of file