diff --git a/redisson-hibernate/redisson-hibernate-4/src/test/resources/org/redisson/hibernate/redisson.json b/redisson-hibernate/redisson-hibernate-4/src/test/resources/org/redisson/hibernate/redisson.json deleted file mode 100644 index 9414f3be5..000000000 --- a/redisson-hibernate/redisson-hibernate-4/src/test/resources/org/redisson/hibernate/redisson.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - } -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.json b/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.json deleted file mode 100644 index 9414f3be5..000000000 --- a/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - } -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.yaml b/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.yaml new file mode 100644 index 000000000..9fd9bb723 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-4/src/test/resources/redisson.yaml @@ -0,0 +1,2 @@ +singleServerConfig: + address: "redis://127.0.0.1:6379" \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java new file mode 100644 index 000000000..09eba0cd9 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2013-2020 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-5/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java index bef2baf6b..a32e43e96 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java @@ -15,22 +15,12 @@ */ package org.redisson.hibernate; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Properties; - +import org.hibernate.boot.registry.selector.spi.StrategySelector; 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.*; import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; import org.hibernate.internal.util.config.ConfigurationHelper; import org.jboss.logging.Logger; @@ -40,11 +30,13 @@ import org.redisson.api.RScript; import org.redisson.api.RedissonClient; import org.redisson.client.codec.LongCodec; import org.redisson.config.Config; -import org.redisson.hibernate.region.RedissonCollectionRegion; -import org.redisson.hibernate.region.RedissonEntityRegion; -import org.redisson.hibernate.region.RedissonNaturalIdRegion; -import org.redisson.hibernate.region.RedissonQueryRegion; -import org.redisson.hibernate.region.RedissonTimestampsRegion; +import org.redisson.hibernate.region.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Properties; /** * Hibernate Cache region factory based on Redisson. @@ -80,11 +72,17 @@ import org.redisson.hibernate.region.RedissonTimestampsRegion; protected RedissonClient redisson; private Settings settings; + private CacheKeysFactory cacheKeysFactory; @Override public void start(SessionFactoryOptions settings, Properties properties) throws CacheException { this.redisson = createRedissonClient(properties); this.settings = new Settings(settings); + + 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(Properties properties) { @@ -175,7 +173,7 @@ import org.redisson.hibernate.region.RedissonTimestampsRegion; log.debug("Building entity cache region: " + regionName); RMapCache mapCache = getCache(regionName, properties, ENTITY_DEF); - return new RedissonEntityRegion(mapCache, this, metadata, settings, properties, ENTITY_DEF); + return new RedissonEntityRegion(mapCache, this, metadata, settings, properties, ENTITY_DEF, cacheKeysFactory); } @Override @@ -184,7 +182,7 @@ import org.redisson.hibernate.region.RedissonTimestampsRegion; log.debug("Building naturalId cache region: " + regionName); RMapCache mapCache = getCache(regionName, properties, NATURAL_ID_DEF); - return new RedissonNaturalIdRegion(mapCache, this, metadata, settings, properties, NATURAL_ID_DEF); + return new RedissonNaturalIdRegion(mapCache, this, metadata, settings, properties, NATURAL_ID_DEF, cacheKeysFactory); } @Override @@ -193,7 +191,7 @@ import org.redisson.hibernate.region.RedissonTimestampsRegion; log.debug("Building collection cache region: " + regionName); RMapCache mapCache = getCache(regionName, properties, COLLECTION_DEF); - return new RedissonCollectionRegion(mapCache, this, metadata, settings, properties, COLLECTION_DEF); + return new RedissonCollectionRegion(mapCache, this, metadata, settings, properties, COLLECTION_DEF, cacheKeysFactory); } @Override diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonCollectionRegion.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonCollectionRegion.java index f9490271c..60a9b2a8a 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonCollectionRegion.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonCollectionRegion.java @@ -19,6 +19,7 @@ import java.util.Properties; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.CollectionRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.access.AccessType; @@ -38,11 +39,17 @@ import org.redisson.hibernate.strategy.TransactionalCollectionRegionAccessStrate public class RedissonCollectionRegion extends BaseRegion implements CollectionRegion { private final Settings settings; + private final CacheKeysFactory cacheKeysFactory; public RedissonCollectionRegion(RMapCache mapCache, RegionFactory regionFactory, - CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey) { + CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey, CacheKeysFactory cacheKeysFactory) { super(mapCache, regionFactory, metadata, properties, defaultKey); this.settings = settings; + this.cacheKeysFactory = cacheKeysFactory; + } + + public CacheKeysFactory getCacheKeysFactory() { + return cacheKeysFactory; } @Override diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonEntityRegion.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonEntityRegion.java index bb3a2e902..b97744425 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonEntityRegion.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonEntityRegion.java @@ -19,6 +19,7 @@ import java.util.Properties; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.EntityRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.access.AccessType; @@ -38,11 +39,17 @@ import org.redisson.hibernate.strategy.TransactionalEntityRegionAccessStrategy; public class RedissonEntityRegion extends BaseRegion implements EntityRegion { private final Settings settings; + private final CacheKeysFactory cacheKeysFactory; public RedissonEntityRegion(RMapCache mapCache, RegionFactory regionFactory, - CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey) { + CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey, CacheKeysFactory cacheKeysFactory) { super(mapCache, regionFactory, metadata, properties, defaultKey); this.settings = settings; + this.cacheKeysFactory = cacheKeysFactory; + } + + public CacheKeysFactory getCacheKeysFactory() { + return cacheKeysFactory; } @Override diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonNaturalIdRegion.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonNaturalIdRegion.java index 9deb6e3da..5f71c8b65 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonNaturalIdRegion.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/region/RedissonNaturalIdRegion.java @@ -19,6 +19,7 @@ import java.util.Properties; import org.hibernate.cache.CacheException; import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.NaturalIdRegion; import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.access.AccessType; @@ -38,11 +39,17 @@ import org.redisson.hibernate.strategy.TransactionalNaturalIdRegionAccessStrateg public class RedissonNaturalIdRegion extends BaseRegion implements NaturalIdRegion { private final Settings settings; + private final CacheKeysFactory cacheKeysFactory; public RedissonNaturalIdRegion(RMapCache mapCache, RegionFactory regionFactory, - CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey) { + CacheDataDescription metadata, Settings settings, Properties properties, String defaultKey, CacheKeysFactory cacheKeysFactory) { super(mapCache, regionFactory, metadata, properties, defaultKey); this.settings = settings; + this.cacheKeysFactory = cacheKeysFactory; + } + + public CacheKeysFactory getCacheKeysFactory() { + return cacheKeysFactory; } @Override diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteCollectionRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteCollectionRegionAccessStrategy.java index facbfb727..d9abad995 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteCollectionRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteCollectionRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; +import org.redisson.hibernate.region.RedissonCollectionRegion; /** * @@ -76,12 +77,12 @@ public class NonStrictReadWriteCollectionRegionAccessStrategy extends BaseRegion @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().createCollectionKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetCollectionId( cacheKey ); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().getCollectionId( cacheKey ); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteEntityRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteEntityRegionAccessStrategy.java index f9225e59c..c465ca208 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteEntityRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteEntityRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonEntityRegion; /** * @@ -99,12 +100,12 @@ public class NonStrictReadWriteEntityRegionAccessStrategy extends BaseRegionAcce @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, factory, tenantIdentifier ); + return ((RedissonEntityRegion)region).getCacheKeysFactory().createEntityKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetEntityId( cacheKey ); + return ((RedissonEntityRegion)region).getCacheKeysFactory().getEntityId( cacheKey ); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteNaturalIdRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteNaturalIdRegionAccessStrategy.java index 000bce917..e0401e433 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteNaturalIdRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/NonStrictReadWriteNaturalIdRegionAccessStrategy.java @@ -24,6 +24,7 @@ import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonNaturalIdRegion; /** * @@ -96,12 +97,12 @@ public class NonStrictReadWriteNaturalIdRegionAccessStrategy extends BaseRegionA @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().createNaturalIdKey(naturalIdValues, persister, session); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().getNaturalIdValues(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyCollectionRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyCollectionRegionAccessStrategy.java index caf2f1bda..118fda6bd 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyCollectionRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyCollectionRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; +import org.redisson.hibernate.region.RedissonCollectionRegion; /** * @@ -69,12 +70,12 @@ public class ReadOnlyCollectionRegionAccessStrategy extends BaseRegionAccessStra @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().createCollectionKey(id, persister, factory, tenantIdentifier); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().getCollectionId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyEntityRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyEntityRegionAccessStrategy.java index c7db4f894..6764cc024 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyEntityRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyEntityRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonEntityRegion; /** * @@ -93,12 +94,12 @@ public class ReadOnlyEntityRegionAccessStrategy extends BaseRegionAccessStrategy @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, factory, tenantIdentifier ); + return ((RedissonEntityRegion)region).getCacheKeysFactory().createEntityKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + return ((RedissonEntityRegion)region).getCacheKeysFactory().getEntityId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyNaturalIdRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyNaturalIdRegionAccessStrategy.java index 6a4a276c5..d953505c7 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyNaturalIdRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadOnlyNaturalIdRegionAccessStrategy.java @@ -24,6 +24,7 @@ import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonNaturalIdRegion; /** * @@ -90,12 +91,12 @@ public class ReadOnlyNaturalIdRegionAccessStrategy extends BaseRegionAccessStrat @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().createNaturalIdKey(naturalIdValues, persister, session); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().getNaturalIdValues(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteCollectionRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteCollectionRegionAccessStrategy.java index 6fc48f201..3aad870a9 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteCollectionRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteCollectionRegionAccessStrategy.java @@ -23,6 +23,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.persister.collection.CollectionPersister; import org.redisson.api.RMapCache; +import org.redisson.hibernate.region.RedissonCollectionRegion; /** * @@ -43,12 +44,12 @@ public class ReadWriteCollectionRegionAccessStrategy extends AbstractReadWriteAc @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().createCollectionKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().getCollectionId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteEntityRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteEntityRegionAccessStrategy.java index 0104c8e23..836870b20 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteEntityRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteEntityRegionAccessStrategy.java @@ -26,6 +26,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; import org.redisson.api.RMapCache; +import org.redisson.hibernate.region.RedissonEntityRegion; /** * @@ -69,12 +70,12 @@ public class ReadWriteEntityRegionAccessStrategy extends AbstractReadWriteAccess @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateEntityKey(id, persister, factory, tenantIdentifier); + return ((RedissonEntityRegion)region).getCacheKeysFactory().createEntityKey(id, persister, factory, tenantIdentifier); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + return ((RedissonEntityRegion)region).getCacheKeysFactory().getEntityId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteNaturalIdRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteNaturalIdRegionAccessStrategy.java index 13aff7558..df21f9aa2 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteNaturalIdRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/ReadWriteNaturalIdRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; import org.redisson.api.RMapCache; +import org.redisson.hibernate.region.RedissonNaturalIdRegion; /** * @@ -67,12 +68,12 @@ public class ReadWriteNaturalIdRegionAccessStrategy extends AbstractReadWriteAcc @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().createNaturalIdKey(naturalIdValues, persister, session); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().getNaturalIdValues(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalCollectionRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalCollectionRegionAccessStrategy.java index 31067e9db..b519f5fb8 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalCollectionRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalCollectionRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.collection.CollectionPersister; +import org.redisson.hibernate.region.RedissonCollectionRegion; /** * @@ -74,12 +75,12 @@ public class TransactionalCollectionRegionAccessStrategy extends BaseRegionAcces @Override public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().createCollectionKey( id, persister, factory, tenantIdentifier ); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + return ((RedissonCollectionRegion)region).getCacheKeysFactory().getCollectionId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalEntityRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalEntityRegionAccessStrategy.java index 314869629..088f482ff 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalEntityRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalEntityRegionAccessStrategy.java @@ -25,6 +25,7 @@ import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonEntityRegion; /** * @@ -97,12 +98,12 @@ public class TransactionalEntityRegionAccessStrategy extends BaseRegionAccessStr @Override public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { - return DefaultCacheKeysFactory.staticCreateEntityKey(id, persister, factory, tenantIdentifier); + return ((RedissonEntityRegion)region).getCacheKeysFactory().createEntityKey(id, persister, factory, tenantIdentifier); } @Override public Object getCacheKeyId(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + return ((RedissonEntityRegion)region).getCacheKeysFactory().getEntityId(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalNaturalIdRegionAccessStrategy.java b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalNaturalIdRegionAccessStrategy.java index 4c8f28ee9..2d9de00b8 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalNaturalIdRegionAccessStrategy.java +++ b/redisson-hibernate/redisson-hibernate-5/src/main/java/org/redisson/hibernate/strategy/TransactionalNaturalIdRegionAccessStrategy.java @@ -24,6 +24,7 @@ import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cfg.Settings; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.persister.entity.EntityPersister; +import org.redisson.hibernate.region.RedissonNaturalIdRegion; /** * @@ -94,12 +95,12 @@ public class TransactionalNaturalIdRegionAccessStrategy extends BaseRegionAccess @Override public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SessionImplementor session) { - return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().createNaturalIdKey(naturalIdValues, persister, session); } @Override public Object[] getNaturalIdValues(Object cacheKey) { - return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + return ((RedissonNaturalIdRegion)region).getCacheKeysFactory().getNaturalIdValues(cacheKey); } } diff --git a/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/CollectionTest.java b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/CollectionTest.java new file mode 100644 index 000000000..785e17bb1 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/CollectionTest.java @@ -0,0 +1,123 @@ +package org.redisson.hibernate; + +import org.hibernate.Session; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.stat.Statistics; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * + * @author Nikita Koksharov + * + */ +public class CollectionTest extends BaseCoreFunctionalTestCase { + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class A implements Serializable { + @Id + Long id; + + @Column(unique = true) String uniqueField; + + @ManyToMany + @JoinTable( + name = "a_b", + joinColumns = @JoinColumn( + name = "unique_field", referencedColumnName = "uniqueField"), + inverseJoinColumns = @JoinColumn( + name = "b_id", referencedColumnName = "id")) + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + private List bs = new ArrayList<>(); + } + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class B implements Serializable { + @Id Long id; + + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { A.class, B.class }; + } + + @Override + protected void configure(Configuration cfg) { + super.configure(cfg); + cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); + cfg.setProperty(Environment.USER, "sa"); + cfg.setProperty(Environment.PASS, ""); + cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); + cfg.setProperty(Environment.GENERATE_STATISTICS, "true"); + + cfg.setProperty(Environment.SHOW_SQL, "true"); + cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); + cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); + cfg.setProperty(Environment.CACHE_REGION_FACTORY, RedissonRegionFactory.class.getName()); + } + + @Before + public void before() { + sessionFactory().getCache().evictEntityRegions(); + sessionFactory().getStatistics().clear(); + } + + @Test + public void testQuery() { + Statistics stats = sessionFactory().getStatistics(); + + Session s = openSession(); + s.beginTransaction(); + + A a = new A(); + a.id = 1L; + a.uniqueField = "1"; + B b = new B(); + b.id = 1L; + s.save(b); + a.bs.add(b); + s.save(a); + s.flush(); + s.getTransaction().commit(); + + s = openSession(); + s.beginTransaction(); + A a1 = s.get(A.class, 1L); + System.out.println("here1"); + assertThat(a1.bs).hasSize(1); + s.getTransaction().commit(); + + Assert.assertEquals(0, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + s = openSession(); + s.beginTransaction(); + A a2 = s.get(A.class, 1L); + B b2 = a2.bs.iterator().next(); + assertThat(a2.bs.size()).isEqualTo(1); + s.getTransaction().commit(); + + s.close(); + + Assert.assertEquals(1, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + stats.logSummary(); + + } + +} diff --git a/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/ReadWriteTest.java b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/ReadWriteTest.java index eb1ff6239..8d340b8c9 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/ReadWriteTest.java +++ b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/ReadWriteTest.java @@ -31,7 +31,7 @@ public class ReadWriteTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); diff --git a/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/TransactionalTest.java b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/TransactionalTest.java index 3b346a459..feb91b606 100644 --- a/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/TransactionalTest.java +++ b/redisson-hibernate/redisson-hibernate-5/src/test/java/org/redisson/hibernate/TransactionalTest.java @@ -31,7 +31,7 @@ public class TransactionalTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); diff --git a/redisson-hibernate/redisson-hibernate-5/src/test/resources/org/redisson/hibernate/redisson.json b/redisson-hibernate/redisson-hibernate-5/src/test/resources/org/redisson/hibernate/redisson.json deleted file mode 100644 index 9414f3be5..000000000 --- a/redisson-hibernate/redisson-hibernate-5/src/test/resources/org/redisson/hibernate/redisson.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - } -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-5/src/test/resources/redisson.json b/redisson-hibernate/redisson-hibernate-5/src/test/resources/redisson.json deleted file mode 100644 index 9414f3be5..000000000 --- a/redisson-hibernate/redisson-hibernate-5/src/test/resources/redisson.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - } -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java b/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java new file mode 100644 index 000000000..09eba0cd9 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2013-2020 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-52/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java b/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java index 2d776560b..22064d184 100644 --- a/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java +++ b/redisson-hibernate/redisson-hibernate-52/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java @@ -15,24 +15,10 @@ */ package org.redisson.hibernate; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Properties; - import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cache.CacheException; -import org.hibernate.cache.internal.DefaultCacheKeysFactory; -import org.hibernate.cache.spi.CacheDataDescription; -import org.hibernate.cache.spi.CacheKeysFactory; -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.*; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; @@ -44,11 +30,13 @@ import org.redisson.api.RScript; import org.redisson.api.RedissonClient; import org.redisson.client.codec.LongCodec; import org.redisson.config.Config; -import org.redisson.hibernate.region.RedissonCollectionRegion; -import org.redisson.hibernate.region.RedissonEntityRegion; -import org.redisson.hibernate.region.RedissonNaturalIdRegion; -import org.redisson.hibernate.region.RedissonQueryRegion; -import org.redisson.hibernate.region.RedissonTimestampsRegion; +import org.redisson.hibernate.region.*; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Properties; /** * Hibernate Cache region factory based on Redisson. @@ -94,7 +82,7 @@ public class RedissonRegionFactory implements RegionFactory { StrategySelector selector = settings.getServiceRegistry().getService(StrategySelector.class); cacheKeysFactory = selector.resolveDefaultableStrategy(CacheKeysFactory.class, - properties.get(Environment.CACHE_KEYS_FACTORY), new DefaultCacheKeysFactory()); + properties.get(Environment.CACHE_KEYS_FACTORY), new RedissonCacheKeysFactory(redisson.getConfig().getCodec())); } protected RedissonClient createRedissonClient(Properties properties) { diff --git a/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/CollectionTest.java b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/CollectionTest.java new file mode 100644 index 000000000..785e17bb1 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/CollectionTest.java @@ -0,0 +1,123 @@ +package org.redisson.hibernate; + +import org.hibernate.Session; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.stat.Statistics; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * + * @author Nikita Koksharov + * + */ +public class CollectionTest extends BaseCoreFunctionalTestCase { + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class A implements Serializable { + @Id + Long id; + + @Column(unique = true) String uniqueField; + + @ManyToMany + @JoinTable( + name = "a_b", + joinColumns = @JoinColumn( + name = "unique_field", referencedColumnName = "uniqueField"), + inverseJoinColumns = @JoinColumn( + name = "b_id", referencedColumnName = "id")) + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + private List bs = new ArrayList<>(); + } + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class B implements Serializable { + @Id Long id; + + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { A.class, B.class }; + } + + @Override + protected void configure(Configuration cfg) { + super.configure(cfg); + cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); + cfg.setProperty(Environment.USER, "sa"); + cfg.setProperty(Environment.PASS, ""); + cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); + cfg.setProperty(Environment.GENERATE_STATISTICS, "true"); + + cfg.setProperty(Environment.SHOW_SQL, "true"); + cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); + cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); + cfg.setProperty(Environment.CACHE_REGION_FACTORY, RedissonRegionFactory.class.getName()); + } + + @Before + public void before() { + sessionFactory().getCache().evictEntityRegions(); + sessionFactory().getStatistics().clear(); + } + + @Test + public void testQuery() { + Statistics stats = sessionFactory().getStatistics(); + + Session s = openSession(); + s.beginTransaction(); + + A a = new A(); + a.id = 1L; + a.uniqueField = "1"; + B b = new B(); + b.id = 1L; + s.save(b); + a.bs.add(b); + s.save(a); + s.flush(); + s.getTransaction().commit(); + + s = openSession(); + s.beginTransaction(); + A a1 = s.get(A.class, 1L); + System.out.println("here1"); + assertThat(a1.bs).hasSize(1); + s.getTransaction().commit(); + + Assert.assertEquals(0, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + s = openSession(); + s.beginTransaction(); + A a2 = s.get(A.class, 1L); + B b2 = a2.bs.iterator().next(); + assertThat(a2.bs.size()).isEqualTo(1); + s.getTransaction().commit(); + + s.close(); + + Assert.assertEquals(1, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + stats.logSummary(); + + } + +} diff --git a/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/ReadWriteTest.java b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/ReadWriteTest.java index 4bf28e9bd..803a65883 100644 --- a/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/ReadWriteTest.java +++ b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/ReadWriteTest.java @@ -31,7 +31,7 @@ public class ReadWriteTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); diff --git a/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/TransactionalTest.java b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/TransactionalTest.java index 8b479921a..ed9933780 100644 --- a/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/TransactionalTest.java +++ b/redisson-hibernate/redisson-hibernate-52/src/test/java/org/redisson/hibernate/TransactionalTest.java @@ -41,7 +41,7 @@ public class TransactionalTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); diff --git a/redisson-hibernate/redisson-hibernate-52/src/test/resources/org/redisson/hibernate/redisson.json b/redisson-hibernate/redisson-hibernate-52/src/test/resources/org/redisson/hibernate/redisson.json deleted file mode 100644 index 6348f5e7d..000000000 --- a/redisson-hibernate/redisson-hibernate-52/src/test/resources/org/redisson/hibernate/redisson.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - }, - "registrationKey": "LJk6V4gqOgTOKZ53Cf2MywSb3/M+AW4igUgBG0pLbj77G2AMBpBkELbiuT9B3HSwqhGN5kxDNtPeUpLdTJLdNaoWSKLO6P9wozkdens3nfi7VE8VEwArQ1naIBLuGMQ5DZ3AHJ4cvYnj0RkAE/lx6sU/uWzBTB1e9jW9sLDSD8M=" -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-52/src/test/resources/redisson.json b/redisson-hibernate/redisson-hibernate-52/src/test/resources/redisson.json deleted file mode 100644 index 6348f5e7d..000000000 --- a/redisson-hibernate/redisson-hibernate-52/src/test/resources/redisson.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "singleServerConfig":{ - "address": "redis://127.0.0.1:6379" - }, - "codec":{ - "class":"org.redisson.codec.FstCodec" - }, - "registrationKey": "LJk6V4gqOgTOKZ53Cf2MywSb3/M+AW4igUgBG0pLbj77G2AMBpBkELbiuT9B3HSwqhGN5kxDNtPeUpLdTJLdNaoWSKLO6P9wozkdens3nfi7VE8VEwArQ1naIBLuGMQ5DZ3AHJ4cvYnj0RkAE/lx6sU/uWzBTB1e9jW9sLDSD8M=" -} \ No newline at end of file diff --git a/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java b/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java new file mode 100644 index 000000000..09eba0cd9 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonCacheKeysFactory.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2013-2020 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-53/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java b/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java index 54dfd5bb8..f29e79a69 100644 --- a/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java +++ b/redisson-hibernate/redisson-hibernate-53/src/main/java/org/redisson/hibernate/RedissonRegionFactory.java @@ -20,7 +20,6 @@ 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.internal.DefaultCacheKeysFactory; import org.hibernate.cache.spi.CacheKeysFactory; import org.hibernate.cache.spi.DomainDataRegion; import org.hibernate.cache.spi.access.AccessType; @@ -80,15 +79,19 @@ public class RedissonRegionFactory extends RegionFactoryTemplate { private RedissonClient redisson; private CacheKeysFactory cacheKeysFactory; private boolean fallback; - + + @Override + protected CacheKeysFactory getImplicitCacheKeysFactory() { + return cacheKeysFactory; + } + @Override protected void prepareForUse(SessionFactoryOptions settings, @SuppressWarnings("rawtypes") Map properties) throws CacheException { this.redisson = createRedissonClient(properties); StrategySelector selector = settings.getServiceRegistry().getService(StrategySelector.class); cacheKeysFactory = selector.resolveDefaultableStrategy(CacheKeysFactory.class, - properties.get(Environment.CACHE_KEYS_FACTORY), DefaultCacheKeysFactory.INSTANCE); - + properties.get(Environment.CACHE_KEYS_FACTORY), new RedissonCacheKeysFactory(redisson.getConfig().getCodec())); } protected RedissonClient createRedissonClient(Map properties) { @@ -192,11 +195,11 @@ public class RedissonRegionFactory extends RegionFactoryTemplate { regionConfig, this, createDomainDataStorageAccess( regionConfig, buildingContext ), - cacheKeysFactory, + getImplicitCacheKeysFactory(), buildingContext ); } - + @Override protected DomainDataStorageAccess createDomainDataStorageAccess(DomainDataRegionConfig regionConfig, DomainDataRegionBuildingContext buildingContext) { diff --git a/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/CollectionTest.java b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/CollectionTest.java new file mode 100644 index 000000000..785e17bb1 --- /dev/null +++ b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/CollectionTest.java @@ -0,0 +1,123 @@ +package org.redisson.hibernate; + +import org.hibernate.Session; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.stat.Statistics; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * + * @author Nikita Koksharov + * + */ +public class CollectionTest extends BaseCoreFunctionalTestCase { + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class A implements Serializable { + @Id + Long id; + + @Column(unique = true) String uniqueField; + + @ManyToMany + @JoinTable( + name = "a_b", + joinColumns = @JoinColumn( + name = "unique_field", referencedColumnName = "uniqueField"), + inverseJoinColumns = @JoinColumn( + name = "b_id", referencedColumnName = "id")) + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + private List bs = new ArrayList<>(); + } + + @Entity + @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) + public static class B implements Serializable { + @Id Long id; + + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { A.class, B.class }; + } + + @Override + protected void configure(Configuration cfg) { + super.configure(cfg); + cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); + cfg.setProperty(Environment.USER, "sa"); + cfg.setProperty(Environment.PASS, ""); + cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); + cfg.setProperty(Environment.GENERATE_STATISTICS, "true"); + + cfg.setProperty(Environment.SHOW_SQL, "true"); + cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true"); + cfg.setProperty(Environment.USE_QUERY_CACHE, "true"); + cfg.setProperty(Environment.CACHE_REGION_FACTORY, RedissonRegionFactory.class.getName()); + } + + @Before + public void before() { + sessionFactory().getCache().evictEntityRegions(); + sessionFactory().getStatistics().clear(); + } + + @Test + public void testQuery() { + Statistics stats = sessionFactory().getStatistics(); + + Session s = openSession(); + s.beginTransaction(); + + A a = new A(); + a.id = 1L; + a.uniqueField = "1"; + B b = new B(); + b.id = 1L; + s.save(b); + a.bs.add(b); + s.save(a); + s.flush(); + s.getTransaction().commit(); + + s = openSession(); + s.beginTransaction(); + A a1 = s.get(A.class, 1L); + System.out.println("here1"); + assertThat(a1.bs).hasSize(1); + s.getTransaction().commit(); + + Assert.assertEquals(0, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + s = openSession(); + s.beginTransaction(); + A a2 = s.get(A.class, 1L); + B b2 = a2.bs.iterator().next(); + assertThat(a2.bs.size()).isEqualTo(1); + s.getTransaction().commit(); + + s.close(); + + Assert.assertEquals(1, stats.getSecondLevelCacheStatistics("org.redisson.hibernate.CollectionTest$A.bs").getHitCount()); + + stats.logSummary(); + + } + +} diff --git a/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/ReadWriteTest.java b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/ReadWriteTest.java index 0ff26a9c6..2f1efdb22 100644 --- a/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/ReadWriteTest.java +++ b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/ReadWriteTest.java @@ -31,7 +31,7 @@ public class ReadWriteTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, ""); diff --git a/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/TransactionalTest.java b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/TransactionalTest.java index 3b346a459..feb91b606 100644 --- a/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/TransactionalTest.java +++ b/redisson-hibernate/redisson-hibernate-53/src/test/java/org/redisson/hibernate/TransactionalTest.java @@ -31,7 +31,7 @@ public class TransactionalTest extends BaseCoreFunctionalTestCase { protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(Environment.DRIVER, org.h2.Driver.class.getName()); - cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"); + cfg.setProperty(Environment.URL, "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;"); cfg.setProperty(Environment.USER, "sa"); cfg.setProperty(Environment.PASS, ""); cfg.setProperty(Environment.CACHE_REGION_PREFIX, "");