diff --git a/redisson-hibernate/pom.xml b/redisson-hibernate/pom.xml
index 563a79656..7c5072681 100644
--- a/redisson-hibernate/pom.xml
+++ b/redisson-hibernate/pom.xml
@@ -18,6 +18,7 @@
redisson-hibernate-5
redisson-hibernate-52
redisson-hibernate-53
+ redisson-hibernate-6
diff --git a/redisson-hibernate/redisson-hibernate-6/pom.xml b/redisson-hibernate/redisson-hibernate-6/pom.xml
new file mode 100644
index 000000000..152ab6faa
--- /dev/null
+++ b/redisson-hibernate/redisson-hibernate-6/pom.xml
@@ -0,0 +1,98 @@
+
+ 4.0.0
+
+
+ org.redisson
+ redisson-hibernate
+ 3.17.3-SNAPSHOT
+ ../
+
+
+ redisson-hibernate-6
+ jar
+
+ Redisson/Hibernate-6.x+
+
+
+
+ org.hibernate.orm
+ hibernate-core
+ 6.0.2.Final
+ true
+
+
+
+ org.hibernate.orm
+ hibernate-testing
+ 6.0.2.Final
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.7.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.7.2
+ test
+
+
+
+
+
+
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ ${maven.build.timestamp}
+ redisson.hibernate53
+
+
+
+
+
+
+ com.mycila
+ license-maven-plugin
+ 3.0
+
+ ${basedir}
+ ${basedir}/../../header.txt
+ false
+ true
+ false
+
+ src/main/java/org/redisson/
+
+
+ target/**
+
+ true
+
+ JAVADOC_STYLE
+
+ true
+ true
+ UTF-8
+
+
+
+
+ check
+
+
+
+
+
+
+
+
+
+
diff --git a/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/JndiRedissonRegionFactory.java b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/JndiRedissonRegionFactory.java
new file mode 100644
index 000000000..f1e6b6cc5
--- /dev/null
+++ b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/JndiRedissonRegionFactory.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2013-2021 Nikita Koksharov
+ *
+ * Licensed 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.redisson.hibernate;
+
+import org.hibernate.boot.registry.StandardServiceRegistry;
+import org.hibernate.cache.CacheException;
+import org.hibernate.engine.jndi.JndiException;
+import org.hibernate.engine.jndi.spi.JndiService;
+import org.hibernate.internal.util.config.ConfigurationHelper;
+import org.redisson.api.RedissonClient;
+
+import java.util.Map;
+
+/**
+ * Hibernate Cache region factory based on Redisson.
+ * Uses Redisson instance located in JNDI.
+ *
+ * @author Nikita Koksharov
+ *
+ */
+public class JndiRedissonRegionFactory extends RedissonRegionFactory {
+
+ private static final long serialVersionUID = -4814502675083325567L;
+
+ public static final String JNDI_NAME = CONFIG_PREFIX + "jndi_name";
+
+ @Override
+ protected RedissonClient createRedissonClient(StandardServiceRegistry registry, Map properties) {
+ String jndiName = ConfigurationHelper.getString(JNDI_NAME, properties);
+ if (jndiName == null) {
+ throw new CacheException(JNDI_NAME + " property not set");
+ }
+
+ try {
+ return (RedissonClient) registry.getService(JndiService.class).locate(jndiName);
+ } catch (JndiException e) {
+ throw new CacheException(e);
+ }
+ }
+
+ @Override
+ protected void releaseFromUse() {
+ }
+
+}
diff --git a/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java
new file mode 100644
index 000000000..5eef3261b
--- /dev/null
+++ b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2013-2021 Nikita Koksharov
+ *
+ * Licensed 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.redisson.hibernate;
+
+import io.netty.buffer.ByteBuf;
+import org.hibernate.PropertyNotFoundException;
+import org.hibernate.cache.internal.DefaultCacheKeysFactory;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.internal.util.ReflectHelper;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.redisson.client.codec.Codec;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+
+/**
+ *
+ * @author Nikita Koksharov
+ *
+ */
+public class RedissonCacheKeysFactory extends DefaultCacheKeysFactory {
+
+ private final Codec codec;
+
+ public RedissonCacheKeysFactory(Codec codec) {
+ this.codec = codec;
+ }
+
+ @Override
+ public Object createCollectionKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) {
+ try {
+ String[] parts = persister.getRole().split("\\.");
+ Field f = ReflectHelper.findField(id.getClass(), parts[parts.length - 1]);
+
+ Object prev = f.get(id);
+ f.set(id, null);
+ ByteBuf state = codec.getMapKeyEncoder().encode(id);
+ Object newId = codec.getMapKeyDecoder().decode(state, null);
+ state.release();
+ f.set(id, prev);
+ return super.createCollectionKey(newId, persister, factory, tenantIdentifier);
+ } catch (PropertyNotFoundException e) {
+ return super.createCollectionKey(id, persister, factory, tenantIdentifier);
+ } catch (IllegalAccessException | IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+
+}
diff --git a/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java
new file mode 100644
index 000000000..5fa72b140
--- /dev/null
+++ b/redisson-hibernate/redisson-hibernate-6/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java
@@ -0,0 +1,241 @@
+/**
+ * Copyright (c) 2013-2021 Nikita Koksharov
+ *
+ * Licensed 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.redisson.hibernate;
+
+import org.hibernate.boot.registry.StandardServiceRegistry;
+import org.hibernate.boot.registry.selector.spi.StrategySelector;
+import org.hibernate.boot.spi.SessionFactoryOptions;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
+import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
+import org.hibernate.cache.spi.CacheKeysFactory;
+import org.hibernate.cache.spi.DomainDataRegion;
+import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.cache.spi.support.*;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.internal.util.config.ConfigurationHelper;
+import org.redisson.Redisson;
+import org.redisson.api.RMapCache;
+import org.redisson.api.RScript;
+import org.redisson.api.RedissonClient;
+import org.redisson.client.codec.LongCodec;
+import org.redisson.config.Config;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Hibernate Cache region factory based on Redisson.
+ * Creates own Redisson instance during region start.
+ *
+ * @author Nikita Koksharov
+ *
+ */
+public class RedissonRegionFactory extends RegionFactoryTemplate {
+
+ private static final long serialVersionUID = 3785315696581773811L;
+
+ public static final String QUERY_DEF = "query";
+
+ public static final String COLLECTION_DEF = "collection";
+
+ public static final String ENTITY_DEF = "entity";
+
+ public static final String NATURAL_ID_DEF = "naturalid";
+
+ public static final String TIMESTAMPS_DEF = "timestamps";
+
+ public static final String MAX_ENTRIES_SUFFIX = ".eviction.max_entries";
+
+ public static final String TTL_SUFFIX = ".expiration.time_to_live";
+
+ public static final String MAX_IDLE_SUFFIX = ".expiration.max_idle_time";
+
+ public static final String CONFIG_PREFIX = "hibernate.cache.redisson.";
+
+ public static final String REDISSON_CONFIG_PATH = CONFIG_PREFIX + "config";
+
+ public static final String FALLBACK = CONFIG_PREFIX + "fallback";
+
+ private RedissonClient redisson;
+ private CacheKeysFactory cacheKeysFactory;
+ protected boolean fallback;
+
+ @Override
+ protected CacheKeysFactory getImplicitCacheKeysFactory() {
+ return cacheKeysFactory;
+ }
+
+ @Override
+ protected void prepareForUse(SessionFactoryOptions settings, @SuppressWarnings("rawtypes") Map properties) throws CacheException {
+ this.redisson = createRedissonClient(settings.getServiceRegistry(), properties);
+
+ String fallbackValue = (String) properties.getOrDefault(FALLBACK, "false");
+ fallback = Boolean.valueOf(fallbackValue);
+
+ StrategySelector selector = settings.getServiceRegistry().getService(StrategySelector.class);
+ cacheKeysFactory = selector.resolveDefaultableStrategy(CacheKeysFactory.class,
+ properties.get(Environment.CACHE_KEYS_FACTORY), new RedissonCacheKeysFactory(redisson.getConfig().getCodec()));
+ }
+
+ protected RedissonClient createRedissonClient(StandardServiceRegistry registry, Map properties) {
+ Config config = null;
+ if (!properties.containsKey(REDISSON_CONFIG_PATH)) {
+ config = loadConfig(RedissonRegionFactory.class.getClassLoader(), "redisson.json");
+ if (config == null) {
+ config = loadConfig(RedissonRegionFactory.class.getClassLoader(), "redisson.yaml");
+ }
+ } else {
+ String configPath = ConfigurationHelper.getString(REDISSON_CONFIG_PATH, properties);
+ config = loadConfig(RedissonRegionFactory.class.getClassLoader(), configPath);
+ if (config == null) {
+ config = loadConfig(configPath);
+ }
+ }
+
+ if (config == null) {
+ throw new CacheException("Unable to locate Redisson configuration");
+ }
+
+ return Redisson.create(config);
+ }
+
+ private Config loadConfig(String configPath) {
+ try {
+ return Config.fromYAML(new File(configPath));
+ } catch (IOException e) {
+ // trying next format
+ try {
+ return Config.fromJSON(new File(configPath));
+ } catch (IOException e1) {
+ throw new CacheException("Can't parse default yaml config", e1);
+ }
+ }
+ }
+
+ private Config loadConfig(ClassLoader classLoader, String fileName) {
+ InputStream is = classLoader.getResourceAsStream(fileName);
+ if (is != null) {
+ try {
+ return Config.fromYAML(is);
+ } catch (IOException e) {
+ try {
+ is = classLoader.getResourceAsStream(fileName);
+ return Config.fromJSON(is);
+ } catch (IOException e1) {
+ throw new CacheException("Can't parse yaml config", e1);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void releaseFromUse() {
+ redisson.shutdown();
+ }
+
+ @Override
+ public boolean isMinimalPutsEnabledByDefault() {
+ return true;
+ }
+
+ @Override
+ public AccessType getDefaultAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ @Override
+ public long nextTimestamp() {
+ long time = System.currentTimeMillis() << 12;
+ try {
+ return redisson.getScript(LongCodec.INSTANCE).eval(RScript.Mode.READ_WRITE,
+ "local currentTime = redis.call('get', KEYS[1]);"
+ + "if currentTime == false then "
+ + "redis.call('set', KEYS[1], ARGV[1]); "
+ + "return ARGV[1]; "
+ + "end;"
+ + "local nextValue = math.max(tonumber(ARGV[1]), tonumber(currentTime) + 1); "
+ + "redis.call('set', KEYS[1], nextValue); "
+ + "return nextValue;",
+ RScript.ReturnType.INTEGER, Arrays.