ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [4/5] ignite git commit: ignite-1794
Date Mon, 10 Apr 2017 09:23:37 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNaturalIdRegion.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNaturalIdRegion.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNaturalIdRegion.java
new file mode 100644
index 0000000..73ed23a
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNaturalIdRegion.java
@@ -0,0 +1,113 @@
+/*
+ * 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.hibernate.cache.CacheException;
+import org.hibernate.cache.internal.DefaultCacheKeysFactory;
+import org.hibernate.cache.spi.CacheDataDescription;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.persister.entity.EntityPersister;
+
+/**
+ * Implementation of {@link NaturalIdRegion}. This region is used to store naturalId data.
+ * <p>
+ * L2 cache for entity naturalId and target cache region 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)
+ * &#064;org.hibernate.annotations.NaturalIdCache
+ * public class Entity {
+ *     &#064;org.hibernate.annotations.NaturalId
+ *     private String entityCode;
+ *
+ *     ...
+ * }
+ * </pre>
+ */
+public class HibernateNaturalIdRegion extends HibernateTransactionalDataRegion implements NaturalIdRegion {
+    /**
+     * @param factory Region factory.
+     * @param name Region name.
+     * @param ignite Grid.
+     * @param cache Region cache,
+     * @param dataDesc Region data description.
+     */
+    public HibernateNaturalIdRegion(HibernateRegionFactory factory, String name,
+        Ignite ignite, HibernateCacheProxy cache, CacheDataDescription dataDesc) {
+        super(factory, name, ignite, cache, dataDesc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+        return new AccessStrategy(createAccessStrategy(accessType));
+    }
+
+    /**
+     * NaturalId region access strategy.
+     */
+    private class AccessStrategy extends HibernateAbstractRegionAccessStrategy implements
+        NaturalIdRegionAccessStrategy {
+        /**
+         * @param stgy Access strategy implementation.
+         */
+        private AccessStrategy(HibernateAccessStrategyAdapter stgy) {
+            super(stgy);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor ses) {
+            return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, ses);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object[] getNaturalIdValues(Object cacheKey) {
+            return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey);
+        }
+
+        /** {@inheritDoc} */
+        @Override public NaturalIdRegion getRegion() {
+            return HibernateNaturalIdRegion.this;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean insert(SharedSessionContractImplementor ses, Object key, Object val) throws CacheException {
+            return stgy.insert(key, val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean afterInsert(SharedSessionContractImplementor ses, Object key, Object val) throws CacheException {
+            return stgy.afterInsert(key, val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean update(SharedSessionContractImplementor ses, Object key, Object val) throws CacheException {
+            return stgy.update(key, val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean afterUpdate(SharedSessionContractImplementor ses, Object key, Object val, SoftLock lock) throws CacheException {
+            return stgy.afterUpdate(key, val, lock);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
new file mode 100644
index 0000000..a36d7e7
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateNonStrictAccessStrategy.java
@@ -0,0 +1,222 @@
+/*
+ * 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.Map;
+import java.util.Set;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.util.GridLeanMap;
+import org.apache.ignite.internal.util.GridLeanSet;
+import org.apache.ignite.internal.util.typedef.F;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implementation of {@link AccessType#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.
+     */
+    protected HibernateNonStrictAccessStrategy(Ignite ignite, HibernateCacheProxy cache, ThreadLocal writeCtx) {
+        super(ignite, cache);
+
+        this.writeCtx = (ThreadLocal<WriteContext>)writeCtx;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected SoftLock lock(Object key) throws CacheException {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx == null)
+            writeCtx.set(ctx = new WriteContext());
+
+        ctx.locked(key);
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void unlock(Object key, SoftLock lock) throws CacheException {
+        try {
+            WriteContext ctx = writeCtx.get();
+
+            if (ctx != null && ctx.unlocked(key)) {
+                writeCtx.remove();
+
+                ctx.updateCache(cache);
+            }
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean update(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterUpdate(Object key, Object val, SoftLock lock) throws CacheException {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx != null) {
+            ctx.updated(key, val);
+
+            unlock(key, lock);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean insert(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterInsert(Object key, Object val) throws CacheException {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void remove(Object key) throws CacheException {
+        WriteContext ctx = writeCtx.get();
+
+        if (ctx != null)
+            ctx.removed(key);
+    }
+
+    /**
+     * Information about updates done during single database transaction.
+     */
+    @SuppressWarnings("TypeMayBeWeakened")
+    private static class WriteContext {
+        /** */
+        private Map<Object, Object> updates;
+
+        /** */
+        private Set<Object> rmvs;
+
+        /** */
+        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 GridLeanMap<>();
+
+            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);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateQueryResultsRegion.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateQueryResultsRegion.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateQueryResultsRegion.java
new file mode 100644
index 0000000..0b9a43d
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateQueryResultsRegion.java
@@ -0,0 +1,70 @@
+/*
+ * 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.hibernate.Query;
+import org.hibernate.cache.spi.QueryResultsRegion;
+
+/**
+ * Implementation of {@link QueryResultsRegion}. This region is used to store query results.
+ * <p>
+ * Query results caching can be enabled 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;!-- Enable query 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>
+ * By default queries are not cached even after enabling query caching, to enable results caching for a particular
+ * query, call {@link Query#setCacheable(boolean)}:
+ * <pre name="code" class="java">
+ *     Session ses = getSession();
+ *
+ *     Query qry = ses.createQuery("...");
+ *
+ *     qry.setCacheable(true); // Enable L2 cache for query.
+ * </pre>
+ * Note: the query cache does not cache the state of the actual entities in the cache, it caches only identifier
+ * values. For this reason, the query cache should always be used in conjunction with
+ * the second-level cache for those entities expected to be cached as part of a query result cache
+ */
+public class HibernateQueryResultsRegion extends HibernateGeneralDataRegion implements QueryResultsRegion {
+    /**
+     * @param factory Region factory.
+     * @param name Region name.
+     * @param ignite Grid.
+     * @param cache Region cache.
+     */
+    public HibernateQueryResultsRegion(HibernateRegionFactory factory, String name,
+        Ignite ignite, HibernateCacheProxy cache) {
+        super(factory, name, ignite, cache);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
new file mode 100644
index 0000000..cdef80e
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadOnlyAccessStrategy.java
@@ -0,0 +1,107 @@
+/*
+ * 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;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implementation of {@link AccessType#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 Grid.
+     * @param cache Cache.
+     */
+    public HibernateReadOnlyAccessStrategy(Ignite ignite, HibernateCacheProxy cache) {
+        super(ignite, cache);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean insert(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterInsert(Object key, Object val) throws CacheException {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected SoftLock lock(Object key) throws CacheException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void unlock(Object key, SoftLock lock) throws CacheException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void remove(Object key) throws CacheException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean update(Object key, Object val) throws CacheException {
+        throw new UnsupportedOperationException("Updates are not supported for read-only access strategy.");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterUpdate(Object key, Object val, SoftLock lock) throws CacheException {
+        throw new UnsupportedOperationException("Updates are not supported for read-only access strategy.");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadWriteAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadWriteAccessStrategy.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadWriteAccessStrategy.java
new file mode 100644
index 0000000..ae9bd71
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateReadWriteAccessStrategy.java
@@ -0,0 +1,328 @@
+/*
+ * 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.Set;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
+import org.apache.ignite.internal.util.GridLeanSet;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.SoftLock;
+
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/**
+ * Implementation of {@link AccessType#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 read-write access strategy for entity. --&gt;
+ *     &lt;class-cache class="com.example.Entity" usage="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.READ_WRITE)
+ * public class Entity { ... }
+ * </pre>
+ */
+public class HibernateReadWriteAccessStrategy extends HibernateAccessStrategyAdapter {
+    /** */
+    private final ThreadLocal<TxContext> txCtx;
+
+    /**
+     * @param ignite Grid.
+     * @param cache Cache.
+     * @param txCtx Thread local instance used to track updates done during one Hibernate transaction.
+     */
+    protected HibernateReadWriteAccessStrategy(Ignite ignite, HibernateCacheProxy cache, ThreadLocal txCtx) {
+        super(ignite, cache);
+
+        this.txCtx = (ThreadLocal<TxContext>)txCtx;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Object get(Object key) throws CacheException {
+        boolean success = false;
+
+        try {
+            Object o = cache.get(key);
+
+            success = true;
+
+            return o;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void putFromLoad(Object key, Object val) throws CacheException {
+        boolean success = false;
+
+        try {
+            cache.put(key, val);
+
+            success = true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected SoftLock lock(Object key) throws CacheException {
+        boolean success = false;
+
+        try {
+            TxContext ctx = txCtx.get();
+
+            if (ctx == null)
+                txCtx.set(ctx = new TxContext());
+
+            lockKey(key);
+
+            ctx.locked(key);
+
+            success = true;
+
+            return null;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void unlock(Object key, SoftLock lock) throws CacheException {
+        boolean success = false;
+
+        try {
+            TxContext ctx = txCtx.get();
+
+            if (ctx != null)
+                unlock(ctx, key);
+
+            success = true;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean update(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterUpdate(Object key, Object val, SoftLock lock) throws CacheException {
+        boolean success = false;
+        boolean res = false;
+
+        try {
+            TxContext ctx = txCtx.get();
+
+            if (ctx != null) {
+                cache.put(key, val);
+
+                unlock(ctx, key);
+
+                res = true;
+            }
+
+            success = true;
+
+            return res;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean insert(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterInsert(Object key, Object val) throws CacheException {
+        boolean success = false;
+
+        try {
+            cache.put(key, val);
+
+            success = true;
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void remove(Object key) throws CacheException {
+        boolean success = false;
+
+        try {
+            TxContext ctx = txCtx.get();
+
+            if (ctx != null)
+                cache.remove(key);
+
+            success = true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (!success)
+                rollbackCurrentTx();
+        }
+    }
+
+    /**
+     *
+     * @param ctx Transaction context.
+     * @param key Key.
+     * @throws CacheException If failed.
+     */
+    private void unlock(TxContext ctx, Object key) throws CacheException {
+        if (ctx.unlocked(key)) { // Finish transaction if last key is unlocked.
+            txCtx.remove();
+
+            GridNearTxLocal tx = cache.tx();
+
+            assert tx != null;
+
+            try {
+                tx.proxy().commit();
+            }
+            finally {
+                tx.proxy().close();
+            }
+
+            assert cache.tx() == null;
+        }
+    }
+
+    /**
+     * Roll backs current transaction.
+     */
+    private void rollbackCurrentTx() {
+        try {
+            TxContext ctx = txCtx.get();
+
+            if (ctx != null) {
+                txCtx.remove();
+
+                GridNearTxLocal tx = cache.tx();
+
+                if (tx != null)
+                    tx.proxy().rollback();
+            }
+        }
+        catch (IgniteException e) {
+            log.error("Failed to rollback cache transaction.", e);
+        }
+    }
+
+    /**
+     * @param key Key.
+     * @throws IgniteCheckedException If failed.
+     */
+    private void lockKey(Object key) throws IgniteCheckedException {
+        if (cache.tx() == null)
+            cache.txStart(PESSIMISTIC, REPEATABLE_READ);
+
+        cache.get(key); // Acquire distributed lock.
+    }
+
+    /**
+     * Information about updates done during single database transaction.
+     */
+    @SuppressWarnings("TypeMayBeWeakened")
+    private static class TxContext {
+        /** */
+        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();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegion.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegion.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegion.java
new file mode 100644
index 0000000..11a96d0
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegion.java
@@ -0,0 +1,99 @@
+/*
+ * 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.Collections;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.Region;
+
+/**
+ * Implementation of {@link Region}. This interface defines base contract for all L2 cache regions.
+ */
+public class HibernateRegion implements Region {
+    /** */
+    protected final HibernateRegionFactory factory;
+
+    /** */
+    private final String name;
+
+    /** Cache instance. */
+    protected final HibernateCacheProxy cache;
+
+    /** Grid instance. */
+    protected Ignite ignite;
+
+    /**
+     * @param factory Region factory.
+     * @param name Region name.
+     * @param ignite Grid.
+     * @param cache Region cache.
+     */
+    public HibernateRegion(HibernateRegionFactory factory, String name, Ignite ignite, HibernateCacheProxy cache) {
+        this.factory = factory;
+        this.name = name;
+        this.ignite = ignite;
+        this.cache = cache;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getName() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void destroy() throws CacheException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean contains(Object key) {
+        return cache.containsKey(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getSizeInMemory() {
+        return -1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getElementCountInMemory() {
+        return cache.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getElementCountOnDisk() {
+        return -1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map toMap() {
+        return Collections.emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long nextTimestamp() {
+        return System.currentTimeMillis();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getTimeout() {
+        return 0;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegionFactory.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegionFactory.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegionFactory.java
new file mode 100644
index 0000000..0329688
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateRegionFactory.java
@@ -0,0 +1,264 @@
+/*
+ * 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 org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.util.typedef.G;
+import org.hibernate.boot.spi.SessionFactoryOptions;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.CacheDataDescription;
+import org.hibernate.cache.spi.CollectionRegion;
+import org.hibernate.cache.spi.EntityRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.QueryResultsRegion;
+import org.hibernate.cache.spi.RegionFactory;
+import org.hibernate.cache.spi.TimestampsRegion;
+import org.hibernate.cache.spi.access.AccessType;
+
+import static org.hibernate.cache.spi.access.AccessType.NONSTRICT_READ_WRITE;
+
+/**
+ * Hibernate L2 cache region factory.
+ * <p>
+ * Following Hibernate settings should be specified to enable second level cache and to use this
+ * region factory for caching:
+ * <pre name="code" class="brush: xml; gutter: false;">
+ * hibernate.cache.use_second_level_cache=true
+ * hibernate.cache.region.factory_class=org.apache.ignite.cache.hibernate.HibernateRegionFactory
+ * </pre>
+ * Note that before region factory is started you need to start properly configured Ignite node in the same JVM.
+ * For example to start Ignite node one of loader provided in {@code org.apache.ignite.grid.startup} package can be used.
+ * <p>
+ * Name of Ignite instance to be used for region factory must be specified as following Hibernate property:
+ * <pre name="code" class="brush: xml; gutter: false;">
+ * org.apache.ignite.hibernate.ignite_instance_name=&lt;Ignite instance name&gt;
+ * </pre>
+ * Each Hibernate cache region must be associated with some {@link IgniteInternalCache}, by default it is assumed that
+ * for each cache region there is a {@link IgniteInternalCache} with the same name. Also it is possible to define
+ * region to cache mapping using properties with prefix {@code org.apache.ignite.hibernate.region_cache}.
+ * For example if for region with name "region1" cache with name "cache1" should be used then following
+ * Hibernate property should be specified:
+ * <pre name="code" class="brush: xml; gutter: false;">
+ * org.apache.ignite.hibernate.region_cache.region1=cache1
+ * </pre>
+ */
+public class HibernateRegionFactory implements RegionFactory {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * 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;
+
+    /** Default region access type. */
+    private AccessType dfltAccessType;
+
+    /** Region name to cache name mapping. */
+    private final Map<String, String> regionCaches = new HashMap<>();
+
+    /** Map needed to provide the same transaction context for different regions. */
+    private final ThreadLocal threadLoc = new ThreadLocal();
+
+    /** Key transformer. */
+    private final HibernateKeyTransformer hibernate4transformer = new HibernateKeyTransformer() {
+        @Override public Object transform(Object key) {
+//            if (key instanceof CacheKey) {
+//                CacheKey cacheKey = (CacheKey)key;
+//
+//                return new HibernateKeyWrapper(
+//                    cacheKey.getKey(),
+//                    cacheKey.getEntityOrRoleName()
+//                );
+//            }
+
+            return key;
+        }
+    };
+
+    /** {@inheritDoc} */
+    @Override public void start(SessionFactoryOptions settings, Properties props) throws CacheException {
+        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 new CacheException(e);
+            }
+        }
+        else
+            ignite = Ignition.ignite(igniteInstanceName);
+
+        String accessType = props.getProperty(DFLT_ACCESS_TYPE_PROPERTY, NONSTRICT_READ_WRITE.name());
+
+        dfltAccessType = AccessType.valueOf(accessType);
+
+        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 CacheException("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 CacheException("Cache specified as default is not configured: " + dfltCacheName);
+
+            this.dfltCache = new HibernateCacheProxy(dfltCache, hibernate4transformer);
+        }
+
+        IgniteLogger log = ignite.log().getLogger(HibernateRegionFactory.class);
+
+        if (log.isDebugEnabled())
+            log.debug("HibernateRegionFactory started [igniteInstanceName=" + igniteInstanceName + ']');
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isMinimalPutsEnabledByDefault() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public AccessType getDefaultAccessType() {
+        return dfltAccessType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long nextTimestamp() {
+        return System.currentTimeMillis();
+    }
+
+    /** {@inheritDoc} */
+    @Override public EntityRegion buildEntityRegion(String regionName, Properties props, CacheDataDescription metadata)
+        throws CacheException {
+        return new HibernateEntityRegion(this, regionName, ignite, regionCache(regionName), metadata);
+    }
+
+    /** {@inheritDoc} */
+    @Override public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties props,
+        CacheDataDescription metadata) throws CacheException {
+        return new HibernateNaturalIdRegion(this, regionName, ignite, regionCache(regionName), metadata);
+    }
+
+    /** {@inheritDoc} */
+    @Override public CollectionRegion buildCollectionRegion(String regionName, Properties props,
+        CacheDataDescription metadata) throws CacheException {
+        return new HibernateCollectionRegion(this, regionName, ignite, regionCache(regionName), metadata);
+    }
+
+    /** {@inheritDoc} */
+    @Override public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties props)
+        throws CacheException {
+        return new HibernateQueryResultsRegion(this, regionName, ignite, regionCache(regionName));
+    }
+
+    /** {@inheritDoc} */
+    @Override public TimestampsRegion buildTimestampsRegion(String regionName, Properties props) throws CacheException {
+        return new HibernateTimestampsRegion(this, regionName, ignite, regionCache(regionName));
+    }
+
+    /**
+     * Reuse same thread local for the same cache across different regions.
+     *
+     * @param cacheName Cache name.
+     * @return Thread local instance used to track updates done during one Hibernate transaction.
+     */
+    ThreadLocal threadLocalForCache(String cacheName) {
+        return threadLoc;
+    }
+
+    /**
+     * @param regionName L2 cache region name.
+     * @return Cache for given region.
+     * @throws CacheException If cache for given region is not configured.
+     */
+    private HibernateCacheProxy regionCache(String regionName) throws CacheException {
+        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 CacheException("Cache '" + cacheName + "' for region '" + regionName + "' is not configured.");
+
+        return new HibernateCacheProxy(cache, hibernate4transformer);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTimestampsRegion.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTimestampsRegion.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTimestampsRegion.java
new file mode 100644
index 0000000..8b4c243
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTimestampsRegion.java
@@ -0,0 +1,39 @@
+/*
+ * 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.hibernate.cache.spi.TimestampsRegion;
+
+/**
+ * Implementation of {@link TimestampsRegion}. This region is automatically created when query
+ * caching is enabled and it holds most recent updates timestamps to queryable tables.
+ * Name of timestamps region is {@code "org.hibernate.cache.spi.UpdateTimestampsCache"}.
+ */
+public class HibernateTimestampsRegion extends HibernateGeneralDataRegion implements TimestampsRegion {
+    /**
+     * @param factory Region factory.
+     * @param name Region name.
+     * @param ignite Grid.
+     * @param cache Region cache.
+     */
+    public HibernateTimestampsRegion(HibernateRegionFactory factory, String name,
+        Ignite ignite,  HibernateCacheProxy cache) {
+        super(factory, name, ignite, cache);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalAccessStrategy.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalAccessStrategy.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalAccessStrategy.java
new file mode 100644
index 0000000..ca52849
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalAccessStrategy.java
@@ -0,0 +1,141 @@
+/*
+ * 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;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.access.SoftLock;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implementation of {@link AccessType#TRANSACTIONAL} cache access strategy.
+ * <p>
+ * It is supposed that this strategy is used in JTA environment and Hibernate and
+ * {@link IgniteInternalCache} corresponding to the L2 cache region are configured to use the same transaction manager.
+ * <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 transactional access strategy for entity. --&gt;
+ *     &lt;class-cache class="com.example.Entity" usage="transactional"/&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.TRANSACTIONAL)
+ * public class Entity { ... }
+ * </pre>
+ */
+public class HibernateTransactionalAccessStrategy extends HibernateAccessStrategyAdapter {
+    /**
+     * @param ignite Grid.
+     * @param cache Cache.
+     */
+    public HibernateTransactionalAccessStrategy(Ignite ignite, HibernateCacheProxy cache) {
+        super(ignite, cache);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override protected Object get(Object key) throws CacheException {
+        try {
+            return cache.get(key);
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void putFromLoad(Object key, Object val) throws CacheException {
+        try {
+            cache.put(key, val);
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected SoftLock lock(Object key) throws CacheException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void unlock(Object key, SoftLock lock) throws CacheException {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean update(Object key, Object val) throws CacheException {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterUpdate(Object key, Object val, SoftLock lock) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean insert(Object key, Object val) throws CacheException {
+        try {
+            cache.put(key, val);
+
+            return true;
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean afterInsert(Object key, Object val) throws CacheException {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void remove(Object key) throws CacheException {
+        try {
+            cache.remove(key);
+        }
+        catch (IgniteCheckedException e) {
+            throw new CacheException(e);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalDataRegion.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalDataRegion.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalDataRegion.java
new file mode 100644
index 0000000..581076a
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/HibernateTransactionalDataRegion.java
@@ -0,0 +1,107 @@
+/*
+ * 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.configuration.TransactionConfiguration;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.spi.CacheDataDescription;
+import org.hibernate.cache.spi.CollectionRegion;
+import org.hibernate.cache.spi.EntityRegion;
+import org.hibernate.cache.spi.NaturalIdRegion;
+import org.hibernate.cache.spi.TransactionalDataRegion;
+import org.hibernate.cache.spi.access.AccessType;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ * Implementation of {@link TransactionalDataRegion} (transactional means that
+ * data in the region is updated in connection with database transaction).
+ * This interface defines base contract for {@link EntityRegion}, {@link CollectionRegion}
+ * and {@link NaturalIdRegion}.
+ */
+public class HibernateTransactionalDataRegion extends HibernateRegion implements TransactionalDataRegion {
+    /** */
+    private final CacheDataDescription dataDesc;
+
+    /**
+     * @param factory Region factory.
+     * @param name Region name.
+     * @param ignite Grid.
+     * @param cache Region cache.
+     * @param dataDesc Region data description.
+     */
+    public HibernateTransactionalDataRegion(HibernateRegionFactory factory, String name,
+        Ignite ignite, HibernateCacheProxy cache, CacheDataDescription dataDesc) {
+        super(factory, name, ignite, cache);
+
+        this.dataDesc = dataDesc;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isTransactionAware() {
+        return false; // This method is not used by Hibernate.
+    }
+
+    /** {@inheritDoc} */
+    @Override public CacheDataDescription getCacheDataDescription() {
+        return dataDesc;
+    }
+
+    /**
+     * @param accessType Hibernate L2 cache access type.
+     * @return Access strategy for given access type.
+     */
+    protected HibernateAccessStrategyAdapter createAccessStrategy(AccessType accessType) {
+        switch (accessType) {
+            case READ_ONLY:
+                return new HibernateReadOnlyAccessStrategy(ignite, cache);
+
+            case NONSTRICT_READ_WRITE:
+                return new HibernateNonStrictAccessStrategy(ignite, cache, factory.threadLocalForCache(cache.name()));
+
+            case READ_WRITE:
+                if (cache.configuration().getAtomicityMode() != TRANSACTIONAL)
+                    throw new CacheException("Hibernate READ-WRITE access strategy must have Ignite cache with " +
+                        "'TRANSACTIONAL' atomicity mode: " + cache.name());
+
+                return new HibernateReadWriteAccessStrategy(ignite, cache, factory.threadLocalForCache(cache.name()));
+
+            case TRANSACTIONAL:
+                if (cache.configuration().getAtomicityMode() != TRANSACTIONAL)
+                    throw new CacheException("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 CacheException("Hibernate TRANSACTIONAL access strategy must have Ignite with " +
+                                "Factory<TransactionManager> configured (see IgniteConfiguration." +
+                                "getTransactionConfiguration().setTxManagerFactory()): " + cache.name());
+                }
+
+                return new HibernateTransactionalAccessStrategy(ignite, cache);
+
+            default:
+                throw new IllegalArgumentException("Unknown Hibernate access type: " + accessType);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/package-info.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/package-info.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/package-info.java
new file mode 100644
index 0000000..1179aec
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/hibernate/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 implementation of Hibernate L2 cache. Refer to
+ * <i>org.apache.ignite.examples.datagrid.hibernate.HibernateL2CacheExample</i> for more information on how to
+ * configure and use Ignite with Hibernate.
+ */
+package org.apache.ignite.cache.hibernate;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStore.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStore.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStore.java
new file mode 100644
index 0000000..c87f08f
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStore.java
@@ -0,0 +1,542 @@
+/*
+ * 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.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.cache.integration.CacheLoaderException;
+import javax.cache.integration.CacheWriterException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+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.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.marshaller.jdk.JdkMarshaller;
+import org.apache.ignite.resources.CacheStoreSessionResource;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.transactions.Transaction;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.SharedSessionContract;
+import org.hibernate.cfg.Configuration;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * {@link CacheStore} implementation backed by Hibernate. This implementation
+ * stores objects in underlying database in {@code BLOB} format.
+ * <h2 class="header">Configuration</h2>
+ * Either {@link #setSessionFactory(SessionFactory)} or
+ * {@link #setHibernateConfigurationPath(String)} or
+ * {@link #setHibernateProperties(Properties)} should be set.
+ * <p>
+ * If session factory is provided it should contain
+ * {@link CacheHibernateBlobStoreEntry} persistent class (via provided
+ * mapping file {@code GridCacheHibernateStoreEntry.hbm.xml} or by
+ * adding {@link CacheHibernateBlobStoreEntry} to annotated classes
+ * of session factory.
+ * <p>
+ * Path to hibernate configuration may be either an URL or a file path or
+ * a classpath resource. This configuration file should include provided
+ * mapping {@code GridCacheHibernateStoreEntry.hbm.xml} or include annotated
+ * class {@link CacheHibernateBlobStoreEntry}.
+ * <p>
+ * If hibernate properties are provided, mapping
+ * {@code GridCacheHibernateStoreEntry.hbm.xml} is included automatically.
+ * <p>
+ * Use {@link CacheHibernateBlobStoreFactory} factory to pass {@link CacheHibernateBlobStore} to {@link CacheConfiguration}.
+ */
+public class CacheHibernateBlobStore<K, V> extends CacheStoreAdapter<K, V> {
+    /**
+     * Default connection URL
+     * (value is <tt>jdbc:h2:mem:hibernateCacheStore;DB_CLOSE_DELAY=-1;DEFAULT_LOCK_TIMEOUT=5000</tt>).
+     */
+    public static final String DFLT_CONN_URL = "jdbc:h2:mem:hibernateCacheStore;DB_CLOSE_DELAY=-1;" +
+        "DEFAULT_LOCK_TIMEOUT=5000";
+
+    /** Default show SQL property value (value is <tt>true</tt>). */
+    public static final String DFLT_SHOW_SQL = "true";
+
+    /** Default <tt>hibernate.hbm2ddl.auto</tt> property value (value is <tt>true</tt>). */
+    public static final String DFLT_HBM2DDL_AUTO = "update";
+
+    /** Session attribute name. */
+    private static final String ATTR_SES = "HIBERNATE_STORE_SESSION";
+
+    /** Name of Hibarname mapping resource. */
+    private static final String MAPPING_RESOURCE =
+            "org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml";
+
+    /** Marshaller. */
+    private static final Marshaller marsh = new JdkMarshaller();
+
+    /** Init guard. */
+    @GridToStringExclude
+    private final AtomicBoolean initGuard = new AtomicBoolean();
+
+    /** Init latch. */
+    @GridToStringExclude
+    private final CountDownLatch initLatch = new CountDownLatch(1);
+
+    /** Hibernate properties. */
+    @GridToStringExclude
+    private Properties hibernateProps;
+
+    /** Session factory. */
+    @GridToStringExclude
+    private SessionFactory sesFactory;
+
+    /** Path to hibernate configuration file. */
+    private String hibernateCfgPath;
+
+    /** Log. */
+    @LoggerResource
+    private IgniteLogger log;
+
+    /** Auto-injected store session. */
+    @CacheStoreSessionResource
+    private CacheStoreSession ses;
+
+    /** Ignite instance. */
+    @IgniteInstanceResource
+    private Ignite ignite;
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"unchecked", "RedundantTypeArguments"})
+    @Override public V load(K key) {
+        init();
+
+        Transaction tx = transaction();
+
+        if (log.isDebugEnabled())
+            log.debug("Store load [key=" + key + ", tx=" + tx + ']');
+
+        Session ses = session(tx);
+
+        try {
+            CacheHibernateBlobStoreEntry entry = (CacheHibernateBlobStoreEntry)
+                ses.get(CacheHibernateBlobStoreEntry.class, toBytes(key));
+
+            if (entry == null)
+                return null;
+
+            return fromBytes(entry.getValue());
+        }
+        catch (IgniteCheckedException | HibernateException e) {
+            rollback(ses, tx);
+
+            throw new CacheLoaderException("Failed to load value from cache store with key: " + key, e);
+        }
+        finally {
+            end(ses, tx);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void write(javax.cache.Cache.Entry<? extends K, ? extends V> entry) {
+        init();
+
+        Transaction tx = transaction();
+
+        K key = entry.getKey();
+        V val = entry.getValue();
+
+        if (log.isDebugEnabled())
+            log.debug("Store put [key=" + key + ", val=" + val + ", tx=" + tx + ']');
+
+        if (val == null) {
+            delete(key);
+
+            return;
+        }
+
+        Session ses = session(tx);
+
+        try {
+            CacheHibernateBlobStoreEntry entry0 = new CacheHibernateBlobStoreEntry(toBytes(key), toBytes(val));
+
+            ses.saveOrUpdate(entry0);
+        }
+        catch (IgniteCheckedException | HibernateException e) {
+            rollback(ses, tx);
+
+            throw new CacheWriterException("Failed to put value to cache store [key=" + key + ", val" + val + "]", e);
+        }
+        finally {
+            end(ses, tx);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"JpaQueryApiInspection", "JpaQlInspection"})
+    @Override public void delete(Object key) {
+        init();
+
+        Transaction tx = transaction();
+
+        if (log.isDebugEnabled())
+            log.debug("Store remove [key=" + key + ", tx=" + tx + ']');
+
+        Session ses = session(tx);
+
+        try {
+            Object obj = ses.get(CacheHibernateBlobStoreEntry.class, toBytes(key));
+
+            if (obj != null)
+                ses.delete(obj);
+        }
+        catch (IgniteCheckedException | HibernateException e) {
+            rollback(ses, tx);
+
+            throw new CacheWriterException("Failed to remove value from cache store with key: " + key, e);
+        }
+        finally {
+            end(ses, tx);
+        }
+    }
+
+    /**
+     * Rolls back hibernate session.
+     *
+     * @param ses Hibernate session.
+     * @param tx Cache ongoing transaction.
+     */
+    private void rollback(SharedSessionContract ses, Transaction tx) {
+        // Rollback only if there is no cache transaction,
+        // otherwise sessionEnd() will do all required work.
+        if (tx == null) {
+            org.hibernate.Transaction hTx = ses.getTransaction();
+
+            if (hTx != null && hTx.isActive())
+                hTx.rollback();
+        }
+    }
+
+    /**
+     * Ends hibernate session.
+     *
+     * @param ses Hibernate session.
+     * @param tx Cache ongoing transaction.
+     */
+    private void end(Session ses, Transaction tx) {
+        // Commit only if there is no cache transaction,
+        // otherwise sessionEnd() will do all required work.
+        if (tx == null) {
+            org.hibernate.Transaction hTx = ses.getTransaction();
+
+            if (hTx != null && hTx.isActive())
+                hTx.commit();
+
+            ses.close();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void sessionEnd(boolean commit) {
+        init();
+
+        Transaction tx = transaction();
+
+        Map<String, Session> props = session().properties();
+
+        Session ses = props.remove(ATTR_SES);
+
+        if (ses != null) {
+            org.hibernate.Transaction hTx = ses.getTransaction();
+
+            if (hTx != null) {
+                try {
+                    if (commit) {
+                        ses.flush();
+
+                        hTx.commit();
+                    }
+                    else
+                        hTx.rollback();
+
+                    if (log.isDebugEnabled())
+                        log.debug("Transaction ended [xid=" + tx.xid() + ", commit=" + commit + ']');
+                }
+                catch (HibernateException e) {
+                    throw new CacheWriterException("Failed to end transaction [xid=" + tx.xid() +
+                        ", commit=" + commit + ']', e);
+                }
+                finally {
+                    ses.close();
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets Hibernate session.
+     *
+     * @param tx Cache transaction.
+     * @return Session.
+     */
+    Session session(@Nullable Transaction tx) {
+        Session ses;
+
+        if (tx != null) {
+            Map<String, Session> props = session().properties();
+
+            ses = props.get(ATTR_SES);
+
+            if (ses == null) {
+                ses = sesFactory.openSession();
+
+                ses.beginTransaction();
+
+                // Store session in transaction metadata, so it can be accessed
+                // for other operations on the same transaction.
+                props.put(ATTR_SES, ses);
+
+                if (log.isDebugEnabled())
+                    log.debug("Hibernate session open [ses=" + ses + ", tx=" + tx.xid() + "]");
+            }
+        }
+        else {
+            ses = sesFactory.openSession();
+
+            ses.beginTransaction();
+        }
+
+        return ses;
+    }
+
+    /**
+     * Sets session factory.
+     *
+     * @param sesFactory Session factory.
+     */
+    public void setSessionFactory(SessionFactory sesFactory) {
+        this.sesFactory = sesFactory;
+    }
+
+    /**
+     * Sets hibernate configuration path.
+     * <p>
+     * This may be either URL or file path or classpath resource.
+     *
+     * @param hibernateCfgPath URL or file path or classpath resource
+     *      pointing to hibernate configuration XML file.
+     */
+    public void setHibernateConfigurationPath(String hibernateCfgPath) {
+        this.hibernateCfgPath = hibernateCfgPath;
+    }
+
+    /**
+     * Sets Hibernate properties.
+     *
+     * @param hibernateProps Hibernate properties.
+     */
+    public void setHibernateProperties(Properties hibernateProps) {
+        this.hibernateProps = hibernateProps;
+    }
+
+    /**
+     * Initializes store.
+     *
+     * @throws IgniteException If failed to initialize.
+     */
+    private void init() throws IgniteException {
+        if (initGuard.compareAndSet(false, true)) {
+            if (log.isDebugEnabled())
+                log.debug("Initializing cache store.");
+
+            try {
+                if (sesFactory != null)
+                    // Session factory has been provided - nothing to do.
+                    return;
+
+                if (!F.isEmpty(hibernateCfgPath)) {
+                    try {
+                        URL url = new URL(hibernateCfgPath);
+
+                        sesFactory = new Configuration().configure(url).buildSessionFactory();
+
+                        if (log.isDebugEnabled())
+                            log.debug("Configured session factory using URL: " + url);
+
+                        // Session factory has been successfully initialized.
+                        return;
+                    }
+                    catch (MalformedURLException e) {
+                        if (log.isDebugEnabled())
+                            log.debug("Caught malformed URL exception: " + e.getMessage());
+                    }
+
+                    // Provided path is not a valid URL. File?
+                    File cfgFile = new File(hibernateCfgPath);
+
+                    if (cfgFile.exists()) {
+                        sesFactory = new Configuration().configure(cfgFile).buildSessionFactory();
+
+                        if (log.isDebugEnabled())
+                            log.debug("Configured session factory using file: " + hibernateCfgPath);
+
+                        // Session factory has been successfully initialized.
+                        return;
+                    }
+
+                    // Provided path is not a file. Classpath resource?
+                    sesFactory = new Configuration().configure(hibernateCfgPath).buildSessionFactory();
+
+                    if (log.isDebugEnabled())
+                        log.debug("Configured session factory using classpath resource: " + hibernateCfgPath);
+                }
+                else {
+                    if (hibernateProps == null) {
+                        U.warn(log, "No Hibernate configuration has been provided for store (will use default).");
+
+                        hibernateProps = new Properties();
+
+                        hibernateProps.setProperty("hibernate.connection.url", DFLT_CONN_URL);
+                        hibernateProps.setProperty("hibernate.show_sql", DFLT_SHOW_SQL);
+                        hibernateProps.setProperty("hibernate.hbm2ddl.auto", DFLT_HBM2DDL_AUTO);
+                    }
+
+                    Configuration cfg = new Configuration();
+
+                    cfg.setProperties(hibernateProps);
+
+                    assert resourceAvailable(MAPPING_RESOURCE) : MAPPING_RESOURCE;
+
+                    cfg.addResource(MAPPING_RESOURCE);
+
+                    sesFactory = cfg.buildSessionFactory();
+
+                    if (log.isDebugEnabled())
+                        log.debug("Configured session factory using properties: " + hibernateProps);
+                }
+            }
+            catch (HibernateException e) {
+                throw new IgniteException("Failed to initialize store.", e);
+            }
+            finally {
+                initLatch.countDown();
+            }
+        }
+        else if (initLatch.getCount() > 0) {
+            try {
+                U.await(initLatch);
+            }
+            catch (IgniteInterruptedCheckedException e) {
+                throw new IgniteException(e);
+            }
+        }
+
+        if (sesFactory == null)
+            throw new IgniteException("Cache store was not properly initialized.");
+    }
+
+    /**
+     * Checks availability of a classpath resource.
+     *
+     * @param name Resource name.
+     * @return {@code true} if resource is available and ready for read, {@code false} otherwise.
+     */
+    private boolean resourceAvailable(String name) {
+        InputStream cfgStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(name);
+
+        if (cfgStream == null) {
+            log.error("Classpath resource not found: " + name);
+
+            return false;
+        }
+
+        try {
+            // Read a single byte to force actual content access by JVM.
+            cfgStream.read();
+
+            return true;
+        }
+        catch (IOException e) {
+            log.error("Failed to read classpath resource: " + name, e);
+
+            return false;
+        }
+        finally {
+            U.close(cfgStream, log);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheHibernateBlobStore.class, this);
+    }
+
+    /**
+     * Serialize object to byte array using marshaller.
+     *
+     * @param obj Object to convert to byte array.
+     * @return Byte array.
+     * @throws IgniteCheckedException If failed to convert.
+     */
+    protected byte[] toBytes(Object obj) throws IgniteCheckedException {
+        return U.marshal(marsh, obj);
+    }
+
+    /**
+     * Deserialize object from byte array using marshaller.
+     *
+     * @param bytes Bytes to deserialize.
+     * @param <X> Result object type.
+     * @return Deserialized object.
+     * @throws IgniteCheckedException If failed.
+     */
+    protected <X> X fromBytes(byte[] bytes) throws IgniteCheckedException {
+        if (bytes == null || bytes.length == 0)
+            return null;
+
+        return U.unmarshal(marsh, bytes, getClass().getClassLoader());
+    }
+
+    /**
+     * @return Current transaction.
+     */
+    @Nullable private Transaction transaction() {
+        CacheStoreSession ses = session();
+
+        return ses != null ? ses.transaction() : null;
+    }
+
+    /**
+     * @return Store session.
+     */
+    private CacheStoreSession session() {
+        return ses;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml
new file mode 100644
index 0000000..5b0be43
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.hbm.xml
@@ -0,0 +1,31 @@
+<?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-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.apache.ignite.examples.datagrid.store" default-access="field">
+    <class name="org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreEntry" table="ENTRIES">
+        <id name="key"/>
+
+        <property name="val"/>
+    </class>
+</hibernate-mapping>

http://git-wip-us.apache.org/repos/asf/ignite/blob/0ac4d044/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.java
----------------------------------------------------------------------
diff --git a/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.java b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.java
new file mode 100644
index 0000000..d40c5ef
--- /dev/null
+++ b/modules/hibernate5/src/main/java/org/apache/ignite/cache/store/hibernate/CacheHibernateBlobStoreEntry.java
@@ -0,0 +1,89 @@
+/*
+ * 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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Entry that is used by {@link CacheHibernateBlobStore} implementation.
+ * <p>
+ * Note that this is a reference implementation for tests only.
+ * When running on production systems use concrete key-value types to
+ * get better performance.
+ */
+@Entity
+@Table(name = "ENTRIES")
+public class CacheHibernateBlobStoreEntry {
+    /** Key (use concrete key type in production). */
+    @Id
+    @Column(length = 65535)
+    private byte[] key;
+
+    /** Value (use concrete value type in production). */
+    @Column(length = 65535)
+    private byte[] val;
+
+    /**
+     * Constructor.
+     */
+    CacheHibernateBlobStoreEntry() {
+        // No-op.
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param key Key.
+     * @param val Value.
+     */
+    CacheHibernateBlobStoreEntry(byte[] key, byte[] val) {
+        this.key = key;
+        this.val = val;
+    }
+
+    /**
+     * @return Key.
+     */
+    public byte[] getKey() {
+        return key;
+    }
+
+    /**
+     * @param key Key.
+     */
+    public void setKey(byte[] key) {
+        this.key = key;
+    }
+
+    /**
+     * @return Value.
+     */
+    public byte[] getValue() {
+        return val;
+    }
+
+    /**
+     * @param val Value.
+     */
+    public void setValue(byte[] val) {
+        this.val = val;
+    }
+}
\ No newline at end of file


Mime
View raw message