diff --git a/CHANGES.md b/CHANGES.md index 631cc735451ef5f8cca512b939a36bc127c57029..b4913a37b349093d0397c8858cbe4d7413dde34b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,17 @@ # J2Cache 版本更新记录 +**j2cache-core 2.8.2 (2020-4-26)** + +1. 修复在使用redis-cluster时redisClient未初始化导致NPE +2. redis二级缓存的keys、clear方法使用scan命令实现(以应对云平台Redis服务对keys命令的限制) + +**j2cache-core 2.8.1 (2020-4-16)** + +* 修复redis使用lettuce连接时,设置密码中出现特殊字符'@'时连接地址及密码解析出错的异常(感谢 [@eddy](https://gitee.com/xqxyxchy)) +详情请看 [https://gitee.com/ld/J2Cache/pulls/149](https://gitee.com/ld/J2Cache/pulls/149) + + +------ **J2Cache 2.4.1-release (2018-8-xx)** diff --git a/README.md b/README.md index b757a403d229a14dded60a927f52c5cd9909f211..017339b015009a6e2cf4655591f348dab814cc43 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -![J2Cache](docs/J2Cache.png) - -# J2Cache —— 基于内存和 Redis 的两级 Java 缓存框架 - +

+ J2Cache +

+

+

J2Cache —— 基于内存和 Redis 的两级 Java 缓存框架

+

专用QQ群: `379110351` JavaDoc [https://apidoc.gitee.com/ld/J2Cache/](https://apidoc.gitee.com/ld/J2Cache/) @@ -10,7 +12,17 @@ J2Cache 是 OSChina 目前正在使用的两级缓存框架(要求至少 Java 由于大量的缓存读取会导致 L2 的网络成为整个系统的瓶颈,因此 L1 的目标是降低对 L2 的读取次数。 该缓存框架主要用于集群环境中。单机也可使用,用于避免应用重启导致的缓存冷启动后对后端业务的冲击。 -J2Cache 和普通缓存框架有何不同,它解决了什么问题? [https://my.oschina.net/javayou/blog/1931381](https://my.oschina.net/javayou/blog/1931381) +J2Cache 相关文章: + +- [J2Cache 和普通缓存框架有何不同,它解决了什么问题?](https://my.oschina.net/javayou/blog/1931381) +- [J2Cache 两级缓存中的 Region 到底是什么东西?](https://my.oschina.net/javayou/blog/3031773) +- [如何让 J2Cache 在多种编程语言环境中使用](https://my.oschina.net/javayou/blog/2247729) +- [J2Cache 中使用 Lettuce 替代 Jedis 管理 Redis 连接](https://my.oschina.net/javayou/blog/2247710) +- [如何通过 J2Cache 实现分布式 session 存储](https://my.oschina.net/javayou/blog/2117109) +- [J2Cache 没有 Redis 也可以实现多节点的缓存同步](https://my.oschina.net/javayou/blog/1865908) +- [微服务的架构里应该使用 J2Cache 两级缓存框架](https://my.oschina.net/javayou/blog/1827480) +- [J2Cache 和 JetCache 框架有何不同?](https://my.oschina.net/javayou/blog/2988523) +- [J2Cache 线上异常问题排查记录](https://my.oschina.net/keking/blog/3058409) J2Cache 已经有 Python 语言版本了,详情请看 [https://gitee.com/ld/Py3Cache](https://gitee.com/ld/Py3Cache) @@ -79,6 +91,7 @@ J2Cache 默认使用 [Caffeine](https://www.oschina.net/p/ben-manes-caffeine) xxxxx ``` +中央仓库地址:[>>飞机](https://mvnrepository.com/artifact/net.oschina.j2cache/j2cache-core) **二. 准备配置** @@ -230,12 +243,14 @@ channel.close(); * https://gitee.com/xchao/j-im * https://gitee.com/fuyang_lipengjun/platform * https://gitee.com/xcOschina/freeter-admin +* https://gitee.com/thinkgem/jeesite4 +* https://gitee.com/noear/weed3 +* https://gitee.com/zuihou111/zuihou-admin-cloud 更多项目收集中,如果你的项目用了,请告诉我 ## TODO ## -1. 当 ehcache 配置模板为永久时的处理 -2. 应用重启,从 Redis 获取数据后,一级缓存的有效期大于预设值 -3. 多节点强一致性? -4. 欢迎大家给 J2Cache 提建议 \ No newline at end of file +1. 应用重启,从 Redis 获取数据后,一级缓存的有效期大于预设值 +2. 多节点强一致性? +3. 欢迎大家给 J2Cache 提建议 \ No newline at end of file diff --git a/README_EN.md b/README_EN.md index 7c82df0dabf5ce9101c8ebe7b9b2b29781584f0c..ed65dfa39dcbf5f0fbab5dbcc3eacd537c9403fe 100644 --- a/README_EN.md +++ b/README_EN.md @@ -68,4 +68,5 @@ Defining the validity period of the cached data in the program will cause the ca * https://gitee.com/jfinal/jfinal * https://gitee.com/fuhai/jboot * https://gitee.com/tywo45/t-io +* https://gitee.com/noear/weed3 * ... \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml index e3d371e849e8573c1b592767bb6083f43b4de2a5..c872a565d14b2f329b1e3c0d369d40b7eb33f813 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -3,11 +3,12 @@ net.oschina.j2cache j2cache - 2.7.0-release + 2.8.0-release 4.0.0 j2cache-core + 2.8.2-release @@ -26,7 +27,14 @@ io.lettuce lettuce-core - 5.1.0.RELEASE + 5.1.3.RELEASE + provided + + + + org.apache.commons + commons-pool2 + 2.5.0 provided @@ -91,7 +99,7 @@ com.rabbitmq amqp-client - 5.3.0 + 5.9.0 provided @@ -116,6 +124,13 @@ provided + + com.jfirer + Fse + 1.0 + provided + + J2Cache - core diff --git a/core/resources/j2cache.properties b/core/resources/j2cache.properties index 9bf83f3a8f8a299d2771d5d97a7fdb6571558d05..dfc8d7af429351993ac6f30d072f8922b508df07 100644 --- a/core/resources/j2cache.properties +++ b/core/resources/j2cache.properties @@ -6,7 +6,7 @@ # values: # jgroups -> use jgroups's multicast # redis -> use redis publish/subscribe mechanism (using jedis) -# lettuce -> use redis publish/subscribe mechanism (using lettuce) +# lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend) # rabbitmq -> use RabbitMQ publisher/consumer mechanism # rocketmq -> use RocketMQ publisher/consumer mechanism # none -> don't notify the other nodes in cluster @@ -63,10 +63,11 @@ j2cache.default_cache_null_object = true # Cache Serialization Provider # values: # fst -> using fast-serialization (recommend) -# kyro -> using kyro serialization +# kryo -> using kryo serialization # json -> using fst's json serialization (testing) # fastjson -> using fastjson serialization (embed non-static class not support) # java -> java standard +# fse -> using fse serialization # [classname implements Serializer] ######################################### @@ -98,8 +99,8 @@ caffeine.properties = /caffeine.properties # # single -> single redis server # sentinel -> master-slaves servers -# cluster -> cluster servers (数据库配置无效,使用 database = 0) -# sharded -> sharded servers (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:password@127.0.0.1:6379/0) +# cluster -> cluster servers (\u6570\u636e\u5e93\u914d\u7f6e\u65e0\u6548\uff0c\u4f7f\u7528 database = 0\uff09 +# sharded -> sharded servers (\u5bc6\u7801\u3001\u6570\u636e\u5e93\u5fc5\u987b\u5728 hosts \u4e2d\u6307\u5b9a\uff0c\u4e14\u8fde\u63a5\u6c60\u914d\u7f6e\u65e0\u6548 ; redis://user:password@127.0.0.1:6379/0\uff09 # ######################################### @@ -119,6 +120,9 @@ redis.cluster_name = j2cache ## redis cache namespace optional, default[empty] redis.namespace = +## redis command scan parameter count, default[1000] +#redis.scanCount = 1000 + ## connection # Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379 @@ -126,6 +130,7 @@ redis.hosts = 127.0.0.1:6379 redis.timeout = 2000 redis.password = redis.database = 0 +redis.ssl = false ## redis pool properties redis.maxTotal = 100 @@ -143,14 +148,33 @@ redis.timeBetweenEvictionRunsMillis = 300000 redis.blockWhenExhausted = false redis.jmxEnabled = false +######################################### +# Lettuce scheme +# +# redis -> single redis server +# rediss -> single redis server with ssl +# redis-sentinel -> redis sentinel +# redis-cluster -> cluster servers +# +######################################### + +## redis command scan parameter count, default[1000] +#lettuce.scanCount = 1000 lettuce.namespace = -lettuce.storage = generic +lettuce.storage = hash lettuce.channel = j2cache lettuce.scheme = redis lettuce.hosts = 127.0.0.1:6379 lettuce.password = lettuce.database = 0 lettuce.sentinelMasterId = +lettuce.maxTotal = 100 +lettuce.maxIdle = 10 +lettuce.minIdle = 10 +# timeout in milliseconds +lettuce.timeout = 10000 +# redis cluster topology refresh interval in milliseconds +lettuce.clusterTopologyRefresh = 3000 ######################################### # memcached server configurations diff --git a/core/src/net/oschina/j2cache/CacheChannel.java b/core/src/net/oschina/j2cache/CacheChannel.java index 767d9715ffdfac27306c28796ab1beff4a027c6b..1c676ee38731ec19e7b9ba6d1fc81e3a93a7358c 100644 --- a/core/src/net/oschina/j2cache/CacheChannel.java +++ b/core/src/net/oschina/j2cache/CacheChannel.java @@ -30,17 +30,26 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { private static final Map _g_keyLocks = new ConcurrentHashMap<>(); private J2CacheConfig config; + private CacheProviderHolder holder; private boolean defaultCacheNullObject ; + private boolean closed; - public CacheChannel(J2CacheConfig config) { + public CacheChannel(J2CacheConfig config, CacheProviderHolder holder) { this.config = config; + this.holder = holder; this.defaultCacheNullObject = config.isDefaultCacheNullObject(); + this.closed = false; } private NullObject newNullObject() { return new NullObject(); } + private void assertNotClose() { + if(closed) + throw new IllegalStateException("CacheChannel closed"); + } + /** *

Just for Inner Use.

* @@ -69,27 +78,29 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { */ public CacheObject get(String region, String key, boolean...cacheNullObject) { + this.assertNotClose(); + CacheObject obj = new CacheObject(region, key, CacheObject.LEVEL_1); - obj.setValue(CacheProviderHolder.getLevel1Cache(region).get(key)); + obj.setValue(holder.getLevel1Cache(region).get(key)); if(obj.rawValue() != null) return obj; String lock_key = key + '%' + region; synchronized (_g_keyLocks.computeIfAbsent(lock_key, v -> new Object())) { - obj.setValue(CacheProviderHolder.getLevel1Cache(region).get(key)); + obj.setValue(holder.getLevel1Cache(region).get(key)); if(obj.rawValue() != null) return obj; try { obj.setLevel(CacheObject.LEVEL_2); - obj.setValue(CacheProviderHolder.getLevel2Cache(region).get(key)); - if (obj.rawValue() != null) - CacheProviderHolder.getLevel1Cache(region).put(key, obj.rawValue()); - else { - boolean cacheNull = (cacheNullObject.length>0)?cacheNullObject[0]: defaultCacheNullObject; - if(cacheNull) - set(region, key, newNullObject(), true); - } + obj.setValue(holder.getLevel2Cache(region).get(key)); + if (obj.rawValue() != null) { + holder.getLevel1Cache(region).put(key, obj.rawValue()); + }else { + boolean cacheNull = (cacheNullObject.length > 0) ? cacheNullObject[0] : defaultCacheNullObject; + if (cacheNull) + set(region, key, newNullObject(), true); + } } finally { _g_keyLocks.remove(lock_key); } @@ -107,6 +118,9 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return cache object */ public CacheObject get(String region, String key, Function loader, boolean...cacheNullObject) { + + this.assertNotClose(); + CacheObject cache = get(region, key, false); if (cache.rawValue() != null) @@ -138,7 +152,10 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return cache object */ public Map get(String region, Collection keys) { - final Map objs = CacheProviderHolder.getLevel1Cache(region).get(keys); + + this.assertNotClose(); + + final Map objs = holder.getLevel1Cache(region).get(keys); List level2Keys = keys.stream().filter(k -> !objs.containsKey(k) || objs.get(k) == null).collect(Collectors.toList()); Map results = objs.entrySet().stream().filter(p -> p.getValue() != null).collect( Collectors.toMap( @@ -147,11 +164,11 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { ) ); - Map objs_level2 = CacheProviderHolder.getLevel2Cache(region).get(level2Keys); + Map objs_level2 = holder.getLevel2Cache(region).get(level2Keys); objs_level2.forEach((k,v) -> { results.put(k, new CacheObject(region, k, CacheObject.LEVEL_2, v)); if (v != null) - CacheProviderHolder.getLevel1Cache(region).put(k, v); + holder.getLevel1Cache(region).put(k, v); }); return results; @@ -166,6 +183,9 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return multiple cache data */ public Map get(String region, Collection keys, Function loader, boolean...cacheNullObject) { + + this.assertNotClose(); + Map results = get(region, keys); results.entrySet().stream().filter(e -> e.getValue().rawValue() == null).forEach( e -> { String lock_key = e.getKey() + '@' + region; @@ -207,9 +227,12 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return 0(不存在),1(一级),2(二级) */ public int check(String region, String key) { - if(CacheProviderHolder.getLevel1Cache(region).exists(key)) + + this.assertNotClose(); + + if(holder.getLevel1Cache(region).exists(key)) return 1; - if(CacheProviderHolder.getLevel2Cache(region).exists(key)) + if(holder.getLevel2Cache(region).exists(key)) return 2; return 0; } @@ -234,13 +257,16 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param cacheNullObject if allow cache null object */ public void set(String region, String key, Object value, boolean cacheNullObject) { + + this.assertNotClose(); + if (!cacheNullObject && value == null) return ; try { - Level1Cache level1 = CacheProviderHolder.getLevel1Cache(region); + Level1Cache level1 = holder.getLevel1Cache(region); level1.put(key, (value==null && cacheNullObject)?newNullObject():value); - Level2Cache level2 = CacheProviderHolder.getLevel2Cache(region); + Level2Cache level2 = holder.getLevel2Cache(region); if(config.isSyncTtlToRedis()) level2.put(key, (value==null && cacheNullObject)?newNullObject():value, level1.ttl()); else @@ -277,6 +303,9 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param cacheNullObject if allow cache null object */ public void set(String region, String key, Object value, long timeToLiveInSeconds, boolean cacheNullObject) { + + this.assertNotClose(); + if (!cacheNullObject && value == null) return ; @@ -284,8 +313,8 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { set(region, key, value, cacheNullObject); else { try { - CacheProviderHolder.getLevel1Cache(region, timeToLiveInSeconds).put(key, (value==null && cacheNullObject)?newNullObject():value); - Level2Cache level2 = CacheProviderHolder.getLevel2Cache(region); + holder.getLevel1Cache(region, timeToLiveInSeconds).put(key, (value==null && cacheNullObject)?newNullObject():value); + Level2Cache level2 = holder.getLevel2Cache(region); if(config.isSyncTtlToRedis()) level2.put(key, (value==null && cacheNullObject)?newNullObject():value, timeToLiveInSeconds); else @@ -312,29 +341,31 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param cacheNullObject if allow cache null object */ public void set(String region, Map elements, boolean cacheNullObject) { + + this.assertNotClose(); + try { if (cacheNullObject && elements.containsValue(null)) { - Map newElems = new HashMap<>(); - newElems.putAll(elements); + Map newElems = new HashMap<>(elements); newElems.forEach((k,v) -> { if (v == null) newElems.put(k, newNullObject()); }); - Level1Cache level1 = CacheProviderHolder.getLevel1Cache(region); + Level1Cache level1 = holder.getLevel1Cache(region); level1.put(newElems); if(config.isSyncTtlToRedis()) - CacheProviderHolder.getLevel2Cache(region).put(newElems, level1.ttl()); + holder.getLevel2Cache(region).put(newElems, level1.ttl()); else - CacheProviderHolder.getLevel2Cache(region).put(newElems); + holder.getLevel2Cache(region).put(newElems); } else { - Level1Cache level1 = CacheProviderHolder.getLevel1Cache(region); + Level1Cache level1 = holder.getLevel1Cache(region); level1.put(elements); if(config.isSyncTtlToRedis()) - CacheProviderHolder.getLevel2Cache(region).put(elements, level1.ttl()); + holder.getLevel2Cache(region).put(elements, level1.ttl()); else - CacheProviderHolder.getLevel2Cache(region).put(elements); + holder.getLevel2Cache(region).put(elements); } } finally { //广播 @@ -366,34 +397,37 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param cacheNullObject if allow cache null object */ public void set(String region, Map elements, long timeToLiveInSeconds, boolean cacheNullObject) { - if(timeToLiveInSeconds <= 0) + + this.assertNotClose(); + + if(timeToLiveInSeconds <= 0) { set(region, elements, cacheNullObject); - else { - try { - if (cacheNullObject && elements.containsValue(null)) { - Map newElems = new HashMap<>(); - newElems.putAll(elements); - newElems.forEach((k,v) -> { - if (v == null) - newElems.put(k, newNullObject()); - }); - CacheProviderHolder.getLevel1Cache(region, timeToLiveInSeconds).put(newElems); - if(config.isSyncTtlToRedis()) - CacheProviderHolder.getLevel2Cache(region).put(newElems, timeToLiveInSeconds); - else - CacheProviderHolder.getLevel2Cache(region).put(newElems); - } - else { - CacheProviderHolder.getLevel1Cache(region, timeToLiveInSeconds).put(elements); - if(config.isSyncTtlToRedis()) - CacheProviderHolder.getLevel2Cache(region).put(elements, timeToLiveInSeconds); - else - CacheProviderHolder.getLevel2Cache(region).put(elements); - } - } finally { - //广播 - this.sendEvictCmd(region, elements.keySet().stream().toArray(String[]::new)); + return; + } + + try { + if (cacheNullObject && elements.containsValue(null)) { + Map newElems = new HashMap<>(elements); + newElems.forEach((k,v) -> { + if (v == null) + newElems.put(k, newNullObject()); + }); + holder.getLevel1Cache(region, timeToLiveInSeconds).put(newElems); + if(config.isSyncTtlToRedis()) + holder.getLevel2Cache(region).put(newElems, timeToLiveInSeconds); + else + holder.getLevel2Cache(region).put(newElems); + } + else { + holder.getLevel1Cache(region, timeToLiveInSeconds).put(elements); + if(config.isSyncTtlToRedis()) + holder.getLevel2Cache(region).put(elements, timeToLiveInSeconds); + else + holder.getLevel2Cache(region).put(elements); } + } finally { + //广播 + this.sendEvictCmd(region, elements.keySet().stream().toArray(String[]::new)); } } @@ -404,10 +438,13 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param keys: Cache key */ public void evict(String region, String...keys) { + + this.assertNotClose(); + try { //先清比较耗时的二级缓存,再清一级缓存 - CacheProviderHolder.getLevel2Cache(region).evict(keys); - CacheProviderHolder.getLevel1Cache(region).evict(keys); + holder.getLevel2Cache(region).evict(keys); + holder.getLevel1Cache(region).evict(keys); } finally { this.sendEvictCmd(region, keys); //发送广播 } @@ -419,10 +456,13 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param region: Cache region name */ public void clear(String region) { + + this.assertNotClose(); + try { //先清比较耗时的二级缓存,再清一级缓存 - CacheProviderHolder.getLevel2Cache(region).clear(); - CacheProviderHolder.getLevel1Cache(region).clear(); + holder.getLevel2Cache(region).clear(); + holder.getLevel1Cache(region).clear(); }finally { this.sendClearCmd(region); } @@ -433,7 +473,8 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return all the regions */ public Collection regions() { - return CacheProviderHolder.regions(); + this.assertNotClose(); + return holder.regions(); } /** @@ -441,7 +482,8 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @param region Cache Region Name */ public void removeRegion(String region) { - CacheProviderHolder.getL1Provider().removeCache(region); + this.assertNotClose(); + holder.getL1Provider().removeCache(region); } /** @@ -452,9 +494,11 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return key list */ public Collection keys(String region) { + this.assertNotClose(); + Set keys = new HashSet<>(); - keys.addAll(CacheProviderHolder.getLevel1Cache(region).keys()); - keys.addAll(CacheProviderHolder.getLevel2Cache(region).keys()); + keys.addAll(holder.getLevel1Cache(region).keys()); + keys.addAll(holder.getLevel2Cache(region).keys()); return keys; } @@ -462,14 +506,16 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * Close J2Cache */ @Override - public abstract void close(); + public void close() { + this.closed = true; + } /** * 获取一级缓存接口 * @return 返回一级缓存的 CacheProvider 实例 */ public CacheProvider getL1Provider() { - return CacheProviderHolder.getL1Provider(); + return holder.getL1Provider(); } /** @@ -487,7 +533,7 @@ public abstract class CacheChannel implements Closeable , AutoCloseable { * @return 返回二级缓存的 CacheProvider 实例 */ public CacheProvider getL2Provider() { - return CacheProviderHolder.getL2Provider(); + return holder.getL2Provider(); } /** diff --git a/core/src/net/oschina/j2cache/CacheProviderHolder.java b/core/src/net/oschina/j2cache/CacheProviderHolder.java index 8f1ca234995cfa28374ecfb4c5ecac31e0dd484f..6b09a81b4a5159219b1d2d823909522c03c48046 100644 --- a/core/src/net/oschina/j2cache/CacheProviderHolder.java +++ b/core/src/net/oschina/j2cache/CacheProviderHolder.java @@ -30,111 +30,128 @@ import java.util.Collection; /** * 两级的缓存管理器 + * * @author Winter Lau(javayou@gmail.com) */ public class CacheProviderHolder { - private final static Logger log = LoggerFactory.getLogger(CacheProviderHolder.class); - - private static CacheProvider l1_provider; - private static CacheProvider l2_provider; - - private static CacheExpiredListener listener; - - /** - * Initialize Cache Provider - * @param config j2cache config instance - * @param listener cache listener - */ - public static void init(J2CacheConfig config, CacheExpiredListener listener){ - CacheProviderHolder.listener = listener; - CacheProviderHolder.l1_provider = loadProviderInstance(config.getL1CacheName()); - if (!l1_provider.isLevel(CacheObject.LEVEL_1)) - throw new CacheException(l1_provider.getClass().getName() + " is not level_1 cache provider"); - CacheProviderHolder.l1_provider.start(config.getL1CacheProperties()); - log.info("Using L1 CacheProvider : " + l1_provider.getClass().getName()); - - CacheProviderHolder.l2_provider = loadProviderInstance(config.getL2CacheName()); - if (!l2_provider.isLevel(CacheObject.LEVEL_2)) - throw new CacheException(l2_provider.getClass().getName() + " is not level_2 cache provider"); - CacheProviderHolder.l2_provider.start(config.getL2CacheProperties()); - log.info("Using L2 CacheProvider : " + l2_provider.getClass().getName()); - } - - /** - * 关闭缓存 - */ - public final static void shutdown() { - l1_provider.stop(); - l2_provider.stop(); - } - - private final static CacheProvider loadProviderInstance(String cacheIdent) { - if("ehcache".equalsIgnoreCase(cacheIdent)) - return new EhCacheProvider(); - if("ehcache3".equalsIgnoreCase(cacheIdent)) - return new EhCacheProvider3(); - if("caffeine".equalsIgnoreCase(cacheIdent)) - return new CaffeineProvider(); - if("redis".equalsIgnoreCase(cacheIdent)) - return new RedisCacheProvider(); - if("readonly-redis".equalsIgnoreCase(cacheIdent)) - return new ReadonlyRedisCacheProvider(); - if("memcached".equalsIgnoreCase(cacheIdent)) - return new XmemcachedCacheProvider(); - if("lettuce".equalsIgnoreCase(cacheIdent)) - return new LettuceCacheProvider(); - if("none".equalsIgnoreCase(cacheIdent)) - return new NullCacheProvider(); - try { - return (CacheProvider) Class.forName(cacheIdent).newInstance(); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { - throw new CacheException("Failed to initialize cache providers", e); - } - } - - public final static CacheProvider getL1Provider() { - return l1_provider; - } - - public final static CacheProvider getL2Provider() { - return l2_provider; - } - - /** - * 一级缓存实例 - * @param region cache region - * @return level 1 cache instance - */ - public final static Level1Cache getLevel1Cache(String region) { - return (Level1Cache)l1_provider.buildCache(region, listener); - } - - /** - * 一级缓存实例 - * @param region cache region - * @param timeToLiveSeconds cache ttl - * @return level 1 cache instance - */ - public final static Level1Cache getLevel1Cache(String region, long timeToLiveSeconds) { - return (Level1Cache)l1_provider.buildCache(region, timeToLiveSeconds, listener); - } - - /** - * 二级缓存实例 - * @param region cache region - * @return level 2 cache instance - */ - public final static Level2Cache getLevel2Cache(String region) { - return (Level2Cache)l2_provider.buildCache(region, listener); - } - - /** - * return all regions - * @return all regions - */ - public final static Collection regions() { - return l1_provider.regions(); - } + private final static Logger log = LoggerFactory.getLogger(CacheProviderHolder.class); + + private CacheProvider l1_provider; + private CacheProvider l2_provider; + + private CacheExpiredListener listener; + + private CacheProviderHolder() { + } + + /** + * Initialize Cache Provider + * + * @param config j2cache config instance + * @param listener cache listener + * @return holder : return CacheProviderHolder instance + */ + public static CacheProviderHolder init(J2CacheConfig config, CacheExpiredListener listener) { + + CacheProviderHolder holder = new CacheProviderHolder(); + + holder.listener = listener; + holder.l1_provider = loadProviderInstance(config.getL1CacheName()); + if (!holder.l1_provider.isLevel(CacheObject.LEVEL_1)) + throw new CacheException(holder.l1_provider.getClass().getName() + " is not level_1 cache provider"); + holder.l1_provider.start(config.getL1CacheProperties()); + log.info("Using L1 CacheProvider : {}", holder.l1_provider.getClass().getName()); + + holder.l2_provider = loadProviderInstance(config.getL2CacheName()); + if (!holder.l2_provider.isLevel(CacheObject.LEVEL_2)) + throw new CacheException(holder.l2_provider.getClass().getName() + " is not level_2 cache provider"); + holder.l2_provider.start(config.getL2CacheProperties()); + log.info("Using L2 CacheProvider : {}", holder.l2_provider.getClass().getName()); + + return holder; + } + + /** + * 关闭缓存 + */ + public void shutdown() { + l1_provider.stop(); + l2_provider.stop(); + } + + private static CacheProvider loadProviderInstance(String cacheIdent) { + switch (cacheIdent.toLowerCase()) { + case "ehcache": + return new EhCacheProvider(); + case "ehcache3": + return new EhCacheProvider3(); + case "caffeine": + return new CaffeineProvider(); + case "redis": + return new RedisCacheProvider(); + case "readonly-redis": + return new ReadonlyRedisCacheProvider(); + case "memcached": + return new XmemcachedCacheProvider(); + case "lettuce": + return new LettuceCacheProvider(); + case "none": + return new NullCacheProvider(); + } + try { + return (CacheProvider) Class.forName(cacheIdent).newInstance(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new CacheException("Failed to initialize cache providers", e); + } + } + + public CacheProvider getL1Provider() { + return l1_provider; + } + + public CacheProvider getL2Provider() { + return l2_provider; + } + + /** + * 一级缓存实例 + * + * @param region cache region + * @return level 1 cache instance + */ + public Level1Cache getLevel1Cache(String region) { + return (Level1Cache) l1_provider.buildCache(region, listener); + } + + /** + * 一级缓存实例 + * + * @param region cache region + * @param timeToLiveSeconds cache ttl + * @return level 1 cache instance + */ + public Level1Cache getLevel1Cache(String region, long timeToLiveSeconds) { + return (Level1Cache) l1_provider.buildCache(region, timeToLiveSeconds, listener); + } + + /** + * 二级缓存实例 + * + * @param region cache region + * @return level 2 cache instance + */ + public Level2Cache getLevel2Cache(String region) { + return (Level2Cache) l2_provider.buildCache(region, listener); + } + + /** + * return all regions + * + * @return all regions + */ + public Collection regions() { + return l1_provider.regions(); + } } diff --git a/core/src/net/oschina/j2cache/Command.java b/core/src/net/oschina/j2cache/Command.java index 90494247a4458093465ccb21761b4bf402ce7a13..55f57d500a7c1cd893cc074f072ab24f5cf61d26 100644 --- a/core/src/net/oschina/j2cache/Command.java +++ b/core/src/net/oschina/j2cache/Command.java @@ -15,11 +15,10 @@ */ package net.oschina.j2cache; -import java.util.Random; +import java.security.SecureRandom; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.annotation.JSONField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,22 +30,21 @@ import org.slf4j.LoggerFactory; public class Command { private final static Logger log = LoggerFactory.getLogger(Command.class); - private final static int SRC_ID = genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 public final static byte OPT_JOIN = 0x01; //加入集群 public final static byte OPT_EVICT_KEY = 0x02; //删除缓存 public final static byte OPT_CLEAR_KEY = 0x03; //清除缓存 public final static byte OPT_QUIT = 0x04; //退出集群 - private int src = SRC_ID; + private int src; private int operator; private String region; private String[] keys; - - private static int genRandomSrc() { + + public static int genRandomSrc() { long ct = System.currentTimeMillis(); - Random rnd_seed = new Random(ct); - return (int)(rnd_seed.nextInt(10000) * 1000 + ct % 1000); + SecureRandom rndSeed = new SecureRandom(); + return (int) (rndSeed.nextInt(10000) * 1000 + ct % 1000); } public Command(){}//just for json deserialize , dont remove it. @@ -57,14 +55,6 @@ public class Command { this.keys = keys; } - /** - * 返回本地的专有标识 - * @return 节点标识 - */ - public static final int LocalID() { - return SRC_ID; - } - public static Command join() { return new Command(OPT_JOIN, null); } @@ -81,16 +71,11 @@ public class Command { try { return JSON.parseObject(json, Command.class); } catch (JSONException e) { - log.warn("Failed to parse j2cache command: " + json, e); + log.warn("Failed to parse j2cache command: {}", json, e); } return null; } - @JSONField(serialize = false) - public boolean isLocal() { - return this.src == SRC_ID; - } - public int getOperator() { return operator; } diff --git a/core/src/net/oschina/j2cache/J2CacheBuilder.java b/core/src/net/oschina/j2cache/J2CacheBuilder.java index 2ab1fe668a22a8c56167384cb3d1377a6457491b..7bfd416cd8cb534ecec082a3609a85bcb45e5f6f 100644 --- a/core/src/net/oschina/j2cache/J2CacheBuilder.java +++ b/core/src/net/oschina/j2cache/J2CacheBuilder.java @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * 使用自定义配置构建 J2Cache + * * @author Winter Lau (javayou@gmail.com) */ public class J2CacheBuilder { @@ -33,6 +34,7 @@ public class J2CacheBuilder { private final static Logger log = LoggerFactory.getLogger(J2CacheBuilder.class); private CacheChannel channel; + private CacheProviderHolder holder; private ClusterPolicy policy; //不同的广播策略 private AtomicBoolean opened = new AtomicBoolean(false); private J2CacheConfig config; @@ -43,7 +45,8 @@ public class J2CacheBuilder { /** * 初始化 J2Cache,这是一个很重的操作,请勿重复执行 - * @param config j2cache config instance + * + * @param config j2cache config instance * @return J2CacheBuilder instance */ public final static J2CacheBuilder init(J2CacheConfig config) { @@ -52,15 +55,16 @@ public class J2CacheBuilder { /** * 返回缓存操作接口 + * * @return CacheChannel */ - public CacheChannel getChannel(){ - if(!this.opened.get()) { + public CacheChannel getChannel() { + if (this.channel == null || !this.opened.get()) { synchronized (J2CacheBuilder.class) { - if(!this.opened.get()) { + if (this.channel == null || !this.opened.get()) { this.initFromConfig(config); /* 初始化缓存接口 */ - this.channel = new CacheChannel(config) { + this.channel = new CacheChannel(config, holder) { @Override public void sendClearCmd(String region) { policy.sendClearCmd(region); @@ -73,8 +77,9 @@ public class J2CacheBuilder { @Override public void close() { + super.close(); policy.disconnect(); - CacheProviderHolder.shutdown(); + holder.shutdown(); opened.set(false); } }; @@ -90,30 +95,33 @@ public class J2CacheBuilder { */ public void close() { this.channel.close(); + this.channel = null; } /** * 加载配置 + * * @return * @throws IOException */ private void initFromConfig(J2CacheConfig config) { SerializationUtils.init(config.getSerialization(), config.getSubProperties(config.getSerialization())); //初始化两级的缓存管理 - CacheProviderHolder.init(config, (region, key)->{ + this.holder = CacheProviderHolder.init(config, (region, key) -> { //当一级缓存中的对象失效时,自动清除二级缓存中的数据 - Level2Cache level2 = CacheProviderHolder.getLevel2Cache(region); + Level2Cache level2 = this.holder.getLevel2Cache(region); level2.evict(key); - if(!level2.supportTTL()) { + if (!level2.supportTTL()) { //再一次清除一级缓存是为了避免缓存失效时再次从 L2 获取到值 - CacheProviderHolder.getLevel1Cache(region).evict(key); + this.holder.getLevel1Cache(region).evict(key); } - log.debug(String.format("Level 1 cache object expired, evict level 2 cache object [%s,%s]", region, key)); - if(policy != null) + log.debug("Level 1 cache object expired, evict level 2 cache object [{},{}]", region, key); + if (policy != null) policy.sendEvictCmd(region, key); }); - policy = ClusterPolicyFactory.init(config.getBroadcast(), config.getBroadcastProperties()); - log.info("Using cluster policy : " + policy.getClass().getName()); + policy = ClusterPolicyFactory.init(holder, config.getBroadcast(), config.getBroadcastProperties()); + log.info("Using cluster policy : {}", policy.getClass().getName()); } + } diff --git a/core/src/net/oschina/j2cache/J2CacheCmd.java b/core/src/net/oschina/j2cache/J2CacheCmd.java index 447a40236841c468427d1bef667ac8b429490780..d6e3cbe0ea497dddbadfeb70a5356f417d329b41 100644 --- a/core/src/net/oschina/j2cache/J2CacheCmd.java +++ b/core/src/net/oschina/j2cache/J2CacheCmd.java @@ -40,7 +40,7 @@ public class J2CacheCmd { try { line = reader.readLine("> "); - if(line == null || line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) + if(line == null || "quit".equalsIgnoreCase(line) || "exit".equalsIgnoreCase(line)) break; String[] cmds = line.split(" "); diff --git a/core/src/net/oschina/j2cache/J2CacheConfig.java b/core/src/net/oschina/j2cache/J2CacheConfig.java index e2a1057111fdb6b20abec280675221ffdeb2f291..7286dc3b9e17fc54c93e472490fdbf31ab219291 100644 --- a/core/src/net/oschina/j2cache/J2CacheConfig.java +++ b/core/src/net/oschina/j2cache/J2CacheConfig.java @@ -15,20 +15,16 @@ */ package net.oschina.j2cache; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.*; import java.util.Properties; /** * J2Cache configurations + * * @author Winter Lau (javayou@gmail.com) */ public class J2CacheConfig { - private final static Logger log = LoggerFactory.getLogger(J2CacheConfig.class); - private Properties properties = new Properties(); private Properties broadcastProperties = new Properties(); private Properties l1CacheProperties = new Properties(); @@ -41,21 +37,55 @@ public class J2CacheConfig { private boolean syncTtlToRedis; private boolean defaultCacheNullObject; + /** + * Read configuration from resource + * + * @param configResource config resource + * @return config instance + * @throws IOException config read io exception + */ public final static J2CacheConfig initFromConfig(String configResource) throws IOException { - try (InputStream stream = getConfigStream(configResource)){ + try (InputStream stream = getConfigStream(configResource)) { return initFromConfig(stream); } } + /** + * Read configuration from file + * + * @param configFile config file + * @return config instance + * @throws IOException config read io exception + */ public final static J2CacheConfig initFromConfig(File configFile) throws IOException { try (FileInputStream stream = new FileInputStream(configFile)) { return initFromConfig(stream); } } + /** + * Read configuration from input stream + * + * @param stream config stream + * @return config instance + * @throws IOException config read io exception + */ public final static J2CacheConfig initFromConfig(InputStream stream) throws IOException { + Properties properties = new Properties(); + properties.load(stream); + return initFromConfig(properties); + } + + /** + * Read configuration from properties + * + * @param properties config properties + * @return config instance + */ + public final static J2CacheConfig initFromConfig(Properties properties) { J2CacheConfig config = new J2CacheConfig(); - config.properties.load(stream); + config.properties = properties; + config.serialization = trim(config.properties.getProperty("j2cache.serialization")); config.broadcast = trim(config.properties.getProperty("j2cache.broadcast")); config.l1CacheName = trim(config.properties.getProperty("j2cache.L1.provider_class")); @@ -64,8 +94,9 @@ public class J2CacheConfig { config.defaultCacheNullObject = "true".equalsIgnoreCase(trim(config.properties.getProperty("j2cache.default_cache_null_object"))); String l2_config_section = trim(config.properties.getProperty("j2cache.L2.config_section")); - if (l2_config_section == null || l2_config_section.trim().equals("")) + if (l2_config_section == null || "".equals(l2_config_section.trim())) { l2_config_section = config.l2CacheName; + } config.broadcastProperties = config.getSubProperties(config.broadcast); config.l1CacheProperties = config.getSubProperties(config.l1CacheName); @@ -75,41 +106,45 @@ public class J2CacheConfig { /** * read sub properties by prefix - * @param i_prefix prefix of config + * + * @param i_prefix prefix of config * @return properties without prefix */ public Properties getSubProperties(String i_prefix) { Properties props = new Properties(); final String prefix = i_prefix + '.'; - properties.forEach((k,v) -> { - String key = (String)k; - if(key.startsWith(prefix)) - props.setProperty(key.substring(prefix.length()), trim((String)v)); + properties.forEach((k, v) -> { + String key = (String) k; + if (key.startsWith(prefix)) { + props.setProperty(key.substring(prefix.length()), trim((String) v)); + } }); return props; } /** * get j2cache properties stream - * @return + * + * @return config stream */ private static InputStream getConfigStream(String resource) { - log.info("Load J2Cache Config File : [{}].", resource); InputStream configStream = J2Cache.class.getResourceAsStream(resource); - if(configStream == null) + if (configStream == null) { configStream = J2Cache.class.getClassLoader().getParent().getResourceAsStream(resource); - if(configStream == null) + } + if (configStream == null) { throw new CacheException("Cannot find " + resource + " !!!"); + } return configStream; } public void dump(PrintStream writer) { writer.printf("j2cache.serialization = %s%n", this.serialization); - writer.printf("[%s]%n",this.broadcast); + writer.printf("[%s]%n", this.broadcast); broadcastProperties.list(writer); - writer.printf("[%s]%n",this.l1CacheName); + writer.printf("[%s]%n", this.l1CacheName); l1CacheProperties.list(writer); - writer.printf("[%s]%n",this.l2CacheName); + writer.printf("[%s]%n", this.l2CacheName); l2CacheProperties.list(writer); } diff --git a/core/src/net/oschina/j2cache/caffeine/CaffeineProvider.java b/core/src/net/oschina/j2cache/caffeine/CaffeineProvider.java index ca5e2e1b775199a42076bc8ade8c0ea15072a591..f187de84868649eb260246c7706f88cb3b0260bf 100644 --- a/core/src/net/oschina/j2cache/caffeine/CaffeineProvider.java +++ b/core/src/net/oschina/j2cache/caffeine/CaffeineProvider.java @@ -18,6 +18,8 @@ package net.oschina.j2cache.caffeine; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.RemovalCause; import net.oschina.j2cache.*; +import net.oschina.j2cache.util.AntPathMatcher; +import net.oschina.j2cache.util.PatternMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.ArrayList; +import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -42,6 +45,7 @@ public class CaffeineProvider implements CacheProvider { private final static String DEFAULT_REGION = "default"; private ConcurrentHashMap caches = new ConcurrentHashMap<>(); private ConcurrentHashMap cacheConfigs = new ConcurrentHashMap<>(); + private PatternMatcher patternMatcher = new AntPathMatcher(); @Override public String name() { @@ -63,13 +67,12 @@ public class CaffeineProvider implements CacheProvider { @Override public Cache buildCache(String region, CacheExpiredListener listener) { return caches.computeIfAbsent(region, v -> { - CacheConfig config = cacheConfigs.get(region); + CacheConfig config = findCacheConfig(region); if (config == null) { + log.warn("Caffeine cache [{}] not defined, using default.", region); config = cacheConfigs.get(DEFAULT_REGION); if (config == null) throw new CacheException(String.format("Undefined [default] caffeine cache")); - - log.warn(String.format("Caffeine cache [%s] not defined, using default.", region)); } return newCaffeineCache(region, config.size, config.expire, listener); }); @@ -78,7 +81,7 @@ public class CaffeineProvider implements CacheProvider { @Override public Cache buildCache(String region, long timeToLiveInSeconds, CacheExpiredListener listener) { CaffeineCache cache = caches.computeIfAbsent(region, v -> { - CacheConfig config = cacheConfigs.get(region); + CacheConfig config = findCacheConfig(region); if(config != null && config.expire != timeToLiveInSeconds) throw new IllegalArgumentException(String.format("Region [%s] TTL %d not match with %d", region, config.expire, timeToLiveInSeconds)); @@ -88,7 +91,7 @@ public class CaffeineProvider implements CacheProvider { throw new CacheException(String.format("Undefined caffeine cache region name = %s", region)); } - log.info(String.format("Started caffeine region [%s] with TTL: %d", region, timeToLiveInSeconds)); + log.info("Started caffeine region [{}] with TTL: {}", region, timeToLiveInSeconds); return newCaffeineCache(region, config.size, timeToLiveInSeconds, listener); }); @@ -108,8 +111,8 @@ public class CaffeineProvider implements CacheProvider { * 返回对 Caffeine cache 的 封装 * @param region region name * @param size max cache object size in memory - * @param expire cache object expire time in millisecond - * if this parameter set to 0 or negative numbers + * @param expire cache object expire time in second + * if this parameter set to 0s or negative numbers * means never expire * @param listener j2cache cache listener * @return CaffeineCache @@ -118,8 +121,11 @@ public class CaffeineProvider implements CacheProvider { Caffeine caffeine = Caffeine.newBuilder(); caffeine = caffeine.maximumSize(size) .removalListener((k,v, cause) -> { - //程序删除的缓存不做通知处理,因为上层已经做了处理 - if(cause != RemovalCause.EXPLICIT && cause != RemovalCause.REPLACED) + /* + * 程序删除的缓存不做通知处理,因为上层已经做了处理 + * 当缓存数据不是因为手工删除和超出容量限制而被删除的情况,就需要通知上层侦听器 + */ + if(cause != RemovalCause.EXPLICIT && cause != RemovalCause.REPLACED && cause != RemovalCause.SIZE) listener.notifyElementExpired(region, (String)k); }); if (expire > 0) { @@ -149,24 +155,46 @@ public class CaffeineProvider implements CacheProvider { } //加载 Caffeine 独立配置文件 String propertiesFile = props.getProperty("properties"); - if(propertiesFile != null && propertiesFile.trim().length() > 0) { - try (InputStream stream = getClass().getResourceAsStream(propertiesFile)) { + if (propertiesFile != null && propertiesFile.trim().length() > 0) { + InputStream stream = null; + try { + stream = getClass().getResourceAsStream(propertiesFile); + if (stream == null) { + stream = getClass().getClassLoader().getResourceAsStream(propertiesFile); + } Properties regionsProps = new Properties(); regionsProps.load(stream); - for(String region : regionsProps.stringPropertyNames()) { + for (String region : regionsProps.stringPropertyNames()) { String s_config = regionsProps.getProperty(region).trim(); this.saveCacheConfig(region, s_config); } } catch (IOException e) { - log.error("Failed to load caffeine regions define " + propertiesFile, e); + log.error("Failed to load caffeine regions define {}", propertiesFile, e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private CacheConfig findCacheConfig(String region){ + for (Map.Entry entry : cacheConfigs.entrySet()) { + if(patternMatcher.matches(entry.getKey(),region)){ + return entry.getValue(); } } + return null; } private void saveCacheConfig(String region, String region_config) { CacheConfig cfg = CacheConfig.parse(region_config); if(cfg == null) - log.warn(String.format("Illegal caffeine cache config [%s=%s]", region, region_config)); + log.warn("Illegal caffeine cache config [{}={}]", region, region_config); else cacheConfigs.put(region, cfg); } diff --git a/core/src/net/oschina/j2cache/cluster/ClusterPolicy.java b/core/src/net/oschina/j2cache/cluster/ClusterPolicy.java index 687d1f2ff09a118b857d3cedcff31881fb53fc3a..c938165f04d69e593f64a055693b2722d1aa76e3 100644 --- a/core/src/net/oschina/j2cache/cluster/ClusterPolicy.java +++ b/core/src/net/oschina/j2cache/cluster/ClusterPolicy.java @@ -20,7 +20,6 @@ import net.oschina.j2cache.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.Properties; /** @@ -34,9 +33,9 @@ public interface ClusterPolicy { /** * 连接到集群 * @param props j2cache 配置信息 + * @param holder Cache Provider Instance */ - void connect(Properties props); - + void connect(Properties props, CacheProviderHolder holder); /** * 发送消息 @@ -71,17 +70,20 @@ public interface ClusterPolicy { * @param region 区域名称 * @param keys 缓存键值 */ - default void evict(String region, String... keys) { - CacheProviderHolder.getLevel1Cache(region).evict(keys); - } + void evict(String region, String... keys); /** * 清除本地整个缓存区域 * @param region 区域名称 */ - default void clear(String region) { - CacheProviderHolder.getLevel1Cache(region).clear(); - } + void clear(String region) ; + + /** + * 判断是否本地实例的命令 + * @param cmd 命令信息 + * @return true if the cmd sent by self + */ + boolean isLocalCommand(Command cmd) ; /** * 处理缓存事件逻辑 @@ -89,12 +91,12 @@ public interface ClusterPolicy { */ default void handleCommand(Command cmd) { try { - if (cmd == null || cmd.isLocal()) + if (cmd == null || isLocalCommand(cmd)) return; switch (cmd.getOperator()) { case Command.OPT_JOIN: - log.info("Node-"+cmd.getSrc() + " joined !"); + log.info("Node-{} joined !", cmd.getSrc()); break; case Command.OPT_EVICT_KEY: this.evict(cmd.getRegion(), cmd.getKeys()); @@ -105,7 +107,7 @@ public interface ClusterPolicy { log.debug("Received cache clear message, region=" + cmd.getRegion()); break; case Command.OPT_QUIT: - log.info("Node-"+cmd.getSrc() + " quit !"); + log.info("Node-{} quit !", cmd.getSrc()); break; default: log.warn("Unknown message type = " + cmd.getOperator()); diff --git a/core/src/net/oschina/j2cache/cluster/ClusterPolicyFactory.java b/core/src/net/oschina/j2cache/cluster/ClusterPolicyFactory.java index 40e75382e31870f73bb9bf641027d2009190ea7f..3f26c8a76c34f59ea742083c19fe2093475a5819 100644 --- a/core/src/net/oschina/j2cache/cluster/ClusterPolicyFactory.java +++ b/core/src/net/oschina/j2cache/cluster/ClusterPolicyFactory.java @@ -16,6 +16,7 @@ package net.oschina.j2cache.cluster; import net.oschina.j2cache.CacheException; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.lettuce.LettuceCacheProvider; import net.oschina.j2cache.redis.RedisPubSubClusterPolicy; @@ -31,26 +32,29 @@ public class ClusterPolicyFactory { /** * 初始化集群消息通知机制 + * @param holder CacheProviderHolder instance * @param broadcast j2cache.broadcast value * @param props broadcast configuations * @return ClusterPolicy instance */ - public final static ClusterPolicy init(String broadcast, Properties props) { + public final static ClusterPolicy init(CacheProviderHolder holder, String broadcast, Properties props) { + ClusterPolicy policy; if ("redis".equalsIgnoreCase(broadcast)) - policy = ClusterPolicyFactory.redis(props); + policy = ClusterPolicyFactory.redis(props, holder); else if ("jgroups".equalsIgnoreCase(broadcast)) - policy = ClusterPolicyFactory.jgroups(props); + policy = ClusterPolicyFactory.jgroups(props, holder); else if ("rabbitmq".equalsIgnoreCase(broadcast)) - policy = ClusterPolicyFactory.rabbitmq(props); + policy = ClusterPolicyFactory.rabbitmq(props, holder); else if ("rocketmq".equalsIgnoreCase(broadcast)) - policy = ClusterPolicyFactory.rocketmq(props); + policy = ClusterPolicyFactory.rocketmq(props, holder); else if ("lettuce".equalsIgnoreCase(broadcast)) - policy = ClusterPolicyFactory.lettuce(props); + policy = ClusterPolicyFactory.lettuce(props, holder); else if ("none".equalsIgnoreCase(broadcast)) policy = new NoneClusterPolicy(); else - policy = ClusterPolicyFactory.custom(broadcast, props); + policy = ClusterPolicyFactory.custom(broadcast, props, holder); + return policy; } @@ -59,10 +63,10 @@ public class ClusterPolicyFactory { * @param props 框架配置 * @return 返回 Redis 集群策略的实例 */ - private final static ClusterPolicy redis(Properties props) { + private final static ClusterPolicy redis(Properties props, CacheProviderHolder holder) { String name = props.getProperty("channel"); RedisPubSubClusterPolicy policy = new RedisPubSubClusterPolicy(name, props); - policy.connect(props); + policy.connect(props, holder); return policy; } @@ -71,10 +75,10 @@ public class ClusterPolicyFactory { * @param props 框架配置 * @return 返回 JGroups 集群策略的实例 */ - private final static ClusterPolicy jgroups(Properties props) { + private final static ClusterPolicy jgroups(Properties props, CacheProviderHolder holder) { String name = props.getProperty("channel.name"); JGroupsClusterPolicy policy = new JGroupsClusterPolicy(name, props); - policy.connect(props); + policy.connect(props, holder); return policy; } @@ -83,21 +87,21 @@ public class ClusterPolicyFactory { * @param props 框架配置 * @return 返回 RabbitMQ 集群策略的实例 */ - private final static ClusterPolicy rabbitmq(Properties props) { + private final static ClusterPolicy rabbitmq(Properties props, CacheProviderHolder holder) { RabbitMQClusterPolicy policy = new RabbitMQClusterPolicy(props); - policy.connect(props); + policy.connect(props, holder); return policy; } - private final static ClusterPolicy rocketmq(Properties props) { + private final static ClusterPolicy rocketmq(Properties props, CacheProviderHolder holder) { RocketMQClusterPolicy policy = new RocketMQClusterPolicy(props); - policy.connect(props); + policy.connect(props, holder); return policy; } - private final static ClusterPolicy lettuce(Properties props) { + private final static ClusterPolicy lettuce(Properties props, CacheProviderHolder holder) { LettuceCacheProvider policy = new LettuceCacheProvider(); - policy.connect(props); + policy.connect(props, holder); return policy; } @@ -107,10 +111,10 @@ public class ClusterPolicyFactory { * @param props * @return */ - private final static ClusterPolicy custom(String classname, Properties props) { + private final static ClusterPolicy custom(String classname, Properties props, CacheProviderHolder holder) { try { ClusterPolicy policy = (ClusterPolicy)Class.forName(classname).newInstance(); - policy.connect(props); + policy.connect(props, holder); return policy; } catch (Exception e) { throw new CacheException("Failed in load custom cluster policy. class = " + classname, e); diff --git a/core/src/net/oschina/j2cache/cluster/JGroupsClusterPolicy.java b/core/src/net/oschina/j2cache/cluster/JGroupsClusterPolicy.java index 5b145917c683fb16ecfad5285df2bbdfe42cb5e2..b310adf1dc5071cfcc615c6fe8bb79ece4d41da5 100644 --- a/core/src/net/oschina/j2cache/cluster/JGroupsClusterPolicy.java +++ b/core/src/net/oschina/j2cache/cluster/JGroupsClusterPolicy.java @@ -16,6 +16,7 @@ package net.oschina.j2cache.cluster; import net.oschina.j2cache.CacheException; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import org.jgroups.*; import org.slf4j.Logger; @@ -32,9 +33,12 @@ public class JGroupsClusterPolicy extends ReceiverAdapter implements ClusterPoli private final static Logger log = LoggerFactory.getLogger(JGroupsClusterPolicy.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + private String configXml; private JChannel channel; private String name; + private CacheProviderHolder holder; static { System.setProperty("java.net.preferIPv4Stack", "true"); //Disable IPv6 in JVM @@ -47,7 +51,7 @@ public class JGroupsClusterPolicy extends ReceiverAdapter implements ClusterPoli */ public JGroupsClusterPolicy(String name, Properties props) { this.name = name; - if(this.name == null || this.name.trim().equalsIgnoreCase("")) + if(this.name == null || "".equalsIgnoreCase(this.name.trim())) this.name = "j2cache"; this.configXml = props.getProperty("configXml"); if(configXml == null || configXml.trim().length() == 0) @@ -55,7 +59,30 @@ public class JGroupsClusterPolicy extends ReceiverAdapter implements ClusterPoli } @Override - public void connect(Properties props) { + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } + + @Override + public void connect(Properties props, CacheProviderHolder holder) { + this.holder = holder; try{ long ct = System.currentTimeMillis(); @@ -67,7 +94,7 @@ public class JGroupsClusterPolicy extends ReceiverAdapter implements ClusterPoli channel.connect(name); this.publish(Command.join()); - log.info("Connected to jgroups channel:" + name + ", time " + (System.currentTimeMillis()-ct) + " ms."); + log.info("Connected to jgroups channel:{}, time {}ms.", name, (System.currentTimeMillis()-ct)); } catch (Exception e){ throw new CacheException(e); @@ -90,18 +117,19 @@ public class JGroupsClusterPolicy extends ReceiverAdapter implements ClusterPoli @Override public void viewAccepted(View view) { - log.info(String.format("Group Members Changed, LIST: %s", - String.join(",", view.getMembers().stream().map(a -> a.toString()).toArray(String[]::new))) + log.info("Group Members Changed, LIST: {}", + String.join(",", view.getMembers().stream().map(a -> a.toString()).toArray(String[]::new)) ); } @Override public void publish(Command cmd) { try { + cmd.setSrc(LOCAL_COMMAND_ID); Message msg = new Message(null, cmd.json()); channel.send(msg); } catch (Exception e) { - log.error("Failed to send message to jgroups -> " + cmd, e); + log.error("Failed to send message to jgroups -> {}", cmd, e); } } } diff --git a/core/src/net/oschina/j2cache/cluster/NoneClusterPolicy.java b/core/src/net/oschina/j2cache/cluster/NoneClusterPolicy.java index ff3eb35b0748957fb8503697594f17093eaf644d..a0e40ac9bc0918a78086ca5b3d5eea075e1750c1 100644 --- a/core/src/net/oschina/j2cache/cluster/NoneClusterPolicy.java +++ b/core/src/net/oschina/j2cache/cluster/NoneClusterPolicy.java @@ -15,6 +15,7 @@ */ package net.oschina.j2cache.cluster; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import java.util.Properties; @@ -25,18 +26,30 @@ import java.util.Properties; */ public class NoneClusterPolicy implements ClusterPolicy { + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + @Override - public void connect(Properties props) { + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + @Override + public void connect(Properties props, CacheProviderHolder holder) { } @Override public void disconnect() { - } @Override public void publish(Command cmd) { + } + @Override + public void evict(String region, String... keys) { + } + + @Override + public void clear(String region) { } } diff --git a/core/src/net/oschina/j2cache/cluster/RabbitMQClusterPolicy.java b/core/src/net/oschina/j2cache/cluster/RabbitMQClusterPolicy.java index 5c072dca5e8ec2957653380d1468a9be7e6ba5d6..f6917ea851f208b0b527ea4af9c16490d2686213 100644 --- a/core/src/net/oschina/j2cache/cluster/RabbitMQClusterPolicy.java +++ b/core/src/net/oschina/j2cache/cluster/RabbitMQClusterPolicy.java @@ -17,6 +17,7 @@ package net.oschina.j2cache.cluster; import com.rabbitmq.client.*; import net.oschina.j2cache.CacheException; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,8 +33,12 @@ public class RabbitMQClusterPolicy implements ClusterPolicy, Consumer { private static final Logger log = LoggerFactory.getLogger(RabbitMQClusterPolicy.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + private static final String EXCHANGE_TYPE = "fanout"; + private CacheProviderHolder holder; + private ConnectionFactory factory; private Connection conn_publisher; private Connection conn_consumer; @@ -55,7 +60,30 @@ public class RabbitMQClusterPolicy implements ClusterPolicy, Consumer { } @Override - public void connect(Properties props) { + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } + + @Override + public void connect(Properties props, CacheProviderHolder holder) { + this.holder = holder; try { long ct = System.currentTimeMillis(); conn_publisher = factory.newConnection(); @@ -71,7 +99,7 @@ public class RabbitMQClusterPolicy implements ClusterPolicy, Consumer { channel_consumer.basicConsume(queueName, true, this); - log.info("Connected to RabbitMQ:" + conn_consumer + ", time " + (System.currentTimeMillis()-ct) + " ms."); + log.info("Connected to RabbitMQ:{}, time {}ms", conn_consumer, System.currentTimeMillis()-ct); } catch (Exception e) { throw new CacheException(String.format("Failed to connect to RabbitMQ (%s:%d)", factory.getHost(), factory.getPort()), e); } @@ -97,6 +125,7 @@ public class RabbitMQClusterPolicy implements ClusterPolicy, Consumer { } } try { + cmd.setSrc(LOCAL_COMMAND_ID); channel_publisher.basicPublish(exchange, "", null, cmd.json().getBytes()); } catch (IOException e ) { throw new CacheException("Failed to publish cmd to RabbitMQ!", e); diff --git a/core/src/net/oschina/j2cache/cluster/RocketMQClusterPolicy.java b/core/src/net/oschina/j2cache/cluster/RocketMQClusterPolicy.java index dbea1d7babfc433a9536bf2b18171b218062501b..ab696b2bef8170652692fc20ff936f5ee86416df 100644 --- a/core/src/net/oschina/j2cache/cluster/RocketMQClusterPolicy.java +++ b/core/src/net/oschina/j2cache/cluster/RocketMQClusterPolicy.java @@ -15,6 +15,7 @@ */ package net.oschina.j2cache.cluster; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; @@ -40,6 +41,9 @@ public class RocketMQClusterPolicy implements ClusterPolicy, MessageListenerConc private static final Logger log = LoggerFactory.getLogger(RocketMQClusterPolicy.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + + private CacheProviderHolder holder; private String hosts; private String topic; private DefaultMQProducer producer; @@ -60,7 +64,30 @@ public class RocketMQClusterPolicy implements ClusterPolicy, MessageListenerConc } @Override - public void connect(Properties props) { + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } + + @Override + public void connect(Properties props, CacheProviderHolder holder) { + this.holder = holder; try { this.producer.start(); publish(Command.join()); @@ -75,11 +102,12 @@ public class RocketMQClusterPolicy implements ClusterPolicy, MessageListenerConc @Override public void publish(Command cmd) { + cmd.setSrc(LOCAL_COMMAND_ID); Message msg = new Message(topic,"","", cmd.json().getBytes()); try { this.producer.send(msg); } catch (Exception e) { - log.error(String.format("Failed to publish %s to RocketMQ", cmd.json()), e); + log.error("Failed to publish {} to RocketMQ", cmd.json(), e); } } diff --git a/core/src/net/oschina/j2cache/ehcache/EhCacheProvider.java b/core/src/net/oschina/j2cache/ehcache/EhCacheProvider.java index 25f4b9a54637a103b5b7ca4405a08cef11e975ef..1b8ceb91921cf91b92324fcaf8c776d9d4a0b0a6 100644 --- a/core/src/net/oschina/j2cache/ehcache/EhCacheProvider.java +++ b/core/src/net/oschina/j2cache/ehcache/EhCacheProvider.java @@ -39,30 +39,30 @@ import net.sf.ehcache.CacheManager; */ public class EhCacheProvider implements CacheProvider { - private final static Logger log = LoggerFactory.getLogger(EhCacheProvider.class); + private final static Logger log = LoggerFactory.getLogger(EhCacheProvider.class); - public final static String KEY_EHCACHE_NAME = "name"; - public final static String KEY_EHCACHE_CONFIG_XML = "configXml"; + public final static String KEY_EHCACHE_NAME = "name"; + public final static String KEY_EHCACHE_CONFIG_XML = "configXml"; - private CacheManager manager; - private ConcurrentHashMap caches; + private CacheManager manager; + private ConcurrentHashMap caches; - @Override - public String name() { - return "ehcache"; - } + @Override + public String name() { + return "ehcache"; + } - @Override - public int level() { - return CacheObject.LEVEL_1; - } + @Override + public int level() { + return CacheObject.LEVEL_1; + } - @Override - public Collection regions() { - Collection regions = new ArrayList<>(); - caches.forEach((k,c) -> regions.add(new CacheChannel.Region(k, c.size(), c.ttl()))); - return regions; - } + @Override + public Collection regions() { + Collection regions = new ArrayList<>(); + caches.forEach((k,c) -> regions.add(new CacheChannel.Region(k, c.size(), c.ttl()))); + return regions; + } /** * Builds a Cache. @@ -73,86 +73,87 @@ public class EhCacheProvider implements CacheProvider { */ @Override public EhCache buildCache(String regionName, CacheExpiredListener listener) { - return caches.computeIfAbsent(regionName, v -> { - net.sf.ehcache.Cache cache = manager.getCache(regionName); - if (cache == null) { - log.warn("Could not find configuration [" + regionName + "]; using defaults."); - manager.addCache(regionName); - cache = manager.getCache(regionName); - log.info("started Ehcache region: " + regionName); - } - return new EhCache(cache, listener); - }); + return caches.computeIfAbsent(regionName, v -> { + net.sf.ehcache.Cache cache = manager.getCache(regionName); + if (cache == null) { + manager.addCache(regionName); + cache = manager.getCache(regionName); + log.warn("Could not find configuration [{}]; using defaults (TTL:{} seconds).", regionName, cache.getCacheConfiguration().getTimeToLiveSeconds()); + } + return new EhCache(cache, listener); + }); + } + + @Override + public EhCache buildCache(String region, long timeToLiveInSeconds, CacheExpiredListener listener) { + EhCache ehcache = caches.computeIfAbsent(region, v -> { + //配置缓存 + CacheConfiguration cfg = manager.getConfiguration().getDefaultCacheConfiguration().clone(); + cfg.setName(region); + if(timeToLiveInSeconds > 0) { + cfg.setTimeToLiveSeconds(timeToLiveInSeconds); + cfg.setTimeToIdleSeconds(timeToLiveInSeconds); + } + + net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(cfg); + manager.addCache(cache); + + log.info("Started Ehcache region [{}] with TTL: {}", region, timeToLiveInSeconds); + + return new EhCache(cache, listener); + }); + + if (ehcache.ttl() != timeToLiveInSeconds) + throw new IllegalArgumentException(String.format("Region [%s] TTL %d not match with %d", region, ehcache.ttl(), timeToLiveInSeconds)); + + return ehcache; + } + + @Override + public void removeCache(String region) { + caches.remove(region); + manager.removeCache(region); } - @Override - public EhCache buildCache(String region, long timeToLiveInSeconds, CacheExpiredListener listener) { - EhCache ehcache = caches.computeIfAbsent(region, v -> { - //配置缓存 - CacheConfiguration cfg = manager.getConfiguration().getDefaultCacheConfiguration().clone(); - cfg.setName(region); - if(timeToLiveInSeconds > 0) { - cfg.setTimeToLiveSeconds(timeToLiveInSeconds); - cfg.setTimeToIdleSeconds(timeToLiveInSeconds); - } - - net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache(cfg); - manager.addCache(cache); - - log.info(String.format("Started Ehcache region [%s] with TTL: %d", region, timeToLiveInSeconds)); - - return new EhCache(cache, listener); - }); - - if (ehcache.ttl() != timeToLiveInSeconds) - throw new IllegalArgumentException(String.format("Region [%s] TTL %d not match with %d", region, ehcache.ttl(), timeToLiveInSeconds)); - - return ehcache; - } - - @Override - public void removeCache(String region) { - caches.remove(region); - manager.removeCache(region); - } - - /** - * init ehcache config - * - * @param props current configuration settings. - */ - public void start(Properties props) { - if (manager != null) { + /** + * init ehcache config + * + * @param props current configuration settings. + */ + public void start(Properties props) { + if (manager != null) { log.warn("Attempt to restart an already started EhCacheProvider."); return; } - - // 如果指定了名称,那么尝试获取已有实例 - String ehcacheName = (String)props.get(KEY_EHCACHE_NAME); - if (ehcacheName != null && ehcacheName.trim().length() > 0) - manager = CacheManager.getCacheManager(ehcacheName); - if (manager == null) { - // 指定了配置文件路径? 加载之 - if (props.containsKey(KEY_EHCACHE_CONFIG_XML)) { - URL url = getClass().getResource(props.getProperty(KEY_EHCACHE_CONFIG_XML)); - manager = CacheManager.newInstance(url); - } else { - // 加载默认实例 - manager = CacheManager.getInstance(); - } - } + + // 如果指定了名称,那么尝试获取已有实例 + String ehcacheName = (String)props.get(KEY_EHCACHE_NAME); + if (ehcacheName != null && ehcacheName.trim().length() > 0) + manager = CacheManager.getCacheManager(ehcacheName); + if (manager == null) { + // 指定了配置文件路径? 加载之 + if (props.containsKey(KEY_EHCACHE_CONFIG_XML)) { + String propertiesFile = props.getProperty(KEY_EHCACHE_CONFIG_XML); + URL url = getClass().getResource(propertiesFile); + url = (url == null) ? getClass().getClassLoader().getResource(propertiesFile) : url; + manager = CacheManager.newInstance(url); + } else { + // 加载默认实例 + manager = CacheManager.getInstance(); + } + } caches = new ConcurrentHashMap<>(); - } + } - /** - * Callback to perform any necessary cleanup of the underlying cache implementation. - */ - public void stop() { - if (manager != null) { + /** + * Callback to perform any necessary cleanup of the underlying cache implementation. + */ + public void stop() { + if (manager != null) { manager.shutdown(); caches.clear(); manager = null; } - } + } } diff --git a/core/src/net/oschina/j2cache/ehcache/EhCacheProvider3.java b/core/src/net/oschina/j2cache/ehcache/EhCacheProvider3.java index 9c235a4f09854de9d8b872d2478803438782a9ff..22490fabdd01a80df078b7242697c4636ed0a74f 100644 --- a/core/src/net/oschina/j2cache/ehcache/EhCacheProvider3.java +++ b/core/src/net/oschina/j2cache/ehcache/EhCacheProvider3.java @@ -78,7 +78,9 @@ public class EhCacheProvider3 implements CacheProvider { CacheConfiguration defaultCacheConfig = manager.getRuntimeConfiguration().getCacheConfigurations().get(DEFAULT_TPL); CacheConfiguration cacheCfg = CacheConfigurationBuilder.newCacheConfigurationBuilder(defaultCacheConfig).build(); cache = manager.createCache(region, cacheCfg); - log.info("Could not find configuration [" + region + "]; using defaults."); + Duration dura = cache.getRuntimeConfiguration().getExpiry().getExpiryForCreation(null, null); + long ttl = dura.isInfinite()?-1:dura.getTimeUnit().toSeconds(dura.getLength()); + log.warn("Could not find configuration [{}]; using defaults (TTL:{} seconds).", region, ttl); } return new EhCache3(region, cache, listener); }); @@ -92,7 +94,7 @@ public class EhCacheProvider3 implements CacheProvider { .withExpiry(Expirations.timeToLiveExpiration(Duration.of(timeToLiveInSeconds, TimeUnit.SECONDS))) .build(); org.ehcache.Cache cache = manager.createCache(region, conf); - log.info(String.format("Started Ehcache region [%s] with TTL: %d", region, timeToLiveInSeconds)); + log.info("Started Ehcache region [{}] with TTL: {}", region, timeToLiveInSeconds); return new EhCache3(region, cache, listener); }); @@ -114,13 +116,16 @@ public class EhCacheProvider3 implements CacheProvider { try { this.defaultHeapSize = Long.parseLong(sDefaultHeapSize); }catch(Exception e) { - log.warn(String.format("Failed to read ehcache3.defaultHeapSize = %s , use default %d", sDefaultHeapSize, defaultHeapSize)); + log.warn("Failed to read ehcache3.defaultHeapSize = {} , use default {}", sDefaultHeapSize, defaultHeapSize); } String configXml = props.getProperty("configXml"); if(configXml == null || configXml.trim().length() == 0) configXml = "/ehcache3.xml"; - URL myUrl = getClass().getResource(configXml); - Configuration xmlConfig = new XmlConfiguration(myUrl); + + URL url = getClass().getResource(configXml); + url = (url == null) ? getClass().getClassLoader().getResource(configXml) : url; + + Configuration xmlConfig = new XmlConfiguration(url); manager = CacheManagerBuilder.newCacheManager(xmlConfig); manager.init(); } diff --git a/core/src/net/oschina/j2cache/lettuce/LettuceByteCodec.java b/core/src/net/oschina/j2cache/lettuce/LettuceByteCodec.java index d0d1f91b8bf6595decae75e926f147ae532b2e17..2547dc12ed5b8f76337b38a3f1c4e3fdd4610186 100644 --- a/core/src/net/oschina/j2cache/lettuce/LettuceByteCodec.java +++ b/core/src/net/oschina/j2cache/lettuce/LettuceByteCodec.java @@ -25,16 +25,16 @@ import java.nio.ByteBuffer; */ public class LettuceByteCodec implements RedisCodec { + private static final byte[] EMPTY = new byte[0]; + @Override public String decodeKey(ByteBuffer byteBuffer) { - return new String(byteBuffer.array()); + return new String(getBytes(byteBuffer)); } @Override public byte[] decodeValue(ByteBuffer byteBuffer) { - byte[] result = new byte[byteBuffer.remaining()]; - byteBuffer.get(result); - return result; + return getBytes(byteBuffer); } @Override @@ -46,4 +46,17 @@ public class LettuceByteCodec implements RedisCodec { public ByteBuffer encodeValue(byte[] bytes) { return ByteBuffer.wrap(bytes); } + + + private static byte[] getBytes(ByteBuffer buffer) { + int remaining = buffer.remaining(); + + if (remaining == 0) { + return EMPTY; + } + + byte[] b = new byte[remaining]; + buffer.get(b); + return b; + } } diff --git a/core/src/net/oschina/j2cache/lettuce/LettuceCache.java b/core/src/net/oschina/j2cache/lettuce/LettuceCache.java new file mode 100644 index 0000000000000000000000000000000000000000..6d15eebdc4eaf128297a56b319513d5784fc8592 --- /dev/null +++ b/core/src/net/oschina/j2cache/lettuce/LettuceCache.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2015-2017, Winter Lau (javayou@gmail.com). + *

+ * 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 net.oschina.j2cache.lettuce; + +import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.api.StatefulRedisConnection; +import io.lettuce.core.api.sync.BaseRedisCommands; +import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; +import net.oschina.j2cache.CacheException; +import net.oschina.j2cache.Level2Cache; +import org.apache.commons.pool2.impl.GenericObjectPool; + +/** + * Lettuce 的基类,封装了普通 Redis 连接和集群 Redis 连接的差异 + * + * @author Winter Lau(javayou@gmail.com) + */ +public abstract class LettuceCache implements Level2Cache { + + protected String namespace; + protected String region; + protected GenericObjectPool> pool; + protected int scanCount; + + protected StatefulConnection connect() { + try { + return pool.borrowObject(); + } catch (Exception e) { + throw new CacheException(e); + } + } + + protected BaseRedisCommands sync(StatefulConnection conn) { + if(conn instanceof StatefulRedisClusterConnection) + return ((StatefulRedisClusterConnection)conn).sync(); + else if(conn instanceof StatefulRedisConnection) + return ((StatefulRedisConnection)conn).sync(); + return null; + } + +} diff --git a/core/src/net/oschina/j2cache/lettuce/LettuceCacheProvider.java b/core/src/net/oschina/j2cache/lettuce/LettuceCacheProvider.java index d1f18416ae7fb57f3d997868a891e2738aa7d484..38a50087967d3d0b3521e5c984073d5b0bddaf4f 100644 --- a/core/src/net/oschina/j2cache/lettuce/LettuceCacheProvider.java +++ b/core/src/net/oschina/j2cache/lettuce/LettuceCacheProvider.java @@ -15,17 +15,25 @@ */ package net.oschina.j2cache.lettuce; +import io.lettuce.core.AbstractRedisClient; import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisURI; +import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.cluster.ClusterClientOptions; +import io.lettuce.core.cluster.ClusterTopologyRefreshOptions; +import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.pubsub.RedisPubSubAdapter; import io.lettuce.core.pubsub.StatefulRedisPubSubConnection; import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands; import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands; +import io.lettuce.core.support.ConnectionPoolSupport; import net.oschina.j2cache.*; import net.oschina.j2cache.cluster.ClusterPolicy; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; -import java.util.Collection; -import java.util.Collections; -import java.util.Properties; +import java.time.Duration; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** @@ -45,14 +53,22 @@ import java.util.concurrent.ConcurrentHashMap; */ public class LettuceCacheProvider extends RedisPubSubAdapter implements CacheProvider, ClusterPolicy { - private static RedisClient redisClient; - private StatefulRedisPubSubConnection pubsub; + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + + private static final LettuceByteCodec codec = new LettuceByteCodec(); + + private static AbstractRedisClient redisClient; + GenericObjectPool> pool; + private StatefulRedisPubSubConnection pubsub_subscriber; private String storage; + private CacheProviderHolder holder; + private String channel; private String namespace; + private int scanCount; - private static final ConcurrentHashMap regions = new ConcurrentHashMap(); + private final ConcurrentHashMap regions = new ConcurrentHashMap(); @Override public String name() { @@ -65,24 +81,15 @@ public class LettuceCacheProvider extends RedisPubSubAdapter imp } @Override - public Cache buildCache(String region, CacheExpiredListener listener) { - return regions.computeIfAbsent(region, v -> "hash".equalsIgnoreCase("hash")?new LettuceHashCache(this.namespace, region, redisClient):new LettuceGenericCache(this.namespace, region, redisClient)); - } - - @Override - public Cache buildCache(String region, long timeToLiveInSeconds, CacheExpiredListener listener) { - return buildCache(region, listener); - } - - @Override - public Collection regions() { - return Collections.emptyList(); + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; } @Override public void start(Properties props) { this.namespace = props.getProperty("namespace"); - this.storage = props.getProperty("storage", "generic"); + this.scanCount = Integer.valueOf(props.getProperty("scanCount", "1000")); + this.storage = props.getProperty("storage", "hash"); this.channel = props.getProperty("channel", "j2cache"); String scheme = props.getProperty("scheme", "redis"); @@ -90,31 +97,129 @@ public class LettuceCacheProvider extends RedisPubSubAdapter imp String password = props.getProperty("password"); int database = Integer.parseInt(props.getProperty("database", "0")); String sentinelMasterId = props.getProperty("sentinelMasterId"); + long clusterTopologyRefreshMs = Long.valueOf(props.getProperty("clusterTopologyRefresh", "3000")); + + if("redis-cluster".equalsIgnoreCase(scheme)) { + scheme = "redis"; + List redisURIs = new ArrayList<>(); + String[] hostArray = hosts.split(","); + for(String host : hostArray) { + String[] redisArray = host.split(":"); + RedisURI uri = RedisURI.create(redisArray[0], Integer.valueOf(redisArray[1])); + uri.setDatabase(database); + uri.setPassword(password); + uri.setSentinelMasterId(sentinelMasterId); + redisURIs.add(uri); + } + redisClient = RedisClusterClient.create(redisURIs); + ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder() + //开启自适应刷新 + .enableAdaptiveRefreshTrigger(ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT, ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS) + .enableAllAdaptiveRefreshTriggers() + .adaptiveRefreshTriggersTimeout(Duration.ofMillis(clusterTopologyRefreshMs)) + //开启定时刷新,时间间隔根据实际情况修改 + .enablePeriodicRefresh(Duration.ofMillis(clusterTopologyRefreshMs)) + .build(); + ((RedisClusterClient)redisClient).setOptions(ClusterClientOptions.builder().topologyRefreshOptions(topologyRefreshOptions).build()); + } + else { + String[] redisArray = hosts.split(":"); + RedisURI uri = RedisURI.create(redisArray[0], Integer.valueOf(redisArray[1])); + uri.setDatabase(database); + uri.setPassword(password); + redisClient = RedisClient.create(uri); + } + + try { + int timeout = Integer.parseInt(props.getProperty("timeout", "10000")); + redisClient.setDefaultTimeout(Duration.ofMillis(timeout)); + }catch(Exception e){ + log.warn("Failed to set default timeout, using default 10000 milliseconds.", e); + } - String redis_url = String.format("%s://%s@%s/%d#%s", scheme, password, hosts, database, sentinelMasterId); - - redisClient = RedisClient.create(redis_url); + //connection pool configurations + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + poolConfig.setMaxTotal(Integer.parseInt(props.getProperty("maxTotal", "100"))); + poolConfig.setMaxIdle(Integer.parseInt(props.getProperty("maxIdle", "10"))); + poolConfig.setMinIdle(Integer.parseInt(props.getProperty("minIdle", "10"))); + + pool = ConnectionPoolSupport.createGenericObjectPool(() -> { + if(redisClient instanceof RedisClient) + return ((RedisClient)redisClient).connect(codec); + else if(redisClient instanceof RedisClusterClient) + return ((RedisClusterClient)redisClient).connect(codec); + return null; + }, poolConfig); } @Override public void stop() { + pool.close(); regions.clear(); redisClient.shutdown(); } @Override - public void connect(Properties props) { - long ct = System.currentTimeMillis(); + public Cache buildCache(String region, CacheExpiredListener listener) { + return regions.computeIfAbsent(this.namespace + ":" + region, v -> "hash".equalsIgnoreCase(this.storage)? + new LettuceHashCache(this.namespace, region, pool): + new LettuceGenericCache(this.namespace, region, pool, scanCount)); + } + + @Override + public Cache buildCache(String region, long timeToLiveInSeconds, CacheExpiredListener listener) { + return buildCache(region, listener); + } + + @Override + public Collection regions() { + return Collections.emptyList(); + } + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + @Override + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + @Override + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } + + /** + * Get PubSub connection + * @return connection instance + */ + private StatefulRedisPubSubConnection pubsub() { + if(redisClient instanceof RedisClient) + return ((RedisClient)redisClient).connectPubSub(); + else if(redisClient instanceof RedisClusterClient) + return ((RedisClusterClient)redisClient).connectPubSub(); + return null; + } + + @Override + public void connect(Properties props, CacheProviderHolder holder) { + long ct = System.currentTimeMillis(); + this.holder = holder; this.channel = props.getProperty("channel", "j2cache"); this.publish(Command.join()); - this.pubsub = redisClient.connectPubSub(); - this.pubsub.addListener(this); - RedisPubSubAsyncCommands async = this.pubsub.async(); + this.pubsub_subscriber = this.pubsub(); + this.pubsub_subscriber.addListener(this); + RedisPubSubAsyncCommands async = this.pubsub_subscriber.async(); async.subscribe(this.channel); - log.info("Connected to redis channel:" + this.channel + ", time " + (System.currentTimeMillis()-ct) + " ms."); + log.info("Connected to redis channel:{}, time {}ms.", this.channel, System.currentTimeMillis()-ct); } @Override @@ -125,7 +230,8 @@ public class LettuceCacheProvider extends RedisPubSubAdapter imp @Override public void publish(Command cmd) { - try (StatefulRedisPubSubConnection connection = redisClient.connectPubSub()){ + cmd.setSrc(LOCAL_COMMAND_ID); + try (StatefulRedisPubSubConnection connection = this.pubsub()){ RedisPubSubCommands sync = connection.sync(); sync.publish(this.channel, cmd.json()); } @@ -137,7 +243,7 @@ public class LettuceCacheProvider extends RedisPubSubAdapter imp this.publish(Command.quit()); super.unsubscribed(this.channel, 1); } finally { - this.pubsub.close(); + this.pubsub_subscriber.close(); } } } diff --git a/core/src/net/oschina/j2cache/lettuce/LettuceGenericCache.java b/core/src/net/oschina/j2cache/lettuce/LettuceGenericCache.java index 9da19d1f3a78581544d8c8176e6670383b9d17b4..feb58941e406c2acd08fe61792bbe7048251f815 100644 --- a/core/src/net/oschina/j2cache/lettuce/LettuceGenericCache.java +++ b/core/src/net/oschina/j2cache/lettuce/LettuceGenericCache.java @@ -15,36 +15,36 @@ */ package net.oschina.j2cache.lettuce; -import io.lettuce.core.RedisClient; -import io.lettuce.core.api.StatefulRedisConnection; -import io.lettuce.core.api.sync.RedisCommands; -import net.oschina.j2cache.Level2Cache; - +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.apache.commons.pool2.impl.GenericObjectPool; + +import io.lettuce.core.KeyScanCursor; +import io.lettuce.core.ScanArgs; +import io.lettuce.core.ScanCursor; +import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.api.sync.RedisKeyCommands; +import io.lettuce.core.api.sync.RedisStringCommands; + /** * Redis 缓存操作封装,基于 region+_key 实现多个 Region 的缓存( * @author Winter Lau(javayou@gmail.com) */ -public class LettuceGenericCache implements Level2Cache { +public class LettuceGenericCache extends LettuceCache { - private static final LettuceByteCodec codec = new LettuceByteCodec(); - - private String namespace; - private String region; - private RedisClient client; - - public LettuceGenericCache(String namespace, String region, RedisClient client) { + public LettuceGenericCache(String namespace, String region, GenericObjectPool> pool, int scanCount) { if (region == null || region.isEmpty()) region = "_"; // 缺省region - this.client = client; + super.pool = pool; this.namespace = namespace; this.region = getRegionName(region); + this.scanCount = scanCount; } /** @@ -66,57 +66,126 @@ public class LettuceGenericCache implements Level2Cache { @Override public byte[] getBytes(String key) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); return cmd.get(_key(key)); } } @Override public List getBytes(Collection keys) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); - return cmd.mget(keys.stream().map(k -> _key(k)).toArray(String[]::new)).stream().map(kv -> kv.getValue()).collect(Collectors.toList()); + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); + return cmd.mget(keys.stream().map(k -> _key(k)).toArray(String[]::new)).stream().map(kv -> kv.hasValue()?kv.getValue():null).collect(Collectors.toList()); } } @Override public void setBytes(String key, byte[] bytes) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); cmd.set(_key(key), bytes); } } @Override public void setBytes(Map bytes) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); cmd.mset(bytes.entrySet().stream().collect(Collectors.toMap(k -> _key(k.getKey()), Map.Entry::getValue))); } } + + /** + * 设置缓存数据字节数组(带有效期) + * @param key cache key + * @param bytes cache data + * @param timeToLiveInSeconds cache ttl + */ + @Override + public void setBytes(String key, byte[] bytes, long timeToLiveInSeconds){ + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); + if (timeToLiveInSeconds > 0) + cmd.setex(_key(key), timeToLiveInSeconds, bytes); + else + cmd.set(_key(key), bytes); + } + } + + /** + * 批量设置带 TTL 的缓存数据 + * @param bytes cache data + * @param timeToLiveInSeconds cache ttl + */ + @Override + public void setBytes(Map bytes, long timeToLiveInSeconds) { + try(StatefulConnection connection = super.connect()) { + RedisStringCommands cmd = (RedisStringCommands)super.sync(connection); + if (timeToLiveInSeconds > 0) + bytes.forEach((k,v)->cmd.setex(_key(k), timeToLiveInSeconds, v)); + else + bytes.forEach((k,v)->cmd.set(_key(k), v)); + } + } + + + /** + * 1、线上redis服务大概率会禁用或重命名keys命令; + * 2、keys命令效率太低容易致使redis宕机; + * 所以使用scan命令替换keys命令操作,增加可用性及提升执行性能 + */ @Override public Collection keys() { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); - return cmd.keys(this.region + ":*").stream().map(k -> k.substring(this.region.length()+1)).collect(Collectors.toList()); + try(StatefulConnection connection = super.connect()) { + RedisKeyCommands cmd = (RedisKeyCommands)super.sync(connection); + + Collection keys = keys(cmd); + + return keys.stream().map(k -> k.substring(this.region.length()+1)).collect(Collectors.toList()); } } + private Collection keys(RedisKeyCommands cmd) { + Collection keys = new ArrayList<>(); + String cursor = "0"; + Collection partKeys = null; + ScanCursor scanCursor = ScanCursor.INITIAL; + ScanArgs scanArgs = new ScanArgs(); + scanArgs.match(this.region + ":*").limit(scanCount); + KeyScanCursor keyScanCursor = null; + while (!scanCursor.isFinished()) { + keyScanCursor = cmd.scan(scanCursor, scanArgs); + partKeys = keyScanCursor.getKeys(); + if(partKeys != null && partKeys.size() != 0) { + keys.addAll(partKeys); + } + cursor = keyScanCursor.getCursor(); + if("0".equals(cursor)) { + scanCursor = ScanCursor.FINISHED; + } + else { + scanCursor = ScanCursor.of(cursor); + } + } + + return keys; + } + @Override public void evict(String... keys) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisKeyCommands cmd = (RedisKeyCommands)super.sync(connection); cmd.del(Arrays.stream(keys).map(k -> _key(k)).toArray(String[]::new)); } } @Override public void clear() { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); - List keys = cmd.keys(this.region + ":*"); + try(StatefulConnection connection = super.connect()) { + RedisKeyCommands cmd = (RedisKeyCommands)super.sync(connection); + Collection keys = keys(cmd); if(keys != null && keys.size() > 0) cmd.del(keys.stream().toArray(String[]::new)); } diff --git a/core/src/net/oschina/j2cache/lettuce/LettuceHashCache.java b/core/src/net/oschina/j2cache/lettuce/LettuceHashCache.java index cac0c4d99aec2a01230eb829f25c8824b1ce4a36..593a478ef85dcfe785141f8d2d067aa9c0a3ce8d 100644 --- a/core/src/net/oschina/j2cache/lettuce/LettuceHashCache.java +++ b/core/src/net/oschina/j2cache/lettuce/LettuceHashCache.java @@ -15,10 +15,10 @@ */ package net.oschina.j2cache.lettuce; -import io.lettuce.core.RedisClient; -import io.lettuce.core.api.StatefulRedisConnection; -import io.lettuce.core.api.sync.RedisCommands; -import net.oschina.j2cache.Level2Cache; +import io.lettuce.core.api.StatefulConnection; +import io.lettuce.core.api.sync.RedisHashCommands; +import io.lettuce.core.api.sync.RedisKeyCommands; +import org.apache.commons.pool2.impl.GenericObjectPool; import java.util.Collection; import java.util.List; @@ -31,21 +31,15 @@ import java.util.stream.Collectors; * * 重要提示!!! hash 存储模式无法单独对 key 设置 expire */ -public class LettuceHashCache implements Level2Cache { +public class LettuceHashCache extends LettuceCache { - private static final LettuceByteCodec codec = new LettuceByteCodec(); - - private String namespace; - private String region; - private RedisClient client; - - public LettuceHashCache(String namespace, String region, RedisClient client) { + public LettuceHashCache(String namespace, String region, GenericObjectPool> pool) { if (region == null || region.isEmpty()) region = "_"; // 缺省region - this.client = client; - this.namespace = namespace; - this.region = getRegionName(region); + super.pool = pool; + super.namespace = namespace; + super.region = getRegionName(region); } /** @@ -63,56 +57,56 @@ public class LettuceHashCache implements Level2Cache { @Override public byte[] getBytes(String key) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); return cmd.hget(this.region, key); } } @Override public List getBytes(Collection keys) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); - return cmd.hmget(this.region, keys.stream().toArray(String[]::new)).stream().map(kv -> kv.getValue()).collect(Collectors.toList()); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); + return cmd.hmget(this.region, keys.stream().toArray(String[]::new)).stream().map(kv -> kv.hasValue()?kv.getValue():null).collect(Collectors.toList()); } } @Override public void setBytes(String key, byte[] bytes) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); cmd.hset(this.region, key, bytes); } } @Override public void setBytes(Map bytes) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); cmd.hmset(this.region, bytes); } } @Override public Collection keys() { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); return cmd.hkeys(this.region); } } @Override public void evict(String... keys) { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisHashCommands cmd = (RedisHashCommands)super.sync(connection); cmd.hdel(this.region, keys); } } @Override public void clear() { - try(StatefulRedisConnection connection = this.client.connect(codec)) { - RedisCommands cmd = connection.sync(); + try(StatefulConnection connection = super.connect()) { + RedisKeyCommands cmd = (RedisKeyCommands)super.sync(connection); cmd.del(this.region); } } diff --git a/core/src/net/oschina/j2cache/memcached/XmemcachedCacheProvider.java b/core/src/net/oschina/j2cache/memcached/XmemcachedCacheProvider.java index fa49034aac4a978b3b75cdc2485c266e09becab4..f81ff413c8244da9d8eeade8f4c4c30febacae13 100644 --- a/core/src/net/oschina/j2cache/memcached/XmemcachedCacheProvider.java +++ b/core/src/net/oschina/j2cache/memcached/XmemcachedCacheProvider.java @@ -41,7 +41,7 @@ public class XmemcachedCacheProvider implements CacheProvider { private static final Logger log = LoggerFactory.getLogger(XmemcachedCacheProvider.class); private MemcachedClient client ; - private static final ConcurrentHashMap regions = new ConcurrentHashMap(); + private final ConcurrentHashMap regions = new ConcurrentHashMap(); @Override public String name() { @@ -53,31 +53,31 @@ public class XmemcachedCacheProvider implements CacheProvider { long ct = System.currentTimeMillis(); - String servers = props.getProperty("servers"); - String username = props.getProperty("username"); - String password = props.getProperty("password"); + String servers = props.getProperty("servers", "127.0.0.1:11211"); + String username = props.getProperty("username", ""); + String password = props.getProperty("password", ""); MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(servers)); builder.setCommandFactory(new BinaryCommandFactory()); boolean needAuth = username != null && password != null && username.trim().length() > 0 && password.trim().length() > 0; if(needAuth) builder.addAuthInfo(AddrUtil.getOneAddress(servers), AuthInfo.typical(username, password)); - builder.setConnectionPoolSize(Integer.valueOf(props.getProperty("connectionPoolSize"))); - builder.setConnectTimeout(Long.valueOf(props.getProperty("connectTimeout"))); - builder.setHealSessionInterval(Long.valueOf(props.getProperty("healSessionInterval"))); - builder.setMaxQueuedNoReplyOperations(Integer.valueOf(props.getProperty("maxQueuedNoReplyOperations"))); - builder.setOpTimeout(Long.valueOf(props.getProperty("opTimeout"))); - builder.setSanitizeKeys("true".equalsIgnoreCase(props.getProperty("sanitizeKeys"))); + builder.setConnectionPoolSize(Integer.valueOf(props.getProperty("connectionPoolSize", "10"))); + builder.setConnectTimeout(Long.valueOf(props.getProperty("connectTimeout", "1000"))); + builder.setHealSessionInterval(Long.valueOf(props.getProperty("healSessionInterval", "1000"))); + builder.setMaxQueuedNoReplyOperations(Integer.valueOf(props.getProperty("maxQueuedNoReplyOperations", "100"))); + builder.setOpTimeout(Long.valueOf(props.getProperty("opTimeout", "100"))); + builder.setSanitizeKeys("true".equalsIgnoreCase(props.getProperty("sanitizeKeys", "false"))); try { client = builder.build(); - log.info(String.format("Memcached client starts with servers(%s),auth(%s),pool-size(%s),time(%dms)", + log.info("Memcached client starts with servers({}),auth({}),pool-size({}),time({}ms)", servers, needAuth, builder.getConfiguration().getSelectorPoolSize(), System.currentTimeMillis() - ct - )); + ); } catch (IOException e) { log.error("Failed to connect to memcached", e); } diff --git a/core/src/net/oschina/j2cache/redis/ReadonlyRedisCacheProvider.java b/core/src/net/oschina/j2cache/redis/ReadonlyRedisCacheProvider.java index 92c5c1f95ae3be44f5103b35907e006a813a3c11..50a79bdf6be08654fe1d797d6f3e2a2041fdab51 100644 --- a/core/src/net/oschina/j2cache/redis/ReadonlyRedisCacheProvider.java +++ b/core/src/net/oschina/j2cache/redis/ReadonlyRedisCacheProvider.java @@ -74,7 +74,7 @@ public class ReadonlyRedisCacheProvider extends RedisCacheProvider { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if(ignoreMethods.contains(methodName)) { - log.debug(String.format("Cache [%s] skipped.", methodName)); + log.debug("Cache [{}] skipped.", methodName); return null; } try { diff --git a/core/src/net/oschina/j2cache/redis/RedisCacheProvider.java b/core/src/net/oschina/j2cache/redis/RedisCacheProvider.java index ca47064772bba5b99ad22c0504760aeddc95fb5b..aacfb81d5433910bb1539ad18b1cde35fb5cd0c9 100644 --- a/core/src/net/oschina/j2cache/redis/RedisCacheProvider.java +++ b/core/src/net/oschina/j2cache/redis/RedisCacheProvider.java @@ -39,8 +39,9 @@ public class RedisCacheProvider implements CacheProvider { private RedisClient redisClient; private String namespace; private String storage; + private int scanCount; - private static final ConcurrentHashMap regions = new ConcurrentHashMap(); + private final ConcurrentHashMap regions = new ConcurrentHashMap(); @Override public String name() { @@ -58,16 +59,18 @@ public class RedisCacheProvider implements CacheProvider { */ @Override public void start(Properties props) { + this.scanCount = Integer.valueOf(props.getProperty("scanCount", "1000")); this.namespace = props.getProperty("namespace"); this.storage = props.getProperty("storage"); JedisPoolConfig poolConfig = RedisUtils.newPoolConfig(props, null); - String hosts = props.getProperty("hosts"); - String mode = props.getProperty("mode"); + String hosts = props.getProperty("hosts", "127.0.0.1:6379"); + String mode = props.getProperty("mode", "single"); String clusterName = props.getProperty("cluster_name"); String password = props.getProperty("password"); - int database = Integer.parseInt(props.getProperty("database")); + int database = Integer.parseInt(props.getProperty("database", "0")); + boolean ssl = Boolean.valueOf(props.getProperty("ssl", "false")); long ct = System.currentTimeMillis(); @@ -77,19 +80,22 @@ public class RedisCacheProvider implements CacheProvider { .password(password) .cluster(clusterName) .database(database) - .poolConfig(poolConfig).newClient(); + .poolConfig(poolConfig) + .ssl(ssl) + .newClient(); - log.info(String.format("Redis client starts with mode(%s),db(%d),storage(%s),namespace(%s),time(%dms)", + log.info("Redis client starts with mode({}),db({}),storage({}),namespace({}),time({}ms)", mode, database, storage, namespace, - System.currentTimeMillis()-ct - )); + (System.currentTimeMillis()-ct) + ); } @Override public void stop() { + regions.clear(); try { redisClient.close(); } catch (IOException e) { @@ -99,7 +105,9 @@ public class RedisCacheProvider implements CacheProvider { @Override public Cache buildCache(String region, CacheExpiredListener listener) { - return regions.computeIfAbsent(region, v -> "hash".equalsIgnoreCase(this.storage)?new RedisHashCache(this.namespace, region, redisClient):new RedisGenericCache(this.namespace, region, redisClient)); + return regions.computeIfAbsent(this.namespace+":"+region, v -> "hash".equalsIgnoreCase(this.storage)? + new RedisHashCache(this.namespace, region, redisClient): + new RedisGenericCache(this.namespace, region, redisClient, scanCount)); } @Override diff --git a/core/src/net/oschina/j2cache/redis/RedisClient.java b/core/src/net/oschina/j2cache/redis/RedisClient.java index 3ae8da5d54a41dbc65183dd63976b01dbc35d9e4..85054bac7f55a4f0a26d650b7ad955a12176c7a4 100644 --- a/core/src/net/oschina/j2cache/redis/RedisClient.java +++ b/core/src/net/oschina/j2cache/redis/RedisClient.java @@ -50,7 +50,6 @@ public class RedisClient implements Closeable, AutoCloseable { private JedisPool single; private JedisSentinelPool sentinel; private ShardedJedisPool sharded; - private String redisPassword; /** * RedisClient 构造器 @@ -62,6 +61,7 @@ public class RedisClient implements Closeable, AutoCloseable { private String cluster; private int database; private JedisPoolConfig poolConfig; + private boolean ssl; public Builder(){} @@ -99,8 +99,12 @@ public class RedisClient implements Closeable, AutoCloseable { this.poolConfig = poolConfig; return this; } + public Builder ssl(boolean ssl) { + this.ssl = ssl; + return this; + } public RedisClient newClient() { - return new RedisClient(mode, hosts, password, cluster, database, poolConfig); + return new RedisClient(mode, hosts, password, cluster, database, poolConfig, ssl); } } @@ -113,9 +117,10 @@ public class RedisClient implements Closeable, AutoCloseable { * @param cluster_name 集群名称 * @param database 数据库 * @param poolConfig 连接池配置 + * @param ssl 使用ssl */ - private RedisClient(String mode, String hosts, String password, String cluster_name, int database, JedisPoolConfig poolConfig) { - this.redisPassword = (password != null && password.trim().length() > 0)? password.trim(): null; + private RedisClient(String mode, String hosts, String password, String cluster_name, int database, JedisPoolConfig poolConfig, boolean ssl) { + password = (password != null && password.trim().length() > 0)? password.trim(): null; this.clients = new ThreadLocal<>(); switch(mode){ case "sentinel": @@ -149,11 +154,11 @@ public class RedisClient implements Closeable, AutoCloseable { String[] infos = node.split(":"); String host = infos[0]; int port = (infos.length > 1)?Integer.parseInt(infos[1]):6379; - this.single = new JedisPool(poolConfig, host, port, CONNECT_TIMEOUT, password, database); + this.single = new JedisPool(poolConfig, host, port, CONNECT_TIMEOUT, password, database, ssl); break; } if(!"single".equalsIgnoreCase(mode)) - log.warn("Redis mode [" + mode + "] not defined. Using 'single'."); + log.warn("Redis mode [{}] not defined. Using 'single'.", mode); break; } } @@ -173,13 +178,14 @@ public class RedisClient implements Closeable, AutoCloseable { client = sharded.getResource(); else if (cluster != null) client = toBinaryJedisCommands(cluster); + clients.set(client); } return client; } /** - * 释放 Redis 连接 + * 释放当前 Redis 连接 */ public void release() { BinaryJedisCommands client = clients.get(); @@ -192,12 +198,14 @@ public class RedisClient implements Closeable, AutoCloseable { log.error("Failed to release jedis connection.", e); } } - else - log.warn("Nothing to do while release redis client."); clients.remove(); } } + /** + * 释放连接池 + * @throws IOException io close exception + */ @Override public void close() throws IOException { if(single != null) diff --git a/core/src/net/oschina/j2cache/redis/RedisGenericCache.java b/core/src/net/oschina/j2cache/redis/RedisGenericCache.java index 61b1d7062bc0b302850d1ed5aea6121a8eb351a5..c06663fb30667dc98b17e0c2337aa449ba8515b3 100644 --- a/core/src/net/oschina/j2cache/redis/RedisGenericCache.java +++ b/core/src/net/oschina/j2cache/redis/RedisGenericCache.java @@ -15,22 +15,27 @@ */ package net.oschina.j2cache.redis; -import net.oschina.j2cache.CacheException; -import net.oschina.j2cache.Level2Cache; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import redis.clients.jedis.BinaryJedis; -import redis.clients.jedis.BinaryJedisCommands; -import redis.clients.jedis.MultiKeyBinaryCommands; -import redis.clients.jedis.MultiKeyCommands; - import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.oschina.j2cache.CacheException; +import net.oschina.j2cache.Level2Cache; +import redis.clients.jedis.BinaryJedis; +import redis.clients.jedis.BinaryJedisCommands; +import redis.clients.jedis.MultiKeyBinaryCommands; +import redis.clients.jedis.MultiKeyCommands; +import redis.clients.jedis.ScanParams; +import redis.clients.jedis.ScanResult; + /** * Redis 缓存操作封装,基于 region+_key 实现多个 Region 的缓存( * @author Winter Lau(javayou@gmail.com) @@ -42,6 +47,7 @@ public class RedisGenericCache implements Level2Cache { private String namespace; private String region; private RedisClient client; + private int scanCount; /** * 缓存构造 @@ -49,13 +55,14 @@ public class RedisGenericCache implements Level2Cache { * @param region 缓存区域的名称 * @param client 缓存客户端接口 */ - public RedisGenericCache(String namespace, String region, RedisClient client) { + public RedisGenericCache(String namespace, String region, RedisClient client, int scanCount) { if (region == null || region.isEmpty()) region = "_"; // 缺省region this.client = client; this.namespace = namespace; this.region = _regionName(region); + this.scanCount = scanCount; } @Override @@ -168,7 +175,13 @@ public class RedisGenericCache implements Level2Cache { } else */ - bytes.forEach((k,v) -> setBytes(k, v, timeToLiveInSeconds)); + + if (timeToLiveInSeconds <= 0) { + log.debug(String.format("Invalid timeToLiveInSeconds value : %d , skipped it.", timeToLiveInSeconds)); + setBytes(bytes); + } + else + bytes.forEach((k,v) -> setBytes(k, v, timeToLiveInSeconds)); } finally { client.release(); } @@ -184,14 +197,17 @@ public class RedisGenericCache implements Level2Cache { } /** - * 性能可能极其低下,谨慎使用 + * 1、线上redis服务大概率会禁用或重命名keys命令; + * 2、keys命令效率太低容易致使redis宕机; + * 所以使用scan命令替换keys命令操作,增加可用性及提升执行性能 */ @Override public Collection keys() { try { BinaryJedisCommands cmd = client.get(); if (cmd instanceof MultiKeyCommands) { - Collection keys = ((MultiKeyCommands) cmd).keys(this.region + ":*"); + Collection keys = keys(cmd); + return keys.stream().map(k -> k.substring(this.region.length()+1)).collect(Collectors.toList()); } } finally { @@ -200,6 +216,25 @@ public class RedisGenericCache implements Level2Cache { throw new CacheException("keys() not implemented in Redis Generic Mode"); } + private Collection keys(BinaryJedisCommands cmd) { + Collection keys = new ArrayList<>(); + String cursor = "0"; + ScanParams scanParams = new ScanParams(); + scanParams.match(this.region + ":*"); + scanParams.count(scanCount); // 这个不是返回结果的数量,应该是每次scan的数量 + ScanResult scan = ((MultiKeyCommands) cmd).scan(cursor, scanParams); + while (null != scan.getStringCursor()) { + keys.addAll(scan.getResult()); // 这一次scan match到的结果 + if (!StringUtils.equals(cursor, scan.getStringCursor())) { // 不断拿着新的cursor scan,最终会拿到所有匹配的值 + scan = ((MultiKeyCommands) cmd).scan(scan.getStringCursor(), scanParams); + continue; + } else { + break; + } + } + return keys; + } + @Override public void evict(String...keys) { try { @@ -218,14 +253,15 @@ public class RedisGenericCache implements Level2Cache { } /** - * 性能可能极其低下,谨慎使用 + * 已使用scan命令替换keys命令操作 */ @Override public void clear() { try { BinaryJedisCommands cmd = client.get(); if (cmd instanceof MultiKeyCommands) { - String[] keys = ((MultiKeyCommands) cmd).keys(this.region + ":*").stream().toArray(String[]::new); + Collection keysCollection = keys(cmd); + String[] keys = keysCollection.stream().toArray(String[]::new); if (keys != null && keys.length > 0) ((MultiKeyCommands) cmd).del(keys); } @@ -235,4 +271,4 @@ public class RedisGenericCache implements Level2Cache { client.release(); } } -} +} \ No newline at end of file diff --git a/core/src/net/oschina/j2cache/redis/RedisPubSubClusterPolicy.java b/core/src/net/oschina/j2cache/redis/RedisPubSubClusterPolicy.java index 3aeb3adaf1e8a4c69662cb28cd15e7abebf22cba..2a1d95ea067f7e6fb404321fc0ff65ba2490f762 100755 --- a/core/src/net/oschina/j2cache/redis/RedisPubSubClusterPolicy.java +++ b/core/src/net/oschina/j2cache/redis/RedisPubSubClusterPolicy.java @@ -15,14 +15,16 @@ */ package net.oschina.j2cache.redis; -import net.oschina.j2cache.cluster.ClusterPolicy; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; +import net.oschina.j2cache.cluster.ClusterPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.*; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.util.Pool; +import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Properties; @@ -37,8 +39,16 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli private final static Logger log = LoggerFactory.getLogger(RedisPubSubClusterPolicy.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + private static int CONNECT_TIMEOUT = 5000; //Redis连接超时时间 + private static int SO_TIMEOUT = 5000; + private static int MAX_ATTEMPTS = 3; + private Pool client; + private JedisCluster cluster; private String channel; + private CacheProviderHolder holder; + private boolean clusterMode = false; public RedisPubSubClusterPolicy(String channel, Properties props){ this.channel = channel; @@ -48,6 +58,7 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli password = null; int database = Integer.parseInt(props.getProperty("database", "0")); + boolean ssl = Boolean.valueOf(props.getProperty("ssl", "false")); JedisPoolConfig config = RedisUtils.newPoolConfig(props, null); @@ -55,43 +66,99 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli if(node == null || node.trim().length() == 0) node = props.getProperty("hosts"); - if("sentinel".equalsIgnoreCase(props.getProperty("mode"))){ + String mode = props.getProperty("mode"); + if ("sentinel".equalsIgnoreCase(mode)) { Set hosts = new HashSet(); hosts.addAll(Arrays.asList(node.split(","))); String masterName = props.getProperty("cluster_name", "j2cache"); this.client = new JedisSentinelPool(masterName, hosts, config, timeout, password, database); - } - else { + } else if ("cluster".equalsIgnoreCase(mode)) { + String[] nodeArray = node.split(","); + Set nodeSet = new HashSet(nodeArray.length); + for (String nodeItem : nodeArray) { + String[] arr = nodeItem.split(":"); + nodeSet.add(new HostAndPort(arr[0], Integer.valueOf(arr[1]))); + } + JedisPoolConfig poolConfig = RedisUtils.newPoolConfig(props, null); + this.cluster = new JedisCluster(nodeSet, CONNECT_TIMEOUT, SO_TIMEOUT, MAX_ATTEMPTS, password, poolConfig); + this.clusterMode = true; + } else { node = node.split(",")[0]; //取第一台主机 String[] infos = node.split(":"); String host = infos[0]; int port = (infos.length > 1)?Integer.parseInt(infos[1]):6379; - this.client = new JedisPool(config, host, port, timeout, password, database); + this.client = new JedisPool(config, host, port, timeout, password, database, ssl); } } + @Override + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + @Override + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + @Override + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } + /** * 加入 Redis 的发布订阅频道 */ @Override - public void connect(Properties props) { + public void connect(Properties props, CacheProviderHolder holder) { long ct = System.currentTimeMillis(); + this.holder = holder; this.publish(Command.join()); Thread subscribeThread = new Thread(()-> { - //当 Redis 重启会导致订阅线程断开连接,需要进行重连 - while(true) { - try (Jedis jedis = client.getResource()){ - jedis.subscribe(this, channel); - log.info("Disconnect to redis channel: " + channel); - break; - } catch (JedisConnectionException e) { - log.error("Failed connect to redis, reconnect it.", e); + if (clusterMode) { + // 如果出现集群节点宕机,需要重连 + while (cluster != null) { try { - Thread.sleep(1000); - } catch (InterruptedException ie){ + this.cluster.subscribe(this, channel); + break; + } catch (Exception e) { + log.error("failed connect redis cluster, reconnect it.", e); + e.printStackTrace(); + if (cluster != null) { + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + break; + } + } + } + } + } else { + //当 Redis 重启会导致订阅线程断开连接,需要进行重连 + while(!client.isClosed()) { + try (Jedis jedis = client.getResource()){ + jedis.subscribe(this, channel); + log.info("Disconnect to redis channel: {}", channel); break; + } catch (JedisConnectionException e) { + log.error("Failed connect to redis, reconnect it.", e); + if(!client.isClosed()) + try { + Thread.sleep(1000); + } catch (InterruptedException ie){ + break; + } } } } @@ -100,7 +167,7 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli subscribeThread.setDaemon(true); subscribeThread.start(); - log.info("Connected to redis channel:" + channel + ", time " + (System.currentTimeMillis()-ct) + " ms."); + log.info("Connected to redis channel:{}, time {} ms.", channel, (System.currentTimeMillis()-ct)); } /** @@ -113,15 +180,21 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli if(this.isSubscribed()) this.unsubscribe(); } finally { - this.client.close(); + close(); + //this.client.close(); //subscribeThread will auto terminate } } @Override public void publish(Command cmd) { - try (Jedis jedis = client.getResource()) { - jedis.publish(channel, cmd.json()); + cmd.setSrc(LOCAL_COMMAND_ID); + if (this.clusterMode) { + this.cluster.publish(channel, cmd.json()); + } else { + try (Jedis jedis = client.getResource()) { + jedis.publish(channel, cmd.json()); + } } } @@ -136,4 +209,28 @@ public class RedisPubSubClusterPolicy extends JedisPubSub implements ClusterPoli handleCommand(cmd); } + @Override + public void unsubscribe() { + if (!this.clusterMode) { + super.unsubscribe(); + } + } + + private void close() { + try { + if (this.client != null) { + this.client.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + try { + if (this.cluster != null) { + this.cluster.close(); + } + this.cluster = null; + } catch (IOException e) { + e.printStackTrace(); + } + } } diff --git a/core/src/net/oschina/j2cache/util/AntPathMatcher.java b/core/src/net/oschina/j2cache/util/AntPathMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..21a72ffd38841e435a0eb2781c1acd1285330fcc --- /dev/null +++ b/core/src/net/oschina/j2cache/util/AntPathMatcher.java @@ -0,0 +1,408 @@ +package net.oschina.j2cache.util; + +/** + *

PathMatcher implementation for Ant-style path patterns. + * Examples are provided below.

+ * + *

Part of this mapping code has been kindly borrowed from + * Apache Ant. + * + *

The mapping matches URLs using the following rules:
+ *

    + *
  • ? matches one character
  • + *
  • * matches zero or more characters
  • + *
  • ** matches zero or more 'directories' in a path
  • + *
+ * + *

Some examples:
+ *

    + *
  • com/t?st.jsp - matches com/test.jsp but also + * com/tast.jsp or com/txst.jsp
  • + *
  • com/*.jsp - matches all .jsp files in the + * com directory
  • + *
  • com/**/test.jsp - matches all test.jsp + * files underneath the com path
  • + *
  • org/apache/shiro/**/*.jsp - matches all .jsp + * files underneath the org/apache/shiro path
  • + *
  • org/**/servlet/bla.jsp - matches + * org/apache/shiro/servlet/bla.jsp but also + * org/apache/shiro/testing/servlet/bla.jsp and + * org/servlet/bla.jsp
  • + *
+ * + *

N.B.: This class was borrowed (with much appreciation) from the + * Spring Framework with modifications. We didn't want to reinvent the + * wheel of great work they've done, but also didn't want to force every Shiro user to depend on Spring

+ * + *

As per the Apache 2.0 license, the original copyright notice and all author and copyright information have + * remained in tact.

+ * + * @since 16.07.2003 + */ +public class AntPathMatcher implements PatternMatcher { + + //TODO - complete JavaDoc + + /** + * Default path separator: "/" + */ + public static final String DEFAULT_PATH_SEPARATOR = "/"; + + private String pathSeparator = DEFAULT_PATH_SEPARATOR; + + + /** + * Set the path separator to use for pattern parsing. + * Default is "/", as in Ant. + */ + public void setPathSeparator(String pathSeparator) { + this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR); + } + + + public boolean isPattern(String path) { + return (path.indexOf('*') != -1 || path.indexOf('?') != -1); + } + + public boolean matches(String pattern, String source) { + return match(pattern, source); + } + + public boolean match(String pattern, String path) { + return doMatch(pattern, path, true); + } + + public boolean matchStart(String pattern, String path) { + return doMatch(pattern, path, false); + } + + + /** + * Actually match the given path against the given pattern. + * + * @param pattern the pattern to match against + * @param path the path String to test + * @param fullMatch whether a full pattern match is required + * (else a pattern match as far as the given base path goes is sufficient) + * @return true if the supplied path matched, + * false if it didn't + */ + protected boolean doMatch(String pattern, String path, boolean fullMatch) { + if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { + return false; + } + + String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); + String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + + int pattIdxStart = 0; + int pattIdxEnd = pattDirs.length - 1; + int pathIdxStart = 0; + int pathIdxEnd = pathDirs.length - 1; + + // Match all elements up to the first ** + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxStart]; + if ("**".equals(patDir)) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxStart])) { + return false; + } + pattIdxStart++; + pathIdxStart++; + } + + if (pathIdxStart > pathIdxEnd) { + // Path is exhausted, only match if rest of pattern is * or **'s + if (pattIdxStart > pattIdxEnd) { + return (pattern.endsWith(this.pathSeparator) ? + path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator)); + } + if (!fullMatch) { + return true; + } + if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && + path.endsWith(this.pathSeparator)) { + return true; + } + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } else if (pattIdxStart > pattIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { + // Path start definitely matches due to "**" part in pattern. + return true; + } + + // up to last '**' + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxEnd]; + if (patDir.equals("**")) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxEnd])) { + return false; + } + pattIdxEnd--; + pathIdxEnd--; + } + if (pathIdxStart > pathIdxEnd) { + // String is exhausted + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } + + while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { + int patIdxTmp = -1; + for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { + if (pattDirs[i].equals("**")) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == pattIdxStart + 1) { + // '**/**' situation, so skip one + pattIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - pattIdxStart - 1); + int strLength = (pathIdxEnd - pathIdxStart + 1); + int foundIdx = -1; + + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = (String) pattDirs[pattIdxStart + j + 1]; + String subStr = (String) pathDirs[pathIdxStart + i + j]; + if (!matchStrings(subPat, subStr)) { + continue strLoop; + } + } + foundIdx = pathIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + pattIdxStart = patIdxTmp; + pathIdxStart = foundIdx + patLength; + } + + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + + return true; + } + + /** + * Tests whether or not a string matches against a pattern. + * The pattern may contain two special characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * + * @param pattern pattern to match against. + * Must not be null. + * @param str string which must be matched against the pattern. + * Must not be null. + * @return true if the string matches against the + * pattern, or false otherwise. + */ + private boolean matchStrings(String pattern, String str) { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length - 1; + int strIdxStart = 0; + int strIdxEnd = strArr.length - 1; + char ch; + + boolean containsStar = false; + for (char aPatArr : patArr) { + if (aPatArr == '*') { + containsStar = true; + break; + } + } + + if (!containsStar) { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) { + ch = patArr[i]; + if (ch != '?') { + if (ch != strArr[i]) { + return false;// Character mismatch + } + } + } + return true; // String matches against pattern + } + + + if (patIdxEnd == 0) { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxStart]) { + return false;// Character mismatch + } + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // Process characters after last star + while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxEnd]) { + return false;// Character mismatch + } + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*') { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + ch = patArr[patIdxStart + j + 1]; + if (ch != '?') { + if (ch != strArr[strIdxStart + i + j]) { + continue strLoop; + } + } + } + + foundIdx = strIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + + return true; + } + + /** + * Given a pattern and a full path, determine the pattern-mapped part. + *

For example: + *

    + *
  • '/docs/cvs/commit.html' and '/docs/cvs/commit.html -> ''
  • + *
  • '/docs/*' and '/docs/cvs/commit -> 'cvs/commit'
  • + *
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html -> 'commit.html'
  • + *
  • '/docs/**' and '/docs/cvs/commit -> 'cvs/commit'
  • + *
  • '/docs/**\/*.html' and '/docs/cvs/commit.html -> 'cvs/commit.html'
  • + *
  • '/*.html' and '/docs/cvs/commit.html -> 'docs/cvs/commit.html'
  • + *
  • '*.html' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • + *
  • '*' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • + *
+ *

Assumes that {@link #match} returns true for 'pattern' + * and 'path', but does not enforce this. + */ + public String extractPathWithinPattern(String pattern, String path) { + String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); + String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + + StringBuilder buffer = new StringBuilder(); + + // Add any path parts that have a wildcarded pattern part. + int puts = 0; + for (int i = 0; i < patternParts.length; i++) { + String patternPart = patternParts[i]; + if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) { + if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + puts++; + } + } + + // Append any trailing path parts. + for (int i = patternParts.length; i < pathParts.length; i++) { + if (puts > 0 || i > 0) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + } + + return buffer.toString(); + } + +} + diff --git a/core/src/net/oschina/j2cache/util/FseSerializer.java b/core/src/net/oschina/j2cache/util/FseSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..850bef2e2daaffe8e56eb1589b8be56613b6db39 --- /dev/null +++ b/core/src/net/oschina/j2cache/util/FseSerializer.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015-2020, whcrow (v@whcrow.com). + *

+ * 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 net.oschina.j2cache.util; + +import com.jfirer.fse.ByteArray; +import com.jfirer.fse.Fse; + +/** + * 使用 fse 实现序列化 + * + * @author whcrow (v@whcrow.com) + */ +public class FseSerializer implements Serializer { + + @Override + public String name() { + return "fse"; + } + + @Override + public byte[] serialize(Object obj) { + ByteArray buf = ByteArray.allocate(100); + new Fse().serialize(obj, buf); + byte[] resultBytes = buf.toArray(); + buf.clear(); + return resultBytes; + } + + @Override + public Object deserialize(byte[] bytes) { + if (bytes == null || bytes.length == 0) { + return null; + } + ByteArray buf = ByteArray.allocate(100); + buf.put(bytes); + Object result = new Fse().deSerialize(buf); + buf.clear(); + return result; + } + +} diff --git a/core/src/net/oschina/j2cache/util/PatternMatcher.java b/core/src/net/oschina/j2cache/util/PatternMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..303ff737f520871702f7a58a0f0f06b83b14888d --- /dev/null +++ b/core/src/net/oschina/j2cache/util/PatternMatcher.java @@ -0,0 +1,24 @@ +package net.oschina.j2cache.util; + +/** + * Interface for components that can match source strings against a specified pattern string. + *

+ * Different implementations can support different pattern types, for example, Ant style path expressions, or + * regular expressions, or other types of text based patterns. + * + * @see org.apache.shiro.util.AntPathMatcher AntPathMatcher + * @since 0.9 RC2 + */ +public interface PatternMatcher { + + /** + * Returns true if the given source matches the specified pattern, + * false otherwise. + * + * @param pattern the pattern to match against + * @param source the source to match + * @return true if the given source matches the specified pattern, + * false otherwise. + */ + boolean matches(String pattern, String source); +} diff --git a/core/src/net/oschina/j2cache/util/SerializationUtils.java b/core/src/net/oschina/j2cache/util/SerializationUtils.java index fbef193098beefa6d21b81e82eeebda08a19df44..5172a520547bb6266bc59d657e47082303cca1ad 100644 --- a/core/src/net/oschina/j2cache/util/SerializationUtils.java +++ b/core/src/net/oschina/j2cache/util/SerializationUtils.java @@ -55,6 +55,8 @@ public class SerializationUtils { g_serializer = new FstJSONSerializer(props); } else if ("fastjson".equals(ser)) { g_serializer = new FastjsonSerializer(); + } else if ("fse".equals(ser)) { + g_serializer = new FseSerializer(); } else { try { g_serializer = (Serializer) Class.forName(ser).newInstance(); @@ -63,7 +65,7 @@ public class SerializationUtils { } } } - log.info("Using Serializer -> [" + g_serializer.name() + ":" + g_serializer.getClass().getName() + ']'); + log.info("Using Serializer -> [{}:{}]", g_serializer.name(), g_serializer.getClass().getName()); } /** diff --git a/core/src/net/oschina/j2cache/util/StringUtils.java b/core/src/net/oschina/j2cache/util/StringUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..fa3d4fc6faf5635a03b71300fb26acd93b81b939 --- /dev/null +++ b/core/src/net/oschina/j2cache/util/StringUtils.java @@ -0,0 +1,297 @@ +package net.oschina.j2cache.util; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; + +public class StringUtils { + public static final String EMPTY_STRING = ""; + public static final char DEFAULT_DELIMITER_CHAR = ','; + public static final char DEFAULT_QUOTE_CHAR = '"'; + + public StringUtils() { + } + + public static boolean hasText(String str) { + if (!hasLength(str)) { + return false; + } else { + int strLen = str.length(); + + for(int i = 0; i < strLen; ++i) { + if (!Character.isWhitespace(str.charAt(i))) { + return true; + } + } + + return false; + } + } + + public static boolean hasLength(String str) { + return str != null && str.length() > 0; + } + + public static boolean startsWithIgnoreCase(String str, String prefix) { + if (str != null && prefix != null) { + if (str.startsWith(prefix)) { + return true; + } else if (str.length() < prefix.length()) { + return false; + } else { + String lcStr = str.substring(0, prefix.length()).toLowerCase(); + String lcPrefix = prefix.toLowerCase(); + return lcStr.equals(lcPrefix); + } + } else { + return false; + } + } + + public static String clean(String in) { + String out = in; + if (in != null) { + out = in.trim(); + if (out.equals("")) { + out = null; + } + } + + return out; + } + + public static String toString(Object[] array) { + return toDelimitedString(array, ","); + } + + public static String toDelimitedString(Object[] array, String delimiter) { + if (array != null && array.length != 0) { + StringBuilder sb = new StringBuilder(); + + for(int i = 0; i < array.length; ++i) { + if (i > 0) { + sb.append(delimiter); + } + + sb.append(array[i]); + } + + return sb.toString(); + } else { + return ""; + } + } + + public static String toDelimitedString(Collection c, String delimiter) { + return c != null && !c.isEmpty() ? join(c.iterator(), delimiter) : ""; + } + + public static String[] tokenizeToStringArray(String str, String delimiters) { + return tokenizeToStringArray(str, delimiters, true, true); + } + + public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) { + if (str == null) { + return null; + } else { + StringTokenizer st = new StringTokenizer(str, delimiters); + ArrayList tokens = new ArrayList(); + + while(true) { + String token; + do { + if (!st.hasMoreTokens()) { + return toStringArray(tokens); + } + + token = st.nextToken(); + if (trimTokens) { + token = token.trim(); + } + } while(ignoreEmptyTokens && token.length() <= 0); + + tokens.add(token); + } + } + } + + public static String[] toStringArray(Collection collection) { + return collection == null ? null : (String[])collection.toArray(new String[collection.size()]); + } + + public static String[] splitKeyValue(String aLine) throws ParseException { + String line = clean(aLine); + if (line == null) { + return null; + } else { + String[] split = line.split(" ", 2); + String msg; + if (split.length != 2) { + split = line.split("=", 2); + if (split.length != 2) { + msg = "Unable to determine Key/Value pair from line [" + line + "]. There is no space from which the split location could be determined."; + throw new ParseException(msg, 0); + } + } + + split[0] = clean(split[0]); + split[1] = clean(split[1]); + if (split[1].startsWith("=")) { + split[1] = clean(split[1].substring(1)); + } + + if (split[0] == null) { + msg = "No valid key could be found in line [" + line + "] to form a key/value pair."; + throw new ParseException(msg, 0); + } else if (split[1] == null) { + msg = "No corresponding value could be found in line [" + line + "] for key [" + split[0] + "]"; + throw new ParseException(msg, 0); + } else { + return split; + } + } + } + + public static String[] split(String line) { + return split(line, ','); + } + + public static String[] split(String line, char delimiter) { + return split(line, delimiter, '"'); + } + + public static String[] split(String line, char delimiter, char quoteChar) { + return split(line, delimiter, quoteChar, quoteChar); + } + + public static String[] split(String line, char delimiter, char beginQuoteChar, char endQuoteChar) { + return split(line, delimiter, beginQuoteChar, endQuoteChar, false, true); + } + + public static String[] split(String aLine, char delimiter, char beginQuoteChar, char endQuoteChar, boolean retainQuotes, boolean trimTokens) { + String line = clean(aLine); + if (line == null) { + return null; + } else { + List tokens = new ArrayList(); + StringBuilder sb = new StringBuilder(); + boolean inQuotes = false; + + for(int i = 0; i < line.length(); ++i) { + char c = line.charAt(i); + if (c == beginQuoteChar) { + if (inQuotes && line.length() > i + 1 && line.charAt(i + 1) == beginQuoteChar) { + sb.append(line.charAt(i + 1)); + ++i; + } else { + inQuotes = !inQuotes; + if (retainQuotes) { + sb.append(c); + } + } + } else if (c == endQuoteChar) { + inQuotes = !inQuotes; + if (retainQuotes) { + sb.append(c); + } + } else if (c == delimiter && !inQuotes) { + String s = sb.toString(); + if (trimTokens) { + s = s.trim(); + } + + tokens.add(s); + sb = new StringBuilder(); + } else { + sb.append(c); + } + } + + String s = sb.toString(); + if (trimTokens) { + s = s.trim(); + } + + tokens.add(s); + return (String[])tokens.toArray(new String[tokens.size()]); + } + } + + public static String join(Iterator iterator, String separator) { + String empty = ""; + if (iterator == null) { + return null; + } else if (!iterator.hasNext()) { + return ""; + } else { + Object first = iterator.next(); + if (!iterator.hasNext()) { + return first == null ? "" : first.toString(); + } else { + StringBuilder buf = new StringBuilder(256); + if (first != null) { + buf.append(first); + } + + while(iterator.hasNext()) { + if (separator != null) { + buf.append(separator); + } + + Object obj = iterator.next(); + if (obj != null) { + buf.append(obj); + } + } + + return buf.toString(); + } + } + } + + public static Set splitToSet(String delimited, String separator) { + if (delimited != null && separator != null) { + String[] split = split(delimited, separator.charAt(0)); + return asSet(split); + } else { + return null; + } + } + + public static String uppercaseFirstChar(String in) { + if (in != null && in.length() != 0) { + int length = in.length(); + StringBuilder sb = new StringBuilder(length); + sb.append(Character.toUpperCase(in.charAt(0))); + if (length > 1) { + String remaining = in.substring(1); + sb.append(remaining); + } + + return sb.toString(); + } else { + return in; + } + } + + private static Set asSet(E... elements) { + if (elements != null && elements.length != 0) { + if (elements.length == 1) { + return Collections.singleton(elements[0]); + } else { + LinkedHashSet set = new LinkedHashSet(elements.length * 4 / 3 + 1); + Collections.addAll(set, elements); + return set; + } + } else { + return Collections.emptySet(); + } + } +} + diff --git a/core/test/net/oschina/j2cache/CacheChannelTest.java b/core/test/net/oschina/j2cache/CacheChannelTest.java index 561818ba1530cacefb56a54a3260b1471c6036ba..444ddacd3769aab29d7626f46baec730ef8bb560 100644 --- a/core/test/net/oschina/j2cache/CacheChannelTest.java +++ b/core/test/net/oschina/j2cache/CacheChannelTest.java @@ -81,8 +81,8 @@ public class CacheChannelTest { String region = "Users"; String key = "CaffeineNeverExpire"; channel.set(region,key,"OSChina.net"); - assertTrue(CacheProviderHolder.getLevel1Cache(region).keys().contains(key)); - assertTrue(CacheProviderHolder.getLevel2Cache(region).keys().contains(key)); + //assertTrue(CacheProviderHolder.getLevel1Cache(region).keys().contains(key)); + //assertTrue(CacheProviderHolder.getLevel2Cache(region).keys().contains(key)); assertTrue(channel.exists(region, key)); } diff --git a/core/src/net/oschina/j2cache/ExpiredTester.java b/core/test/net/oschina/j2cache/ExpiredTester.java similarity index 100% rename from core/src/net/oschina/j2cache/ExpiredTester.java rename to core/test/net/oschina/j2cache/ExpiredTester.java diff --git a/core/test/net/oschina/j2cache/MultiChannelTester.java b/core/test/net/oschina/j2cache/MultiChannelTester.java new file mode 100644 index 0000000000000000000000000000000000000000..a23d02b3c26ab0ec9a5e0a1cb2cbec503683f8c4 --- /dev/null +++ b/core/test/net/oschina/j2cache/MultiChannelTester.java @@ -0,0 +1,33 @@ +package net.oschina.j2cache; + +/** + * 测试一个应用里多个 CacheChannel 实例 + */ +public class MultiChannelTester { + + public static void main( String[] args ) + { + try { + + J2CacheConfig config_admin = J2CacheConfig.initFromConfig("/j2cache.properties"); + J2CacheConfig config_service = J2CacheConfig.initFromConfig("/j2cache2.properties"); + + config_admin.dump(System.out); + + System.out.println("---------------------------------------------"); + + config_service.dump(System.out); + + CacheChannel channel_admin = J2CacheBuilder.init(config_admin).getChannel(); + CacheChannel channel_service = J2CacheBuilder.init(config_service).getChannel(); + + channel_admin.set("test-admin", "test-key-admin", "test-value-admin"); + channel_service.set("test-service", "test-key-service", "test-value-service"); + + } catch (Exception e) { + e.printStackTrace(); + } + + System.exit(0); + } +} diff --git a/core/src/net/oschina/j2cache/MultiThreadTester.java b/core/test/net/oschina/j2cache/MultiThreadTester.java similarity index 100% rename from core/src/net/oschina/j2cache/MultiThreadTester.java rename to core/test/net/oschina/j2cache/MultiThreadTester.java diff --git a/core/test/net/oschina/j2cache/PatternMatcherTest.java b/core/test/net/oschina/j2cache/PatternMatcherTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4aa0582f371cb3e32016822819e1abc1f9194ba6 --- /dev/null +++ b/core/test/net/oschina/j2cache/PatternMatcherTest.java @@ -0,0 +1,14 @@ +package net.oschina.j2cache; + +import net.oschina.j2cache.util.AntPathMatcher; +import net.oschina.j2cache.util.PatternMatcher; + +public class PatternMatcherTest { + + public static void main(String[] args) { + PatternMatcher matcher = new AntPathMatcher(); + System.out.println(matcher.matches("abc_*","abc_sdfsd")); + System.out.println(matcher.matches("asf_*","dsffsd")); + System.out.println(matcher.matches("default","default")); + } +} diff --git a/modules/hibernate3/pom.xml b/modules/hibernate3/pom.xml index a157d259629a6e1003cfa909dc20134703b448d4..a6e9f892aee501b6941e180b57986766bbf62cc9 100755 --- a/modules/hibernate3/pom.xml +++ b/modules/hibernate3/pom.xml @@ -3,7 +3,7 @@ net.oschina.j2cache j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml @@ -19,8 +19,7 @@ net.oschina.j2cache j2cache-core - ${j2cache-version} - compile + provided org.hibernate @@ -32,4 +31,4 @@ J2Cache - hibernate3 - \ No newline at end of file + diff --git a/modules/hibernate4/pom.xml b/modules/hibernate4/pom.xml index 45daf999d5d1b0faf2bd9870cf7545656fbdaf43..9e0de703dd61cfd3008eb0589ed03d80f91c4dbe 100755 --- a/modules/hibernate4/pom.xml +++ b/modules/hibernate4/pom.xml @@ -3,7 +3,7 @@ net.oschina.j2cache j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml @@ -20,8 +20,7 @@ net.oschina.j2cache j2cache-core - ${j2cache-version} - compile + provided org.hibernate @@ -64,4 +63,4 @@ - \ No newline at end of file + diff --git a/modules/hibernate4/src/net/oschina/j2cache/hibernate4/J2CacheCacheRegion.java b/modules/hibernate4/src/net/oschina/j2cache/hibernate4/J2CacheCacheRegion.java index 5afa7506bad940cab9a0981719108735271b7e70..3e0d480b405bb2356289f7ade2bead118c50ae5d 100644 --- a/modules/hibernate4/src/net/oschina/j2cache/hibernate4/J2CacheCacheRegion.java +++ b/modules/hibernate4/src/net/oschina/j2cache/hibernate4/J2CacheCacheRegion.java @@ -17,10 +17,6 @@ package net.oschina.j2cache.hibernate4; import net.oschina.j2cache.CacheChannel; import net.oschina.j2cache.CacheObject; -import org.hibernate.HibernateException; - -import java.io.IOException; -import java.io.Serializable; public class J2CacheCacheRegion implements CacheRegion { @@ -44,17 +40,17 @@ public class J2CacheCacheRegion implements CacheRegion { @Override public CacheObject get(Object key) { - return this.cacheChannel.get(this.region, (String) key); + return this.cacheChannel.get(this.region, key.toString()); } @Override public void put(Object key, Object value) { - this.cacheChannel.set(this.region, (String) key, value); + this.cacheChannel.set(this.region, key.toString(), value); } @Override public void evict(Object key) { - this.cacheChannel.evict(this.region, (String)key); + this.cacheChannel.evict(this.region, key.toString()); } public Iterable keys() { diff --git a/modules/hibernate5/pom.xml b/modules/hibernate5/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8d58a369ac3eb7eea0c144cdaf83b6f1ebe9f8d --- /dev/null +++ b/modules/hibernate5/pom.xml @@ -0,0 +1,108 @@ + + + + + j2cache + net.oschina.j2cache + 2.8.0-release + ../../pom.xml + + + 4.0.0 + + j2cache-hibernate5 + jar + J2Cache - hibernate5 + + + 5.2.17.Final + 5.0.8.RELEASE + + + + + net.oschina.j2cache + j2cache-core + provided + + + org.hibernate + hibernate-ehcache + ${hibernate.version} + compile + + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework + spring-web + ${spring.version} + test + + + org.springframework + spring-context-support + ${spring.version} + test + + + org.springframework + spring-orm + ${spring.version} + test + + + org.springframework + spring-aop + ${spring.version} + test + + + org.springframework + spring-aspects + ${spring.version} + test + + + com.cloudhopper.proxool + proxool + 0.9.1 + test + + + log4j + log4j + 1.2.17 + test + + + mysql + mysql-connector-java + 5.1.46 + test + + + + org.ehcache + ehcache + 3.4.0 + test + + + + + src + test/src + + diff --git a/modules/hibernate5/readme.md b/modules/hibernate5/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..3b79c71dabdb0f1d14d9fa9610c9d82440d283e8 --- /dev/null +++ b/modules/hibernate5/readme.md @@ -0,0 +1,53 @@ +# Hibernate 5 支持模块 + +基于 Hibernate 5.2.17 开发,感谢 [@tandy](https://gitee.com/tandy) + +Maven: + +```xml + + net.oschina.j2cache + j2cache-hibernate5 + 1.0.0-beta1 + +``` +使用说明: + +1、XML文件配置 + +```xml + + + + ...省略其他配置... + org.springframework.orm.hibernate5.SpringSessionContext + net.oschina.j2cache.hibernate5.J2CacheRegionFactory + true + true + + + ...省略其他配置... + +``` + +2、properties文件配置 +```xml + spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext + spring.jpa.properties.hibernate.cache.region.factory_class=net.oschina.j2cache.hibernate5.J2CacheRegionFactory + spring.jpa.properties.hibernate.cache.use_second_level_cache=true + spring.jpa.properties.hibernate.cache.use_query_cache=true +``` + +3、yml文件配置 +```xml + spring: + jpa: + properties: + hibernate: + current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext + cache: + use_second_level_cache: true + use_query_cache: true + region: + factory_class: net.oschina.j2cache.hibernate5.J2CacheRegionFactory +``` \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/AbstractJ2CacheRegionFactory.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/AbstractJ2CacheRegionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7ac98493205ed75d8e130cf6c3e96c1fd6823c2c --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/AbstractJ2CacheRegionFactory.java @@ -0,0 +1,89 @@ +package net.oschina.j2cache.hibernate5; + +import net.oschina.j2cache.CacheChannel; +import net.oschina.j2cache.hibernate5.strategy.NonstopAccessStrategyFactory; +import net.oschina.j2cache.hibernate5.regions.*; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactoryImpl; +import net.oschina.j2cache.hibernate5.util.Timestamper; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.*; +import org.hibernate.cache.spi.access.AccessType; + +import java.util.Properties; + +public abstract class AbstractJ2CacheRegionFactory implements RegionFactory { + + protected SessionFactoryOptions settings; + + protected CacheChannel channel; + + protected final J2CacheAccessStrategyFactory accessStrategyFactory = new NonstopAccessStrategyFactory(new J2CacheAccessStrategyFactoryImpl()); + + @Override + public boolean isMinimalPutsEnabledByDefault() { + return true; + } + + @Override + public long nextTimestamp() { + return Timestamper.next(); + } + + @Override + public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + return new J2CacheEntityRegion(accessStrategyFactory, getCache( regionName ), settings, metadata, properties ); + } + + @Override + public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) + throws CacheException { + return new J2CacheNaturalIdRegion( + accessStrategyFactory, + getCache( regionName ), + settings, + metadata, + properties + ); + } + + @Override + public CollectionRegion buildCollectionRegion( + String regionName, + Properties properties, + CacheDataDescription metadata) + throws CacheException { + return new J2CacheCollectionRegion( + accessStrategyFactory, + getCache( regionName ), + settings, + metadata, + properties + ); + } + + @Override + public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { + return new J2CacheQueryResultsRegion( accessStrategyFactory, getCache( regionName ), properties ); + } + + @Override + public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException { + return new J2CacheTimestampsRegion( accessStrategyFactory, getCache( regionName ), properties ); + } + + @Override + public AccessType getDefaultAccessType() { + return AccessType.READ_WRITE; + } + + public void setChannel(CacheChannel channel) { + this.channel = channel; + } + + private CacheRegion getCache(String name) throws CacheException { + return new J2CacheCacheRegion(channel,name); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/CacheRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/CacheRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..d93ef2fcdd9370d97557aabadbb0dd92c09125ee --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/CacheRegion.java @@ -0,0 +1,18 @@ +package net.oschina.j2cache.hibernate5; + +import net.oschina.j2cache.CacheObject; + +public interface CacheRegion { + + String getName(); + + void clear(); + + CacheObject get(Object key); + + void put(Object key, Object value); + + void evict(Object key); + + Iterable keys(); +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheCacheRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheCacheRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..917bc86c081d325eba45f4ca937a6b49fc20c1f6 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheCacheRegion.java @@ -0,0 +1,44 @@ +package net.oschina.j2cache.hibernate5; + +import net.oschina.j2cache.CacheChannel; +import net.oschina.j2cache.CacheObject; + +public class J2CacheCacheRegion implements CacheRegion { + + private CacheChannel cacheChannel; + private String region; + + public J2CacheCacheRegion(CacheChannel channel, String region) { + this.cacheChannel = channel; + this.region = region; + } + + @Override + public String getName() { + return this.region; + } + + @Override + public void clear() { + this.cacheChannel.clear(this.region); + } + + @Override + public CacheObject get(Object key) { + return this.cacheChannel.get(this.region, key.toString()); + } + + @Override + public void put(Object key, Object value) { + this.cacheChannel.set(this.region, key.toString(), value); + } + + @Override + public void evict(Object key) { + this.cacheChannel.evict(this.region, key.toString()); + } + + public Iterable keys() { + return this.cacheChannel.keys(this.region); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactory.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..ffd5222dbb3d35413eb62d18f70e5491df2b0fd2 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactory.java @@ -0,0 +1,39 @@ +package net.oschina.j2cache.hibernate5; + +import net.oschina.j2cache.J2Cache; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; + +import java.util.Map; +import java.util.Properties; + +public class J2CacheRegionFactory extends AbstractJ2CacheRegionFactory { + + private static final String SPRING_CACHEMANAGER = "hibernate.cache.spring.cache_manager"; + + private static final String DEFAULT_SPRING_CACHEMANAGER = "cacheManager"; + + @SuppressWarnings("UnusedDeclaration") + public J2CacheRegionFactory() { + } + + @SuppressWarnings("UnusedDeclaration") + public J2CacheRegionFactory(Properties prop) { + super(); + } + + @Override + public void start(SessionFactoryOptions settings, Properties properties) throws CacheException { + this.settings = settings; + if (this.channel == null) { + this.channel = J2Cache.getChannel(); + } + } + + @Override + public void stop() { + if (channel != null) { + channel.close(); + } + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..28f374476011ea86bb26193b21432b8bfff7c3d4 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2015-2017. + *

+ * 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 net.oschina.j2cache.hibernate5.log; + +import org.hibernate.internal.CoreMessageLogger; +import org.jboss.logging.LogMessage; +import org.jboss.logging.Logger.Level; +import org.jboss.logging.Message; +import org.jboss.logging.MessageLogger; + +@MessageLogger(projectCode = "HHH") +public interface J2CacheMessageLogger extends CoreMessageLogger { + + + @LogMessage(level = Level.WARN) + @Message( + value = "Attempt to restart an already started J2CacheRegionFactory. Use sessionFactory.close() between " + + "repeated calls to buildSessionFactory. Using previously created J2CacheRegionFactory. If this " + + "behaviour is required, consider using org.hibernate.cache.j2cache.SingletonJ2CacheRegionFactory.", + id = 20001 + ) + void attemptToRestartAlreadyStartedJ2CacheProvider(); + + /** + * Log a message (WARN) about inability to find configuration file + * + * @param name The name of the configuration file + */ + @LogMessage(level = Level.WARN) + @Message(value = "Could not find configuration [%s]; using defaults.", id = 20002) + void unableToFindConfiguration(String name); + + /** + * Log a message (WARN) about inability to find named cache configuration + * + * @param name The name of the cache configuration + */ + @LogMessage(level = Level.WARN) + @Message(value = "Could not find a specific J2Cache configuration for cache named [%s]; using defaults.", id = 20003) + void unableToFindJ2CacheConfiguration(String name); + + /** + * Logs a message about not being able to resolve the configuration by resource name. + * + * @param configurationResourceName The resource name we attempted to resolve + */ + @LogMessage(level = Level.WARN) + @Message( + value = "A configurationResourceName was set to %s but the resource could not be loaded from the classpath. " + + "J2Cache will configure itself using defaults.", + id = 20004 + ) + void unableToLoadConfiguration(String configurationResourceName); + + /** + * Logs a message (WARN) about attempt to use an incompatible + */ + @LogMessage(level = Level.WARN) + @Message( + value = "The default cache value mode for this J2Cache configuration is \"identity\". " + + "This is incompatible with clustered Hibernate caching - the value mode has therefore been " + + "switched to \"serialization\"", + id = 20005 + ) + void incompatibleCacheValueMode(); + + /** + * Logs a message (WARN) about attempt to use an incompatible + * + * @param cacheName The name of the cache whose config attempted to specify value mode. + */ + @LogMessage(level = Level.WARN) + @Message(value = "The value mode for the cache[%s] is \"identity\". This is incompatible with clustered Hibernate caching - " + + "the value mode has therefore been switched to \"serialization\"", id = 20006) + void incompatibleCacheValueModePerCache(String cacheName); + + /** + * Log a message (WARN) about an attempt to specify read-only caching for a mutable entity + * + * @param entityName The name of the entity + */ + @LogMessage(level = Level.WARN) + @Message(value = "read-only cache configured for mutable entity [%s]", id = 20007) + void readOnlyCacheConfiguredForMutableEntity(String entityName); + + /** + * Log a message (WARN) about expiry of soft-locked region. + * + * @param regionName The region name + * @param key The cache key + * @param lock The lock + */ + @LogMessage(level = Level.WARN) + @Message( + value = "Cache[%s] Key[%s] Lockable[%s]\n" + + "A soft-locked cache entry was expired by the underlying J2Cache. If this happens regularly you " + + "should consider increasing the cache timeouts and/or capacity limits", + id = 20008 + ) + void softLockedCacheExpired(String regionName, Object key, String lock); + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger_$logger.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger_$logger.java new file mode 100644 index 0000000000000000000000000000000000000000..9d622713ae76c3b1d588f6d927cf8221a793bbe0 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/log/J2CacheMessageLogger_$logger.java @@ -0,0 +1,3522 @@ +/** + * Copyright (c) 2015-2017. + *

+ * 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 net.oschina.j2cache.hibernate5.log; + +import org.hibernate.HibernateException; +import org.hibernate.LockMode; +import org.hibernate.cache.CacheException; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; +import org.hibernate.engine.jndi.JndiException; +import org.hibernate.engine.jndi.JndiNameException; +import org.hibernate.engine.loading.internal.CollectionLoadContext; +import org.hibernate.engine.loading.internal.EntityLoadContext; +import org.hibernate.engine.spi.CollectionKey; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.id.IntegralDataTypeHolder; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.type.BasicType; +import org.hibernate.type.SerializationException; +import org.hibernate.type.Type; +import org.jboss.logging.BasicLogger; +import org.jboss.logging.DelegatingBasicLogger; +import org.jboss.logging.Logger; + +import javax.annotation.Generated; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Method; +import java.net.URL; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.util.*; + +@Generated(value = "org.jboss.logging.processor.generator.model.MessageLoggerImplementor", date = "2015-01-06T12:13:01-0800") +public class J2CacheMessageLogger_$logger extends DelegatingBasicLogger implements Serializable, J2CacheMessageLogger, CoreMessageLogger, BasicLogger { + + private static final long serialVersionUID = 1L; + private static final String FQCN = J2CacheMessageLogger_$logger.class.getName(); + private static final Locale LOCALE; + private static final String attemptToRestartAlreadyStartedJ2CacheProvider = "HHH020001: Attempt to restart an already started J2CacheRegionFactory. Use sessionFactory.close() between repeated calls to buildSessionFactory. Using previously created J2CacheRegionFactory. If this behaviour is required, consider using org.hibernate.cache.ehcache.SingletonJ2CacheRegionFactory."; + private static final String unableToFindConfiguration = "HHH020002: Could not find configuration [%s]; using defaults."; + private static final String unableToFindJ2CacheConfiguration = "HHH020003: Could not find a specific ehcache configuration for cache named [%s]; using defaults."; + private static final String unableToLoadConfiguration = "HHH020004: A configurationResourceName was set to %s but the resource could not be loaded from the classpath. Ehcache will configure itself using defaults."; + private static final String incompatibleCacheValueMode = "HHH020005: The default cache value mode for this Ehcache configuration is \"identity\". This is incompatible with clustered Hibernate caching - the value mode has therefore been switched to \"serialization\""; + private static final String incompatibleCacheValueModePerCache = "HHH020006: The value mode for the cache[%s] is \"identity\". This is incompatible with clustered Hibernate caching - the value mode has therefore been switched to \"serialization\""; + private static final String readOnlyCacheConfiguredForMutableEntity = "HHH020007: read-only cache configured for mutable entity [%s]"; + private static final String softLockedCacheExpired = "HHH020008: Cache[%s] Key[%s] Lockable[%s]\nA soft-locked cache entry was expired by the underlying Ehcache. If this happens regularly you should consider increasing the cache timeouts and/or capacity limits"; + private static final String alreadySessionBound = "HHH000002: Already session bound on call to bind(); make sure you clean up your sessions!"; + private static final String autoCommitMode = "HHH000006: Autocommit mode: %s"; + private static final String autoFlushWillNotWork = "HHH000008: JTASessionContext being used with JDBC transactions; auto-flush will not operate correctly with getCurrentSession()"; + private static final String batchContainedStatementsOnRelease = "HHH000010: On release of batch it still contained JDBC statements"; + private static final String bytecodeProvider = "HHH000021: Bytecode provider name : %s"; + private static final String c3p0ProviderClassNotFound = "HHH000022: c3p0 properties were encountered, but the %s provider class was not found on the classpath; these properties are going to be ignored."; + private static final String cachedFileNotFound = "HHH000023: I/O reported cached file could not be found : %s : %s"; + private static final String cacheProvider = "HHH000024: Cache provider: %s"; + private static final String callingJoinTransactionOnNonJtaEntityManager = "HHH000027: Calling joinTransaction() on a non JTA EntityManager"; + private static final String closing = "HHH000031: Closing"; + private static final String collectionsFetched = "HHH000032: Collections fetched (minimize this): %s"; + private static final String collectionsLoaded = "HHH000033: Collections loaded: %s"; + private static final String collectionsRecreated = "HHH000034: Collections recreated: %s"; + private static final String collectionsRemoved = "HHH000035: Collections removed: %s"; + private static final String collectionsUpdated = "HHH000036: Collections updated: %s"; + private static final String columns = "HHH000037: Columns: %s"; + private static final String compositeIdClassDoesNotOverrideEquals = "HHH000038: Composite-id class does not override equals(): %s"; + private static final String compositeIdClassDoesNotOverrideHashCode = "HHH000039: Composite-id class does not override hashCode(): %s"; + private static final String configurationResource = "HHH000040: Configuration resource: %s"; + private static final String configuredSessionFactory = "HHH000041: Configured SessionFactory: %s"; + private static final String configuringFromFile = "HHH000042: Configuring from file: %s"; + private static final String configuringFromResource = "HHH000043: Configuring from resource: %s"; + private static final String configuringFromUrl = "HHH000044: Configuring from URL: %s"; + private static final String configuringFromXmlDocument = "HHH000045: Configuring from XML document"; + private static final String connectionsObtained = "HHH000048: Connections obtained: %s"; + private static final String containerProvidingNullPersistenceUnitRootUrl = "HHH000050: Container is providing a null PersistenceUnitRootUrl: discovery impossible"; + private static final String containsJoinFetchedCollection = "HHH000051: Ignoring bag join fetch [%s] due to prior collection join fetch"; + private static final String creatingSubcontextInfo = "HHH000053: Creating subcontext: %s"; + private static final String definingFlushBeforeCompletionIgnoredInHem = "HHH000059: Defining %s=true ignored in HEM"; + private static final String deprecatedForceDescriminatorAnnotation = "HHH000062: @ForceDiscriminator is deprecated use @DiscriminatorOptions instead."; + private static final String deprecatedOracle9Dialect = "HHH000063: The Oracle9Dialect dialect has been deprecated; use either Oracle9iDialect or Oracle10gDialect instead"; + private static final String deprecatedOracleDialect = "HHH000064: The OracleDialect dialect has been deprecated; use Oracle8iDialect instead"; + private static final String deprecatedUuidGenerator = "HHH000065: DEPRECATED : use [%s] instead with custom [%s] implementation"; + private static final String disallowingInsertStatementComment = "HHH000067: Disallowing insert statement comment for select-identity due to Oracle driver bug"; + private static final String duplicateGeneratorName = "HHH000069: Duplicate generator name %s"; + private static final String duplicateGeneratorTable = "HHH000070: Duplicate generator table: %s"; + private static final String duplicateImport = "HHH000071: Duplicate import: %s -> %s"; + private static final String duplicateJoins = "HHH000072: Duplicate joins for class: %s"; + private static final String duplicateListener = "HHH000073: entity-listener duplication, first event definition will be used: %s"; + private static final String duplicateMetadata = "HHH000074: Found more than one , subsequent ignored"; + private static final String entitiesDeleted = "HHH000076: Entities deleted: %s"; + private static final String entitiesFetched = "HHH000077: Entities fetched (minimize this): %s"; + private static final String entitiesInserted = "HHH000078: Entities inserted: %s"; + private static final String entitiesLoaded = "HHH000079: Entities loaded: %s"; + private static final String entitiesUpdated = "HHH000080: Entities updated: %s"; + private static final String entityAnnotationOnNonRoot = "HHH000081: @org.hibernate.annotations.Entity used on a non root entity: ignored for %s"; + private static final String entityManagerClosedBySomeoneElse = "HHH000082: Entity Manager closed by someone else (%s must not be used)"; + private static final String entityMappedAsNonAbstract = "HHH000084: Entity [%s] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names"; + private static final String exceptionHeaderFound = "HHH000085: %s %s found"; + private static final String exceptionHeaderNotFound = "HHH000086: %s No %s found"; + private static final String exceptionInAfterTransactionCompletionInterceptor = "HHH000087: Exception in interceptor afterTransactionCompletion()"; + private static final String exceptionInBeforeTransactionCompletionInterceptor = "HHH000088: Exception in interceptor beforeTransactionCompletion()"; + private static final String exceptionInSubResolver = "HHH000089: Sub-resolver threw unexpected exception, continuing to next : %s"; + private static final String expectedType = "HHH000091: Expected type: %s, actual value: %s"; + private static final String expired = "HHH000092: An item was expired by the cache while it was locked (increase your cache timeout): %s"; + private static final String factoryBoundToJndiName = "HHH000094: Bound factory to JNDI name: %s"; + private static final String factoryJndiRename = "HHH000096: A factory was renamed from [%s] to [%s] in JNDI"; + private static final String factoryUnboundFromJndiName = "HHH000097: Unbound factory from JNDI name: %s"; + private static final String factoryUnboundFromName = "HHH000098: A factory was unbound from name: %s"; + private static final String failed = "HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): %s"; + private static final String failSafeCollectionsCleanup = "HHH000100: Fail-safe cleanup (collections) : %s"; + private static final String failSafeEntitiesCleanup = "HHH000101: Fail-safe cleanup (entities) : %s"; + private static final String fetchingDatabaseMetadata = "HHH000102: Fetching database metadata"; + private static final String firstOrMaxResultsSpecifiedWithCollectionFetch = "HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!"; + private static final String flushes = "HHH000105: Flushes: %s"; + private static final String forcingContainerResourceCleanup = "HHH000106: Forcing container resource cleanup on transaction completion"; + private static final String forcingTableUse = "HHH000107: Forcing table use for sequence-style generator due to pooled optimizer selection where db does not support pooled sequences"; + private static final String foreignKeys = "HHH000108: Foreign keys: %s"; + private static final String foundMappingDocument = "HHH000109: Found mapping document in jar: %s"; + private static final String gettersOfLazyClassesCannotBeFinal = "HHH000112: Getters of lazy classes cannot be final: %s.%s"; + private static final String guidGenerated = "HHH000113: GUID identifier generated: %s"; + private static final String handlingTransientEntity = "HHH000114: Handling transient entity in delete processing"; + private static final String hibernateConnectionPoolSize = "HHH000115: Hibernate connection pool size: %s (min=%s)"; + private static final String honoringOptimizerSetting = "HHH000116: Config specified explicit optimizer of [%s], but [%s=%s]; using optimizer [%s] increment default of [%s]."; + private static final String hql = "HHH000117: HQL: %s, time: %sms, rows: %s"; + private static final String hsqldbSupportsOnlyReadCommittedIsolation = "HHH000118: HSQLDB supports only READ_UNCOMMITTED isolation"; + private static final String hydratingEntitiesCount = "HHH000119: On EntityLoadContext#clear, hydratingEntities contained [%s] entries"; + private static final String ignoringTableGeneratorConstraints = "HHH000120: Ignoring unique constraints specified on table generator [%s]"; + private static final String ignoringUnrecognizedQueryHint = "HHH000121: Ignoring unrecognized query hint [%s]"; + private static final String illegalPropertyGetterArgument = "HHH000122: IllegalArgumentException in class: %s, getter method of property: %s"; + private static final String illegalPropertySetterArgument = "HHH000123: IllegalArgumentException in class: %s, setter method of property: %s"; + private static final String immutableAnnotationOnNonRoot = "HHH000124: @Immutable used on a non root entity: ignored for %s"; + private static final String incompleteMappingMetadataCacheProcessing = "HHH000125: Mapping metadata cache was not completely processed"; + private static final String indexes = "HHH000126: Indexes: %s"; + private static final String couldNotBindJndiListener = "HHH000127: Could not bind JNDI listener"; + private static final String instantiatingExplicitConnectionProvider = "HHH000130: Instantiating explicit connection provider: %s"; + private static final String invalidArrayElementType = "HHH000132: Array element type error\n%s"; + private static final String invalidDiscriminatorAnnotation = "HHH000133: Discriminator column has to be defined in the root entity, it will be ignored in subclass: %s"; + private static final String invalidEditOfReadOnlyItem = "HHH000134: Application attempted to edit read only item: %s"; + private static final String invalidJndiName = "HHH000135: Invalid JNDI name: %s"; + private static final String invalidOnDeleteAnnotation = "HHH000136: Inapropriate use of @OnDelete on entity, annotation ignored: %s"; + private static final String invalidPrimaryKeyJoinColumnAnnotation = "HHH000137: Root entity should not hold a PrimaryKeyJoinColum(s), will be ignored: %s"; + private static final String invalidSubStrategy = "HHH000138: Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: %s"; + private static final String invalidTableAnnotation = "HHH000139: Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: %s"; + private static final String jaccContextId = "HHH000140: JACC contextID: %s"; + private static final String JavaSqlTypesMappedSameCodeMultipleTimes = "HHH000141: java.sql.Types mapped the same code [%s] multiple times; was [%s]; now [%s]"; + private static final String bytecodeEnhancementFailed = "HHH000142: Bytecode enhancement failed: %s"; + private static final String jdbcAutoCommitFalseBreaksEjb3Spec = "HHH000144: %s = false breaks the EJB3 specification"; + private static final String jdbcRollbackFailed = "HHH000151: JDBC rollback failed"; + private static final String jndiInitialContextProperties = "HHH000154: JNDI InitialContext properties:%s"; + private static final String jndiNameDoesNotHandleSessionFactoryReference = "HHH000155: JNDI name %s does not handle a session factory reference"; + private static final String lazyPropertyFetchingAvailable = "HHH000157: Lazy property fetching available for: %s"; + private static final String loadingCollectionKeyNotFound = "HHH000159: In CollectionLoadContext#endLoadingCollections, localLoadingCollectionKeys contained [%s], but no LoadingCollectionEntry was found in loadContexts"; + private static final String localLoadingCollectionKeysCount = "HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [%s] entries"; + private static final String loggingStatistics = "HHH000161: Logging statistics...."; + private static final String logicalConnectionClosed = "HHH000162: *** Logical connection closed ***"; + private static final String logicalConnectionReleasingPhysicalConnection = "HHH000163: Logical connection releasing its physical connection"; + private static final String maxQueryTime = "HHH000173: Max query time: %sms"; + private static final String missingArguments = "HHH000174: Function template anticipated %s arguments, but %s arguments encountered"; + private static final String missingEntityAnnotation = "HHH000175: Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity (most likely a user error): %s"; + private static final String namedQueryError = "HHH000177: Error in named query: %s"; + private static final String namingExceptionAccessingFactory = "HHH000178: Naming exception occurred accessing factory: %s"; + private static final String narrowingProxy = "HHH000179: Narrowing proxy to %s - this operation breaks =="; + private static final String needsLimit = "HHH000180: FirstResult/maxResults specified on polymorphic query; applying in memory!"; + private static final String noAppropriateConnectionProvider = "HHH000181: No appropriate connection provider encountered, assuming application will be supplying connections"; + private static final String noDefaultConstructor = "HHH000182: No default (no-argument) constructor for class: %s (class must be instantiated by Interceptor)"; + private static final String noPersistentClassesFound = "HHH000183: no persistent classes found for query class: %s"; + private static final String noSessionFactoryWithJndiName = "HHH000184: No session factory with JNDI name %s"; + private static final String optimisticLockFailures = "HHH000187: Optimistic lock failures: %s"; + private static final String orderByAnnotationIndexedCollection = "HHH000189: @OrderBy not allowed for an indexed collection, annotation ignored."; + private static final String overridingTransactionStrategyDangerous = "HHH000193: Overriding %s is dangerous, this might break the EJB3 specification implementation"; + private static final String packageNotFound = "HHH000194: Package not found or wo package-info.java: %s"; + private static final String parsingXmlError = "HHH000196: Error parsing XML (%s) : %s"; + private static final String parsingXmlErrorForFile = "HHH000197: Error parsing XML: %s(%s) %s"; + private static final String parsingXmlWarning = "HHH000198: Warning parsing XML (%s) : %s"; + private static final String parsingXmlWarningForFile = "HHH000199: Warning parsing XML: %s(%s) %s"; + private static final String persistenceProviderCallerDoesNotImplementEjb3SpecCorrectly = "HHH000200: Persistence provider caller does not implement the EJB3 spec correctly.PersistenceUnitInfo.getNewTempClassLoader() is null."; + private static final String pooledOptimizerReportedInitialValue = "HHH000201: Pooled optimizer source reported [%s] as the initial value; use of 1 or greater highly recommended"; + private static final String preparedStatementAlreadyInBatch = "HHH000202: PreparedStatement was already in the batch, [%s]."; + private static final String processEqualityExpression = "HHH000203: processEqualityExpression() : No expression to process!"; + private static final String processingPersistenceUnitInfoName = "HHH000204: Processing PersistenceUnitInfo [\n\tname: %s\n\t...]"; + private static final String propertiesLoaded = "HHH000205: Loaded properties from resource hibernate.properties: %s"; + private static final String propertiesNotFound = "HHH000206: hibernate.properties not found"; + private static final String propertyNotFound = "HHH000207: Property %s not found in class but described in (possible typo error)"; + private static final String proxoolProviderClassNotFound = "HHH000209: proxool properties were encountered, but the %s provider class was not found on the classpath; these properties are going to be ignored."; + private static final String queriesExecuted = "HHH000210: Queries executed to database: %s"; + private static final String queryCacheHits = "HHH000213: Query cache hits: %s"; + private static final String queryCacheMisses = "HHH000214: Query cache misses: %s"; + private static final String queryCachePuts = "HHH000215: Query cache puts: %s"; + private static final String rdmsOs2200Dialect = "HHH000218: RDMSOS2200Dialect version: 1.0"; + private static final String readingCachedMappings = "HHH000219: Reading mappings from cache file: %s"; + private static final String readingMappingsFromFile = "HHH000220: Reading mappings from file: %s"; + private static final String readingMappingsFromResource = "HHH000221: Reading mappings from resource: %s"; + private static final String readOnlyCacheConfiguredForMutableCollection = "HHH000222: read-only cache configured for mutable collection [%s]"; + private static final String recognizedObsoleteHibernateNamespace = "HHH000223: Recognized obsolete hibernate namespace %s. Use namespace %s instead. Refer to Hibernate 3.6 Migration Guide!"; + private static final String renamedProperty = "HHH000225: Property [%s] has been renamed to [%s]; update your properties appropriately"; + private static final String requiredDifferentProvider = "HHH000226: Required a different provider: %s"; + private static final String runningHbm2ddlSchemaExport = "HHH000227: Running hbm2ddl schema export"; + private static final String runningHbm2ddlSchemaUpdate = "HHH000228: Running hbm2ddl schema update"; + private static final String runningSchemaValidator = "HHH000229: Running schema validator"; + private static final String schemaExportComplete = "HHH000230: Schema export complete"; + private static final String schemaExportUnsuccessful = "HHH000231: Schema export unsuccessful"; + private static final String schemaUpdateComplete = "HHH000232: Schema update complete"; + private static final String scopingTypesToSessionFactoryAfterAlreadyScoped = "HHH000233: Scoping types to session factory %s after already scoped %s"; + private static final String searchingForMappingDocuments = "HHH000235: Searching for mapping documents in jar: %s"; + private static final String secondLevelCacheHits = "HHH000237: Second level cache hits: %s"; + private static final String secondLevelCacheMisses = "HHH000238: Second level cache misses: %s"; + private static final String secondLevelCachePuts = "HHH000239: Second level cache puts: %s"; + private static final String serviceProperties = "HHH000240: Service properties: %s"; + private static final String sessionsClosed = "HHH000241: Sessions closed: %s"; + private static final String sessionsOpened = "HHH000242: Sessions opened: %s"; + private static final String settersOfLazyClassesCannotBeFinal = "HHH000243: Setters of lazy classes cannot be final: %s.%s"; + private static final String sortAnnotationIndexedCollection = "HHH000244: @Sort not allowed for an indexed collection, annotation ignored."; + private static final String splitQueries = "HHH000245: Manipulation query [%s] resulted in [%s] split queries"; + private static final String sqlWarning = "HHH000247: SQL Error: %s, SQLState: %s"; + private static final String startingQueryCache = "HHH000248: Starting query cache at region: %s"; + private static final String startingServiceAtJndiName = "HHH000249: Starting service at JNDI name: %s"; + private static final String startingUpdateTimestampsCache = "HHH000250: Starting update timestamps cache at region: %s"; + private static final String startTime = "HHH000251: Start time: %s"; + private static final String statementsClosed = "HHH000252: Statements closed: %s"; + private static final String statementsPrepared = "HHH000253: Statements prepared: %s"; + private static final String stoppingService = "HHH000255: Stopping service"; + private static final String subResolverException = "HHH000257: sub-resolver threw unexpected exception, continuing to next : %s"; + private static final String successfulTransactions = "HHH000258: Successful transactions: %s"; + private static final String synchronizationAlreadyRegistered = "HHH000259: Synchronization [%s] was already registered"; + private static final String synchronizationFailed = "HHH000260: Exception calling user Synchronization [%s] : %s"; + private static final String tableFound = "HHH000261: Table found: %s"; + private static final String tableNotFound = "HHH000262: Table not found: %s"; + private static final String multipleTablesFound = "HHH000263: More than one table found: %s"; + private static final String transactions = "HHH000266: Transactions: %s"; + private static final String transactionStartedOnNonRootSession = "HHH000267: Transaction started on non-root session"; + private static final String transactionStrategy = "HHH000268: Transaction strategy: %s"; + private static final String typeDefinedNoRegistrationKeys = "HHH000269: Type [%s] defined no registration keys; ignoring"; + private static final String typeRegistrationOverridesPrevious = "HHH000270: Type registration [%s] overrides previous : %s"; + private static final String unableToAccessEjb3Configuration = "HHH000271: Naming exception occurred accessing Ejb3Configuration"; + private static final String unableToAccessSessionFactory = "HHH000272: Error while accessing session factory with JNDI name %s"; + private static final String unableToAccessTypeInfoResultSet = "HHH000273: Error accessing type info result set : %s"; + private static final String unableToApplyConstraints = "HHH000274: Unable to apply constraints on DDL for %s"; + private static final String unableToBindEjb3ConfigurationToJndi = "HHH000276: Could not bind Ejb3Configuration to JNDI"; + private static final String unableToBindFactoryToJndi = "HHH000277: Could not bind factory to JNDI"; + private static final String unableToBindValueToParameter = "HHH000278: Could not bind value '%s' to parameter: %s; %s"; + private static final String unableToBuildEnhancementMetamodel = "HHH000279: Unable to build enhancement metamodel for %s"; + private static final String unableToBuildSessionFactoryUsingMBeanClasspath = "HHH000280: Could not build SessionFactory using the MBean classpath - will try again using client classpath: %s"; + private static final String unableToCleanUpCallableStatement = "HHH000281: Unable to clean up callable statement"; + private static final String unableToCleanUpPreparedStatement = "HHH000282: Unable to clean up prepared statement"; + private static final String unableToCleanupTemporaryIdTable = "HHH000283: Unable to cleanup temporary id table after use [%s]"; + private static final String unableToCloseConnection = "HHH000284: Error closing connection"; + private static final String unableToCloseInitialContext = "HHH000285: Error closing InitialContext [%s]"; + private static final String unableToCloseInputFiles = "HHH000286: Error closing input files: %s"; + private static final String unableToCloseInputStream = "HHH000287: Could not close input stream"; + private static final String unableToCloseInputStreamForResource = "HHH000288: Could not close input stream for %s"; + private static final String unableToCloseIterator = "HHH000289: Unable to close iterator"; + private static final String unableToCloseJar = "HHH000290: Could not close jar: %s"; + private static final String unableToCloseOutputFile = "HHH000291: Error closing output file: %s"; + private static final String unableToCloseOutputStream = "HHH000292: IOException occurred closing output stream"; + private static final String unableToCloseSession = "HHH000294: Could not close session"; + private static final String unableToCloseSessionDuringRollback = "HHH000295: Could not close session during rollback"; + private static final String unableToCloseStream = "HHH000296: IOException occurred closing stream"; + private static final String unableToCloseStreamError = "HHH000297: Could not close stream on hibernate.properties: %s"; + private static final String unableToCommitJta = "HHH000298: JTA commit failed"; + private static final String unableToCompleteSchemaUpdate = "HHH000299: Could not complete schema update"; + private static final String unableToCompleteSchemaValidation = "HHH000300: Could not complete schema validation"; + private static final String unableToConfigureSqlExceptionConverter = "HHH000301: Unable to configure SQLExceptionConverter : %s"; + private static final String unableToConstructCurrentSessionContext = "HHH000302: Unable to construct current session context [%s]"; + private static final String unableToConstructSqlExceptionConverter = "HHH000303: Unable to construct instance of specified SQLExceptionConverter : %s"; + private static final String unableToCopySystemProperties = "HHH000304: Could not copy system properties, system properties will be ignored"; + private static final String unableToCreateProxyFactory = "HHH000305: Could not create proxy factory for:%s"; + private static final String unableToCreateSchema = "HHH000306: Error creating schema "; + private static final String unableToDeserializeCache = "HHH000307: Could not deserialize cache file: %s : %s"; + private static final String unableToDestroyCache = "HHH000308: Unable to destroy cache: %s"; + private static final String unableToDestroyQueryCache = "HHH000309: Unable to destroy query cache: %s: %s"; + private static final String unableToDestroyUpdateTimestampsCache = "HHH000310: Unable to destroy update timestamps cache: %s: %s"; + private static final String unableToDetermineLockModeValue = "HHH000311: Unable to determine lock mode value : %s -> %s"; + private static final String unableToDetermineTransactionStatus = "HHH000312: Could not determine transaction status"; + private static final String unableToDetermineTransactionStatusAfterCommit = "HHH000313: Could not determine transaction status after commit"; + private static final String unableToDropTemporaryIdTable = "HHH000314: Unable to drop temporary id table after use [%s]"; + private static final String unableToExecuteBatch = "HHH000315: Exception executing batch [%s], SQL: %s"; + private static final String unableToExecuteResolver = "HHH000316: Error executing resolver [%s] : %s"; + private static final String unableToFindPersistenceXmlInClasspath = "HHH000318: Could not find any META-INF/persistence.xml file in the classpath"; + private static final String unableToGetDatabaseMetadata = "HHH000319: Could not get database metadata"; + private static final String unableToInstantiateConfiguredSchemaNameResolver = "HHH000320: Unable to instantiate configured schema name resolver [%s] %s"; + private static final String unableToLocateCustomOptimizerClass = "HHH000321: Unable to interpret specified optimizer [%s], falling back to noop"; + private static final String unableToInstantiateOptimizer = "HHH000322: Unable to instantiate specified optimizer [%s], falling back to noop"; + private static final String unableToInstantiateUuidGenerationStrategy = "HHH000325: Unable to instantiate UUID generation strategy class : %s"; + private static final String unableToJoinTransaction = "HHH000326: Cannot join transaction: do not override %s"; + private static final String unableToLoadCommand = "HHH000327: Error performing load command : %s"; + private static final String unableToLoadDerbyDriver = "HHH000328: Unable to load/access derby driver class sysinfo to check versions : %s"; + private static final String unableToLoadProperties = "HHH000329: Problem loading properties from hibernate.properties"; + private static final String unableToLocateConfigFile = "HHH000330: Unable to locate config file: %s"; + private static final String unableToLocateConfiguredSchemaNameResolver = "HHH000331: Unable to locate configured schema name resolver class [%s] %s"; + private static final String unableToLocateMBeanServer = "HHH000332: Unable to locate MBeanServer on JMX service shutdown"; + private static final String unableToLocateUuidGenerationStrategy = "HHH000334: Unable to locate requested UUID generation strategy class : %s"; + private static final String unableToLogSqlWarnings = "HHH000335: Unable to log SQLWarnings : %s"; + private static final String unableToLogWarnings = "HHH000336: Could not log warnings"; + private static final String unableToMarkForRollbackOnPersistenceException = "HHH000337: Unable to mark for rollback on PersistenceException: "; + private static final String unableToMarkForRollbackOnTransientObjectException = "HHH000338: Unable to mark for rollback on TransientObjectException: "; + private static final String unableToObjectConnectionMetadata = "HHH000339: Could not obtain connection metadata: %s"; + private static final String unableToObjectConnectionToQueryMetadata = "HHH000340: Could not obtain connection to query metadata: %s"; + private static final String unableToObtainConnectionMetadata = "HHH000341: Could not obtain connection metadata : %s"; + private static final String unableToObtainConnectionToQueryMetadata = "HHH000342: Could not obtain connection to query metadata : %s"; + private static final String unableToObtainInitialContext = "HHH000343: Could not obtain initial context"; + private static final String unableToParseMetadata = "HHH000344: Could not parse the package-level metadata [%s]"; + private static final String unableToPerformJdbcCommit = "HHH000345: JDBC commit failed"; + private static final String unableToPerformManagedFlush = "HHH000346: Error during managed flush [%s]"; + private static final String unableToQueryDatabaseMetadata = "HHH000347: Unable to query java.sql.DatabaseMetaData"; + private static final String unableToReadClass = "HHH000348: Unable to read class: %s"; + private static final String unableToReadColumnValueFromResultSet = "HHH000349: Could not read column value from result set: %s; %s"; + private static final String unableToReadHiValue = "HHH000350: Could not read a hi value - you need to populate the table: %s"; + private static final String unableToReadOrInitHiValue = "HHH000351: Could not read or init a hi value"; + private static final String unableToReleaseBatchStatement = "HHH000352: Unable to release batch statement..."; + private static final String unableToReleaseCacheLock = "HHH000353: Could not release a cache lock : %s"; + private static final String unableToReleaseContext = "HHH000354: Unable to release initial context: %s"; + private static final String unableToReleaseCreatedMBeanServer = "HHH000355: Unable to release created MBeanServer : %s"; + private static final String unableToReleaseIsolatedConnection = "HHH000356: Unable to release isolated connection [%s]"; + private static final String unableToReleaseTypeInfoResultSet = "HHH000357: Unable to release type info result set"; + private static final String unableToRemoveBagJoinFetch = "HHH000358: Unable to erase previously added bag join fetch"; + private static final String unableToResolveAggregateFunction = "HHH000359: Could not resolve aggregate function [%s]; using standard definition"; + private static final String unableToResolveMappingFile = "HHH000360: Unable to resolve mapping file [%s]"; + private static final String unableToRetrieveCache = "HHH000361: Unable to retrieve cache from JNDI [%s]: %s"; + private static final String unableToRetrieveTypeInfoResultSet = "HHH000362: Unable to retrieve type info result set : %s"; + private static final String unableToRollbackConnection = "HHH000363: Unable to rollback connection on exception [%s]"; + private static final String unableToRollbackIsolatedTransaction = "HHH000364: Unable to rollback isolated transaction on error [%s] : [%s]"; + private static final String unableToRollbackJta = "HHH000365: JTA rollback failed"; + private static final String unableToRunSchemaUpdate = "HHH000366: Error running schema update"; + private static final String unableToSetTransactionToRollbackOnly = "HHH000367: Could not set transaction to rollback only"; + private static final String unableToStopHibernateService = "HHH000368: Exception while stopping service"; + private static final String unableToStopService = "HHH000369: Error stopping service [%s] : %s"; + private static final String unableToSwitchToMethodUsingColumnIndex = "HHH000370: Exception switching from method: [%s] to a method using the column index. Reverting to using: [%, , , , or , which will only initialize entities (not as a proxy) as needed."; + private static final String deprecatedManyToManyFetch = "HHH000455: The fetch attribute on has been deprecated. Instead of fetch=\"select\", use lazy=\"extra\" with , , , , or , which will only initialize entities (not as a proxy) as needed."; + private static final String unsupportedNamedParameters = "HHH000456: Named parameters are used for a callable statement, but database metadata indicates named parameters are not supported."; + private static final String applyingExplicitDiscriminatorColumnForJoined = "HHH000457: Joined inheritance hierarchy [%1$s] defined explicit @DiscriminatorColumn. Legacy Hibernate behavior was to ignore the @DiscriminatorColumn. However, as part of issue HHH-6911 we now apply the explicit @DiscriminatorColumn. If you would prefer the legacy behavior, enable the `%2$s` setting (%2$s=true)"; + private static final String creatingPooledLoOptimizer = "HHH000467: Creating pooled optimizer (lo) with [incrementSize=%s; returnClass=%s]"; + private static final String logBadHbmAttributeConverterType = "HHH000468: Unable to interpret type [%s] as an AttributeConverter due to an exception : %s"; + private static final String usingStoppedClassLoaderService = "HHH000469: The ClassLoaderService can not be reused. This instance was stopped already."; + private static final String logUnexpectedSessionInCollectionNotConnected = "HHH000470: An unexpected session is defined for a collection, but the collection is not connected to that session. A persistent collection may only be associated with one session at a time. Overwriting session. %s"; + private static final String logCannotUnsetUnexpectedSessionInCollection = "HHH000471: Cannot unset session in a collection because an unexpected session is defined. A persistent collection may only be associated with one session at a time. %s"; + private static final String hikariProviderClassNotFound = "HHH000472: Hikari properties were encountered, but the Hikari ConnectionProvider was not found on the classpath; these properties are going to be ignored."; + private static final String cachedFileObsolete = "HHH000473: Omitting cached file [%s] as the mapping file is newer"; + private static final String ambiguousPropertyMethods = "HHH000474: Ambiguous persistent property methods detected on %s; mark one as @Transient : [%s] and [%s]"; + private static final String logCannotLocateIndexColumnInformation = "HHH000475: Cannot locate column information using identifier [%s]; ignoring index [%s]"; + private static final String executingImportScript = "HHH000476: Executing import script '%s'"; + private static final String startingDelayedSchemaDrop = "HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down'"; + private static final String unsuccessfulSchemaManagementCommand = "HHH000478: Unsuccessful: %s"; + private static final String collectionNotProcessedByFlush = "HHH000479: Collection [%s] was not processed by flush(). This is likely due to unsafe use of the session (e.g. used in multiple threads concurrently, updates during entity lifecycle hooks)."; + private static final String stalePersistenceContextInEntityEntry = "HHH000480: A ManagedEntity was associated with a stale PersistenceContext. A ManagedEntity may only be associated with one PersistenceContext at a time; %s"; + private static final String unknownJavaTypeNoEqualsHashCode = "HHH000481: Encountered Java type [%s] for which we could not locate a JavaTypeDescriptor and which does not appear to implement equals and/or hashCode. This can lead to significant performance problems when performing equality/dirty checking involving this Java type. Consider registering a custom JavaTypeDescriptor or at least implementing equals/hashCode."; + private static final String cacheOrCacheableAnnotationOnNonRoot = "HHH000482: @javax.persistence.Cacheable or @org.hibernate.annotations.Cache used on a non-root entity: ignored for %s"; + private static final String emptyCompositesEnabled = "HHH000483: An experimental feature has been enabled (hibernate.create_empty_composites.enabled=true) that instantiates empty composite/embedded objects when all of its attribute values are null. This feature has known issues and should not be used in production until it is stabilized. See Hibernate Jira issue HHH-11936 for details."; + private static final String immutableEntityUpdateQuery = "HHH000487: The query: [%s] attempts to update an immutable entity: %s"; + + public J2CacheMessageLogger_$logger(Logger log) { + super(log); + } + + protected Locale getLoggingLocale() { + return LOCALE; + } + + public final void attemptToRestartAlreadyStartedJ2CacheProvider() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.attemptToRestartAlreadyStartedJ2CacheProvider$str(), new Object[0]); + } + + protected String attemptToRestartAlreadyStartedJ2CacheProvider$str() { + return "HHH020001: Attempt to restart an already started J2CacheRegionFactory. Use sessionFactory.close() between repeated calls to buildSessionFactory. Using previously created J2CacheRegionFactory. If this behaviour is required, consider using org.hibernate.cache.ehcache.SingletonJ2CacheRegionFactory."; + } + + public final void unableToFindConfiguration(String name) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToFindConfiguration$str(), name); + } + + protected String unableToFindConfiguration$str() { + return "HHH020002: Could not find configuration [%s]; using defaults."; + } + + public final void unableToFindJ2CacheConfiguration(String name) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToFindJ2CacheConfiguration$str(), name); + } + + protected String unableToFindJ2CacheConfiguration$str() { + return "HHH020003: Could not find a specific ehcache configuration for cache named [%s]; using defaults."; + } + + public final void unableToLoadConfiguration(String configurationResourceName) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLoadConfiguration$str(), configurationResourceName); + } + + protected String unableToLoadConfiguration$str() { + return "HHH020004: A configurationResourceName was set to %s but the resource could not be loaded from the classpath. Ehcache will configure itself using defaults."; + } + + public final void incompatibleCacheValueMode() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.incompatibleCacheValueMode$str(), new Object[0]); + } + + protected String incompatibleCacheValueMode$str() { + return "HHH020005: The default cache value mode for this Ehcache configuration is \"identity\". This is incompatible with clustered Hibernate caching - the value mode has therefore been switched to \"serialization\""; + } + + public final void incompatibleCacheValueModePerCache(String cacheName) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.incompatibleCacheValueModePerCache$str(), cacheName); + } + + protected String incompatibleCacheValueModePerCache$str() { + return "HHH020006: The value mode for the cache[%s] is \"identity\". This is incompatible with clustered Hibernate caching - the value mode has therefore been switched to \"serialization\""; + } + + public final void readOnlyCacheConfiguredForMutableEntity(String entityName) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.readOnlyCacheConfiguredForMutableEntity$str(), entityName); + } + + protected String readOnlyCacheConfiguredForMutableEntity$str() { + return "HHH020007: read-only cache configured for mutable entity [%s]"; + } + + public final void softLockedCacheExpired(String regionName, Object key, String lock) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.softLockedCacheExpired$str(), regionName, key, lock); + } + + protected String softLockedCacheExpired$str() { + return "HHH020008: Cache[%s] Key[%s] Lockable[%s]\nA soft-locked cache entry was expired by the underlying Ehcache. If this happens regularly you should consider increasing the cache timeouts and/or capacity limits"; + } + + public final void alreadySessionBound() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.alreadySessionBound$str(), new Object[0]); + } + + protected String alreadySessionBound$str() { + return "HHH000002: Already session bound on call to bind(); make sure you clean up your sessions!"; + } + + public final void autoCommitMode(boolean arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.autoCommitMode$str(), arg0); + } + + protected String autoCommitMode$str() { + return "HHH000006: Autocommit mode: %s"; + } + + public final void autoFlushWillNotWork() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.autoFlushWillNotWork$str(), new Object[0]); + } + + protected String autoFlushWillNotWork$str() { + return "HHH000008: JTASessionContext being used with JDBC transactions; auto-flush will not operate correctly with getCurrentSession()"; + } + + public final void batchContainedStatementsOnRelease() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.batchContainedStatementsOnRelease$str(), new Object[0]); + } + + protected String batchContainedStatementsOnRelease$str() { + return "HHH000010: On release of batch it still contained JDBC statements"; + } + + public final void bytecodeProvider(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.bytecodeProvider$str(), arg0); + } + + protected String bytecodeProvider$str() { + return "HHH000021: Bytecode provider name : %s"; + } + + public final void c3p0ProviderClassNotFound(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.c3p0ProviderClassNotFound$str(), arg0); + } + + protected String c3p0ProviderClassNotFound$str() { + return "HHH000022: c3p0 properties were encountered, but the %s provider class was not found on the classpath; these properties are going to be ignored."; + } + + public final void cachedFileNotFound(String arg0, FileNotFoundException arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.cachedFileNotFound$str(), arg0, arg1); + } + + protected String cachedFileNotFound$str() { + return "HHH000023: I/O reported cached file could not be found : %s : %s"; + } + + public final void cacheProvider(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.cacheProvider$str(), arg0); + } + + protected String cacheProvider$str() { + return "HHH000024: Cache provider: %s"; + } + + public final void callingJoinTransactionOnNonJtaEntityManager() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.callingJoinTransactionOnNonJtaEntityManager$str(), new Object[0]); + } + + protected String callingJoinTransactionOnNonJtaEntityManager$str() { + return "HHH000027: Calling joinTransaction() on a non JTA EntityManager"; + } + + public final void closing() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.closing$str(), new Object[0]); + } + + protected String closing$str() { + return "HHH000031: Closing"; + } + + public final void collectionsFetched(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.collectionsFetched$str(), arg0); + } + + protected String collectionsFetched$str() { + return "HHH000032: Collections fetched (minimize this): %s"; + } + + public final void collectionsLoaded(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.collectionsLoaded$str(), arg0); + } + + protected String collectionsLoaded$str() { + return "HHH000033: Collections loaded: %s"; + } + + public final void collectionsRecreated(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.collectionsRecreated$str(), arg0); + } + + protected String collectionsRecreated$str() { + return "HHH000034: Collections recreated: %s"; + } + + public final void collectionsRemoved(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.collectionsRemoved$str(), arg0); + } + + protected String collectionsRemoved$str() { + return "HHH000035: Collections removed: %s"; + } + + public final void collectionsUpdated(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.collectionsUpdated$str(), arg0); + } + + protected String collectionsUpdated$str() { + return "HHH000036: Collections updated: %s"; + } + + public final void columns(Set arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.columns$str(), arg0); + } + + protected String columns$str() { + return "HHH000037: Columns: %s"; + } + + public final void compositeIdClassDoesNotOverrideEquals(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.compositeIdClassDoesNotOverrideEquals$str(), arg0); + } + + protected String compositeIdClassDoesNotOverrideEquals$str() { + return "HHH000038: Composite-id class does not override equals(): %s"; + } + + public final void compositeIdClassDoesNotOverrideHashCode(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.compositeIdClassDoesNotOverrideHashCode$str(), arg0); + } + + protected String compositeIdClassDoesNotOverrideHashCode$str() { + return "HHH000039: Composite-id class does not override hashCode(): %s"; + } + + public final void configurationResource(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configurationResource$str(), arg0); + } + + protected String configurationResource$str() { + return "HHH000040: Configuration resource: %s"; + } + + public final void configuredSessionFactory(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configuredSessionFactory$str(), arg0); + } + + protected String configuredSessionFactory$str() { + return "HHH000041: Configured SessionFactory: %s"; + } + + public final void configuringFromFile(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configuringFromFile$str(), arg0); + } + + protected String configuringFromFile$str() { + return "HHH000042: Configuring from file: %s"; + } + + public final void configuringFromResource(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configuringFromResource$str(), arg0); + } + + protected String configuringFromResource$str() { + return "HHH000043: Configuring from resource: %s"; + } + + public final void configuringFromUrl(URL arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configuringFromUrl$str(), arg0); + } + + protected String configuringFromUrl$str() { + return "HHH000044: Configuring from URL: %s"; + } + + public final void configuringFromXmlDocument() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.configuringFromXmlDocument$str(), new Object[0]); + } + + protected String configuringFromXmlDocument$str() { + return "HHH000045: Configuring from XML document"; + } + + public final void connectionsObtained(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.connectionsObtained$str(), arg0); + } + + protected String connectionsObtained$str() { + return "HHH000048: Connections obtained: %s"; + } + + public final void containerProvidingNullPersistenceUnitRootUrl() { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.containerProvidingNullPersistenceUnitRootUrl$str(), new Object[0]); + } + + protected String containerProvidingNullPersistenceUnitRootUrl$str() { + return "HHH000050: Container is providing a null PersistenceUnitRootUrl: discovery impossible"; + } + + public final void containsJoinFetchedCollection(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.containsJoinFetchedCollection$str(), arg0); + } + + protected String containsJoinFetchedCollection$str() { + return "HHH000051: Ignoring bag join fetch [%s] due to prior collection join fetch"; + } + + public final void creatingSubcontextInfo(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.creatingSubcontextInfo$str(), arg0); + } + + protected String creatingSubcontextInfo$str() { + return "HHH000053: Creating subcontext: %s"; + } + + public final void definingFlushBeforeCompletionIgnoredInHem(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.definingFlushBeforeCompletionIgnoredInHem$str(), arg0); + } + + protected String definingFlushBeforeCompletionIgnoredInHem$str() { + return "HHH000059: Defining %s=true ignored in HEM"; + } + + public final void deprecatedForceDescriminatorAnnotation() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedForceDescriminatorAnnotation$str(), new Object[0]); + } + + protected String deprecatedForceDescriminatorAnnotation$str() { + return "HHH000062: @ForceDiscriminator is deprecated use @DiscriminatorOptions instead."; + } + + public final void deprecatedOracle9Dialect() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedOracle9Dialect$str(), new Object[0]); + } + + protected String deprecatedOracle9Dialect$str() { + return "HHH000063: The Oracle9Dialect dialect has been deprecated; use either Oracle9iDialect or Oracle10gDialect instead"; + } + + public final void deprecatedOracleDialect() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedOracleDialect$str(), new Object[0]); + } + + protected String deprecatedOracleDialect$str() { + return "HHH000064: The OracleDialect dialect has been deprecated; use Oracle8iDialect instead"; + } + + public final void deprecatedUuidGenerator(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedUuidGenerator$str(), arg0, arg1); + } + + protected String deprecatedUuidGenerator$str() { + return "HHH000065: DEPRECATED : use [%s] instead with custom [%s] implementation"; + } + + public final void disallowingInsertStatementComment() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.disallowingInsertStatementComment$str(), new Object[0]); + } + + protected String disallowingInsertStatementComment$str() { + return "HHH000067: Disallowing insert statement comment for select-identity due to Oracle driver bug"; + } + + public final void duplicateGeneratorName(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.duplicateGeneratorName$str(), arg0); + } + + protected String duplicateGeneratorName$str() { + return "HHH000069: Duplicate generator name %s"; + } + + public final void duplicateGeneratorTable(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.duplicateGeneratorTable$str(), arg0); + } + + protected String duplicateGeneratorTable$str() { + return "HHH000070: Duplicate generator table: %s"; + } + + public final void duplicateImport(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.duplicateImport$str(), arg0, arg1); + } + + protected String duplicateImport$str() { + return "HHH000071: Duplicate import: %s -> %s"; + } + + public final void duplicateJoins(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.duplicateJoins$str(), arg0); + } + + protected String duplicateJoins$str() { + return "HHH000072: Duplicate joins for class: %s"; + } + + public final void duplicateListener(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.duplicateListener$str(), arg0); + } + + protected String duplicateListener$str() { + return "HHH000073: entity-listener duplication, first event definition will be used: %s"; + } + + public final void duplicateMetadata() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.duplicateMetadata$str(), new Object[0]); + } + + protected String duplicateMetadata$str() { + return "HHH000074: Found more than one , subsequent ignored"; + } + + public final void entitiesDeleted(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.entitiesDeleted$str(), arg0); + } + + protected String entitiesDeleted$str() { + return "HHH000076: Entities deleted: %s"; + } + + public final void entitiesFetched(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.entitiesFetched$str(), arg0); + } + + protected String entitiesFetched$str() { + return "HHH000077: Entities fetched (minimize this): %s"; + } + + public final void entitiesInserted(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.entitiesInserted$str(), arg0); + } + + protected String entitiesInserted$str() { + return "HHH000078: Entities inserted: %s"; + } + + public final void entitiesLoaded(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.entitiesLoaded$str(), arg0); + } + + protected String entitiesLoaded$str() { + return "HHH000079: Entities loaded: %s"; + } + + public final void entitiesUpdated(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.entitiesUpdated$str(), arg0); + } + + protected String entitiesUpdated$str() { + return "HHH000080: Entities updated: %s"; + } + + public final void entityAnnotationOnNonRoot(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.entityAnnotationOnNonRoot$str(), arg0); + } + + protected String entityAnnotationOnNonRoot$str() { + return "HHH000081: @org.hibernate.annotations.Entity used on a non root entity: ignored for %s"; + } + + public final void entityManagerClosedBySomeoneElse(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.entityManagerClosedBySomeoneElse$str(), arg0); + } + + protected String entityManagerClosedBySomeoneElse$str() { + return "HHH000082: Entity Manager closed by someone else (%s must not be used)"; + } + + public final void entityMappedAsNonAbstract(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.entityMappedAsNonAbstract$str(), arg0); + } + + protected String entityMappedAsNonAbstract$str() { + return "HHH000084: Entity [%s] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names"; + } + + public final void exceptionHeaderFound(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.exceptionHeaderFound$str(), arg0, arg1); + } + + protected String exceptionHeaderFound$str() { + return "HHH000085: %s %s found"; + } + + public final void exceptionHeaderNotFound(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.exceptionHeaderNotFound$str(), arg0, arg1); + } + + protected String exceptionHeaderNotFound$str() { + return "HHH000086: %s No %s found"; + } + + public final void exceptionInAfterTransactionCompletionInterceptor(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.exceptionInAfterTransactionCompletionInterceptor$str(), new Object[0]); + } + + protected String exceptionInAfterTransactionCompletionInterceptor$str() { + return "HHH000087: Exception in interceptor afterTransactionCompletion()"; + } + + public final void exceptionInBeforeTransactionCompletionInterceptor(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.exceptionInBeforeTransactionCompletionInterceptor$str(), new Object[0]); + } + + protected String exceptionInBeforeTransactionCompletionInterceptor$str() { + return "HHH000088: Exception in interceptor beforeTransactionCompletion()"; + } + + public final void exceptionInSubResolver(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.exceptionInSubResolver$str(), arg0); + } + + protected String exceptionInSubResolver$str() { + return "HHH000089: Sub-resolver threw unexpected exception, continuing to next : %s"; + } + + public final void expectedType(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.expectedType$str(), arg0, arg1); + } + + protected String expectedType$str() { + return "HHH000091: Expected type: %s, actual value: %s"; + } + + public final void expired(Object arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.expired$str(), arg0); + } + + protected String expired$str() { + return "HHH000092: An item was expired by the cache while it was locked (increase your cache timeout): %s"; + } + + public final void factoryBoundToJndiName(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.factoryBoundToJndiName$str(), arg0); + } + + protected String factoryBoundToJndiName$str() { + return "HHH000094: Bound factory to JNDI name: %s"; + } + + public final void factoryJndiRename(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.factoryJndiRename$str(), arg0, arg1); + } + + protected String factoryJndiRename$str() { + return "HHH000096: A factory was renamed from [%s] to [%s] in JNDI"; + } + + public final void factoryUnboundFromJndiName(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.factoryUnboundFromJndiName$str(), arg0); + } + + protected String factoryUnboundFromJndiName$str() { + return "HHH000097: Unbound factory from JNDI name: %s"; + } + + public final void factoryUnboundFromName(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.factoryUnboundFromName$str(), arg0); + } + + protected String factoryUnboundFromName$str() { + return "HHH000098: A factory was unbound from name: %s"; + } + + public final void failed(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.failed$str(), arg0); + } + + protected String failed$str() { + return "HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): %s"; + } + + public final void failSafeCollectionsCleanup(CollectionLoadContext arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.failSafeCollectionsCleanup$str(), arg0); + } + + protected String failSafeCollectionsCleanup$str() { + return "HHH000100: Fail-safe cleanup (collections) : %s"; + } + + public final void failSafeEntitiesCleanup(EntityLoadContext arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.failSafeEntitiesCleanup$str(), arg0); + } + + protected String failSafeEntitiesCleanup$str() { + return "HHH000101: Fail-safe cleanup (entities) : %s"; + } + + public final void fetchingDatabaseMetadata() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.fetchingDatabaseMetadata$str(), new Object[0]); + } + + protected String fetchingDatabaseMetadata$str() { + return "HHH000102: Fetching database metadata"; + } + + public final void firstOrMaxResultsSpecifiedWithCollectionFetch() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.firstOrMaxResultsSpecifiedWithCollectionFetch$str(), new Object[0]); + } + + protected String firstOrMaxResultsSpecifiedWithCollectionFetch$str() { + return "HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!"; + } + + public final void flushes(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.flushes$str(), arg0); + } + + protected String flushes$str() { + return "HHH000105: Flushes: %s"; + } + + public final void forcingContainerResourceCleanup() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.forcingContainerResourceCleanup$str(), new Object[0]); + } + + protected String forcingContainerResourceCleanup$str() { + return "HHH000106: Forcing container resource cleanup on transaction completion"; + } + + public final void forcingTableUse() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.forcingTableUse$str(), new Object[0]); + } + + protected String forcingTableUse$str() { + return "HHH000107: Forcing table use for sequence-style generator due to pooled optimizer selection where db does not support pooled sequences"; + } + + public final void foreignKeys(Set arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.foreignKeys$str(), arg0); + } + + protected String foreignKeys$str() { + return "HHH000108: Foreign keys: %s"; + } + + public final void foundMappingDocument(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.foundMappingDocument$str(), arg0); + } + + protected String foundMappingDocument$str() { + return "HHH000109: Found mapping document in jar: %s"; + } + + public final void gettersOfLazyClassesCannotBeFinal(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.gettersOfLazyClassesCannotBeFinal$str(), arg0, arg1); + } + + protected String gettersOfLazyClassesCannotBeFinal$str() { + return "HHH000112: Getters of lazy classes cannot be final: %s.%s"; + } + + public final void guidGenerated(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.guidGenerated$str(), arg0); + } + + protected String guidGenerated$str() { + return "HHH000113: GUID identifier generated: %s"; + } + + public final void handlingTransientEntity() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.handlingTransientEntity$str(), new Object[0]); + } + + protected String handlingTransientEntity$str() { + return "HHH000114: Handling transient entity in delete processing"; + } + + public final void hibernateConnectionPoolSize(int arg0, int arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.hibernateConnectionPoolSize$str(), arg0, arg1); + } + + protected String hibernateConnectionPoolSize$str() { + return "HHH000115: Hibernate connection pool size: %s (min=%s)"; + } + + public final void honoringOptimizerSetting(String arg0, String arg1, int arg2, String arg3, int arg4) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.honoringOptimizerSetting$str(), new Object[]{arg0, arg1, arg2, arg3, arg4}); + } + + protected String honoringOptimizerSetting$str() { + return "HHH000116: Config specified explicit optimizer of [%s], but [%s=%s]; using optimizer [%s] increment default of [%s]."; + } + + public final void hql(String arg0, Long arg1, Long arg2) { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.hql$str(), arg0, arg1, arg2); + } + + protected String hql$str() { + return "HHH000117: HQL: %s, time: %sms, rows: %s"; + } + + public final void hsqldbSupportsOnlyReadCommittedIsolation() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.hsqldbSupportsOnlyReadCommittedIsolation$str(), new Object[0]); + } + + protected String hsqldbSupportsOnlyReadCommittedIsolation$str() { + return "HHH000118: HSQLDB supports only READ_UNCOMMITTED isolation"; + } + + public final void hydratingEntitiesCount(int arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.hydratingEntitiesCount$str(), arg0); + } + + protected String hydratingEntitiesCount$str() { + return "HHH000119: On EntityLoadContext#clear, hydratingEntities contained [%s] entries"; + } + + public final void ignoringTableGeneratorConstraints(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.ignoringTableGeneratorConstraints$str(), arg0); + } + + protected String ignoringTableGeneratorConstraints$str() { + return "HHH000120: Ignoring unique constraints specified on table generator [%s]"; + } + + public final void ignoringUnrecognizedQueryHint(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.ignoringUnrecognizedQueryHint$str(), arg0); + } + + protected String ignoringUnrecognizedQueryHint$str() { + return "HHH000121: Ignoring unrecognized query hint [%s]"; + } + + public final void illegalPropertyGetterArgument(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.illegalPropertyGetterArgument$str(), arg0, arg1); + } + + protected String illegalPropertyGetterArgument$str() { + return "HHH000122: IllegalArgumentException in class: %s, getter method of property: %s"; + } + + public final void illegalPropertySetterArgument(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.illegalPropertySetterArgument$str(), arg0, arg1); + } + + protected String illegalPropertySetterArgument$str() { + return "HHH000123: IllegalArgumentException in class: %s, setter method of property: %s"; + } + + public final void immutableAnnotationOnNonRoot(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.immutableAnnotationOnNonRoot$str(), arg0); + } + + protected String immutableAnnotationOnNonRoot$str() { + return "HHH000124: @Immutable used on a non root entity: ignored for %s"; + } + + public final void incompleteMappingMetadataCacheProcessing() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.incompleteMappingMetadataCacheProcessing$str(), new Object[0]); + } + + protected String incompleteMappingMetadataCacheProcessing$str() { + return "HHH000125: Mapping metadata cache was not completely processed"; + } + + public final void indexes(Set arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.indexes$str(), arg0); + } + + protected String indexes$str() { + return "HHH000126: Indexes: %s"; + } + + public final void couldNotBindJndiListener() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.couldNotBindJndiListener$str(), new Object[0]); + } + + protected String couldNotBindJndiListener$str() { + return "HHH000127: Could not bind JNDI listener"; + } + + public final void instantiatingExplicitConnectionProvider(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.instantiatingExplicitConnectionProvider$str(), arg0); + } + + protected String instantiatingExplicitConnectionProvider$str() { + return "HHH000130: Instantiating explicit connection provider: %s"; + } + + public final void invalidArrayElementType(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.invalidArrayElementType$str(), arg0); + } + + protected String invalidArrayElementType$str() { + return "HHH000132: Array element type error\n%s"; + } + + public final void invalidDiscriminatorAnnotation(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.invalidDiscriminatorAnnotation$str(), arg0); + } + + protected String invalidDiscriminatorAnnotation$str() { + return "HHH000133: Discriminator column has to be defined in the root entity, it will be ignored in subclass: %s"; + } + + public final void invalidEditOfReadOnlyItem(Object arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.invalidEditOfReadOnlyItem$str(), arg0); + } + + protected String invalidEditOfReadOnlyItem$str() { + return "HHH000134: Application attempted to edit read only item: %s"; + } + + public final void invalidJndiName(String arg0, JndiNameException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.invalidJndiName$str(), arg0); + } + + protected String invalidJndiName$str() { + return "HHH000135: Invalid JNDI name: %s"; + } + + public final void invalidOnDeleteAnnotation(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.invalidOnDeleteAnnotation$str(), arg0); + } + + protected String invalidOnDeleteAnnotation$str() { + return "HHH000136: Inapropriate use of @OnDelete on entity, annotation ignored: %s"; + } + + public final void invalidPrimaryKeyJoinColumnAnnotation(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.invalidPrimaryKeyJoinColumnAnnotation$str(), arg0); + } + + protected String invalidPrimaryKeyJoinColumnAnnotation$str() { + return "HHH000137: Root entity should not hold a PrimaryKeyJoinColum(s), will be ignored: %s"; + } + + public final void invalidSubStrategy(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.invalidSubStrategy$str(), arg0); + } + + protected String invalidSubStrategy$str() { + return "HHH000138: Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: %s"; + } + + public final void invalidTableAnnotation(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.invalidTableAnnotation$str(), arg0); + } + + protected String invalidTableAnnotation$str() { + return "HHH000139: Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: %s"; + } + + public final void jaccContextId(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.jaccContextId$str(), arg0); + } + + protected String jaccContextId$str() { + return "HHH000140: JACC contextID: %s"; + } + + public final void JavaSqlTypesMappedSameCodeMultipleTimes(int arg0, String arg1, String arg2) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.JavaSqlTypesMappedSameCodeMultipleTimes$str(), arg0, arg1, arg2); + } + + protected String JavaSqlTypesMappedSameCodeMultipleTimes$str() { + return "HHH000141: java.sql.Types mapped the same code [%s] multiple times; was [%s]; now [%s]"; + } + + protected String bytecodeEnhancementFailed$str() { + return "HHH000142: Bytecode enhancement failed: %s"; + } + + public final String bytecodeEnhancementFailed(String arg0) { + return String.format(this.getLoggingLocale(), this.bytecodeEnhancementFailed$str(), arg0); + } + + public final void jdbcAutoCommitFalseBreaksEjb3Spec(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.jdbcAutoCommitFalseBreaksEjb3Spec$str(), arg0); + } + + protected String jdbcAutoCommitFalseBreaksEjb3Spec$str() { + return "HHH000144: %s = false breaks the EJB3 specification"; + } + + protected String jdbcRollbackFailed$str() { + return "HHH000151: JDBC rollback failed"; + } + + public final String jdbcRollbackFailed() { + return String.format(this.getLoggingLocale(), this.jdbcRollbackFailed$str()); + } + + public final void jndiInitialContextProperties(Hashtable arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.jndiInitialContextProperties$str(), arg0); + } + + protected String jndiInitialContextProperties$str() { + return "HHH000154: JNDI InitialContext properties:%s"; + } + + public final void jndiNameDoesNotHandleSessionFactoryReference(String arg0, ClassCastException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.jndiNameDoesNotHandleSessionFactoryReference$str(), arg0); + } + + protected String jndiNameDoesNotHandleSessionFactoryReference$str() { + return "HHH000155: JNDI name %s does not handle a session factory reference"; + } + + public final void lazyPropertyFetchingAvailable(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.lazyPropertyFetchingAvailable$str(), arg0); + } + + protected String lazyPropertyFetchingAvailable$str() { + return "HHH000157: Lazy property fetching available for: %s"; + } + + public final void loadingCollectionKeyNotFound(CollectionKey arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.loadingCollectionKeyNotFound$str(), arg0); + } + + protected String loadingCollectionKeyNotFound$str() { + return "HHH000159: In CollectionLoadContext#endLoadingCollections, localLoadingCollectionKeys contained [%s], but no LoadingCollectionEntry was found in loadContexts"; + } + + public final void localLoadingCollectionKeysCount(int arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.localLoadingCollectionKeysCount$str(), arg0); + } + + protected String localLoadingCollectionKeysCount$str() { + return "HHH000160: On CollectionLoadContext#cleanup, localLoadingCollectionKeys contained [%s] entries"; + } + + public final void loggingStatistics() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.loggingStatistics$str(), new Object[0]); + } + + protected String loggingStatistics$str() { + return "HHH000161: Logging statistics...."; + } + + public final void logicalConnectionClosed() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.logicalConnectionClosed$str(), new Object[0]); + } + + protected String logicalConnectionClosed$str() { + return "HHH000162: *** Logical connection closed ***"; + } + + public final void logicalConnectionReleasingPhysicalConnection() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.logicalConnectionReleasingPhysicalConnection$str(), new Object[0]); + } + + protected String logicalConnectionReleasingPhysicalConnection$str() { + return "HHH000163: Logical connection releasing its physical connection"; + } + + public final void maxQueryTime(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.maxQueryTime$str(), arg0); + } + + protected String maxQueryTime$str() { + return "HHH000173: Max query time: %sms"; + } + + public final void missingArguments(int arg0, int arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.missingArguments$str(), arg0, arg1); + } + + protected String missingArguments$str() { + return "HHH000174: Function template anticipated %s arguments, but %s arguments encountered"; + } + + public final void missingEntityAnnotation(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.missingEntityAnnotation$str(), arg0); + } + + protected String missingEntityAnnotation$str() { + return "HHH000175: Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity (most likely a user error): %s"; + } + + public final void namedQueryError(String arg0, HibernateException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.namedQueryError$str(), arg0); + } + + protected String namedQueryError$str() { + return "HHH000177: Error in named query: %s"; + } + + public final void namingExceptionAccessingFactory(NamingException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.namingExceptionAccessingFactory$str(), arg0); + } + + protected String namingExceptionAccessingFactory$str() { + return "HHH000178: Naming exception occurred accessing factory: %s"; + } + + public final void narrowingProxy(Class arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.narrowingProxy$str(), arg0); + } + + protected String narrowingProxy$str() { + return "HHH000179: Narrowing proxy to %s - this operation breaks =="; + } + + public final void needsLimit() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.needsLimit$str(), new Object[0]); + } + + protected String needsLimit$str() { + return "HHH000180: FirstResult/maxResults specified on polymorphic query; applying in memory!"; + } + + public final void noAppropriateConnectionProvider() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.noAppropriateConnectionProvider$str(), new Object[0]); + } + + protected String noAppropriateConnectionProvider$str() { + return "HHH000181: No appropriate connection provider encountered, assuming application will be supplying connections"; + } + + public final void noDefaultConstructor(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.noDefaultConstructor$str(), arg0); + } + + protected String noDefaultConstructor$str() { + return "HHH000182: No default (no-argument) constructor for class: %s (class must be instantiated by Interceptor)"; + } + + public final void noPersistentClassesFound(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.noPersistentClassesFound$str(), arg0); + } + + protected String noPersistentClassesFound$str() { + return "HHH000183: no persistent classes found for query class: %s"; + } + + public final void noSessionFactoryWithJndiName(String arg0, NameNotFoundException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.noSessionFactoryWithJndiName$str(), arg0); + } + + protected String noSessionFactoryWithJndiName$str() { + return "HHH000184: No session factory with JNDI name %s"; + } + + public final void optimisticLockFailures(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.optimisticLockFailures$str(), arg0); + } + + protected String optimisticLockFailures$str() { + return "HHH000187: Optimistic lock failures: %s"; + } + + public final void orderByAnnotationIndexedCollection() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.orderByAnnotationIndexedCollection$str(), new Object[0]); + } + + protected String orderByAnnotationIndexedCollection$str() { + return "HHH000189: @OrderBy not allowed for an indexed collection, annotation ignored."; + } + + public final void overridingTransactionStrategyDangerous(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.overridingTransactionStrategyDangerous$str(), arg0); + } + + protected String overridingTransactionStrategyDangerous$str() { + return "HHH000193: Overriding %s is dangerous, this might break the EJB3 specification implementation"; + } + + public final void packageNotFound(String arg0) { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.packageNotFound$str(), arg0); + } + + protected String packageNotFound$str() { + return "HHH000194: Package not found or wo package-info.java: %s"; + } + + public final void parsingXmlError(int arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.parsingXmlError$str(), arg0, arg1); + } + + protected String parsingXmlError$str() { + return "HHH000196: Error parsing XML (%s) : %s"; + } + + public final void parsingXmlErrorForFile(String arg0, int arg1, String arg2) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.parsingXmlErrorForFile$str(), arg0, arg1, arg2); + } + + protected String parsingXmlErrorForFile$str() { + return "HHH000197: Error parsing XML: %s(%s) %s"; + } + + public final void parsingXmlWarning(int arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.parsingXmlWarning$str(), arg0, arg1); + } + + protected String parsingXmlWarning$str() { + return "HHH000198: Warning parsing XML (%s) : %s"; + } + + public final void parsingXmlWarningForFile(String arg0, int arg1, String arg2) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.parsingXmlWarningForFile$str(), arg0, arg1, arg2); + } + + protected String parsingXmlWarningForFile$str() { + return "HHH000199: Warning parsing XML: %s(%s) %s"; + } + + public final void persistenceProviderCallerDoesNotImplementEjb3SpecCorrectly() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.persistenceProviderCallerDoesNotImplementEjb3SpecCorrectly$str(), new Object[0]); + } + + protected String persistenceProviderCallerDoesNotImplementEjb3SpecCorrectly$str() { + return "HHH000200: Persistence provider caller does not implement the EJB3 spec correctly.PersistenceUnitInfo.getNewTempClassLoader() is null."; + } + + public final void pooledOptimizerReportedInitialValue(IntegralDataTypeHolder arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.pooledOptimizerReportedInitialValue$str(), arg0); + } + + protected String pooledOptimizerReportedInitialValue$str() { + return "HHH000201: Pooled optimizer source reported [%s] as the initial value; use of 1 or greater highly recommended"; + } + + public final void preparedStatementAlreadyInBatch(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.preparedStatementAlreadyInBatch$str(), arg0); + } + + protected String preparedStatementAlreadyInBatch$str() { + return "HHH000202: PreparedStatement was already in the batch, [%s]."; + } + + public final void processEqualityExpression() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.processEqualityExpression$str(), new Object[0]); + } + + protected String processEqualityExpression$str() { + return "HHH000203: processEqualityExpression() : No expression to process!"; + } + + public final void processingPersistenceUnitInfoName(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.processingPersistenceUnitInfoName$str(), arg0); + } + + protected String processingPersistenceUnitInfoName$str() { + return "HHH000204: Processing PersistenceUnitInfo [\n\tname: %s\n\t...]"; + } + + public final void propertiesLoaded(Properties arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.propertiesLoaded$str(), arg0); + } + + protected String propertiesLoaded$str() { + return "HHH000205: Loaded properties from resource hibernate.properties: %s"; + } + + public final void propertiesNotFound() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.propertiesNotFound$str(), new Object[0]); + } + + protected String propertiesNotFound$str() { + return "HHH000206: hibernate.properties not found"; + } + + public final void propertyNotFound(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.propertyNotFound$str(), arg0); + } + + protected String propertyNotFound$str() { + return "HHH000207: Property %s not found in class but described in (possible typo error)"; + } + + public final void proxoolProviderClassNotFound(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.proxoolProviderClassNotFound$str(), arg0); + } + + protected String proxoolProviderClassNotFound$str() { + return "HHH000209: proxool properties were encountered, but the %s provider class was not found on the classpath; these properties are going to be ignored."; + } + + public final void queriesExecuted(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.queriesExecuted$str(), arg0); + } + + protected String queriesExecuted$str() { + return "HHH000210: Queries executed to database: %s"; + } + + public final void queryCacheHits(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.queryCacheHits$str(), arg0); + } + + protected String queryCacheHits$str() { + return "HHH000213: Query cache hits: %s"; + } + + public final void queryCacheMisses(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.queryCacheMisses$str(), arg0); + } + + protected String queryCacheMisses$str() { + return "HHH000214: Query cache misses: %s"; + } + + public final void queryCachePuts(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.queryCachePuts$str(), arg0); + } + + protected String queryCachePuts$str() { + return "HHH000215: Query cache puts: %s"; + } + + public final void rdmsOs2200Dialect() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.rdmsOs2200Dialect$str(), new Object[0]); + } + + protected String rdmsOs2200Dialect$str() { + return "HHH000218: RDMSOS2200Dialect version: 1.0"; + } + + public final void readingCachedMappings(File arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.readingCachedMappings$str(), arg0); + } + + protected String readingCachedMappings$str() { + return "HHH000219: Reading mappings from cache file: %s"; + } + + public final void readingMappingsFromFile(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.readingMappingsFromFile$str(), arg0); + } + + protected String readingMappingsFromFile$str() { + return "HHH000220: Reading mappings from file: %s"; + } + + public final void readingMappingsFromResource(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.readingMappingsFromResource$str(), arg0); + } + + protected String readingMappingsFromResource$str() { + return "HHH000221: Reading mappings from resource: %s"; + } + + public final void readOnlyCacheConfiguredForMutableCollection(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.readOnlyCacheConfiguredForMutableCollection$str(), arg0); + } + + protected String readOnlyCacheConfiguredForMutableCollection$str() { + return "HHH000222: read-only cache configured for mutable collection [%s]"; + } + + public final void recognizedObsoleteHibernateNamespace(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.recognizedObsoleteHibernateNamespace$str(), arg0, arg1); + } + + protected String recognizedObsoleteHibernateNamespace$str() { + return "HHH000223: Recognized obsolete hibernate namespace %s. Use namespace %s instead. Refer to Hibernate 3.6 Migration Guide!"; + } + + public final void renamedProperty(Object arg0, Object arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.renamedProperty$str(), arg0, arg1); + } + + protected String renamedProperty$str() { + return "HHH000225: Property [%s] has been renamed to [%s]; update your properties appropriately"; + } + + public final void requiredDifferentProvider(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.requiredDifferentProvider$str(), arg0); + } + + protected String requiredDifferentProvider$str() { + return "HHH000226: Required a different provider: %s"; + } + + public final void runningHbm2ddlSchemaExport() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.runningHbm2ddlSchemaExport$str(), new Object[0]); + } + + protected String runningHbm2ddlSchemaExport$str() { + return "HHH000227: Running hbm2ddl schema export"; + } + + public final void runningHbm2ddlSchemaUpdate() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.runningHbm2ddlSchemaUpdate$str(), new Object[0]); + } + + protected String runningHbm2ddlSchemaUpdate$str() { + return "HHH000228: Running hbm2ddl schema update"; + } + + public final void runningSchemaValidator() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.runningSchemaValidator$str(), new Object[0]); + } + + protected String runningSchemaValidator$str() { + return "HHH000229: Running schema validator"; + } + + public final void schemaExportComplete() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.schemaExportComplete$str(), new Object[0]); + } + + protected String schemaExportComplete$str() { + return "HHH000230: Schema export complete"; + } + + public final void schemaExportUnsuccessful(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.schemaExportUnsuccessful$str(), new Object[0]); + } + + protected String schemaExportUnsuccessful$str() { + return "HHH000231: Schema export unsuccessful"; + } + + public final void schemaUpdateComplete() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.schemaUpdateComplete$str(), new Object[0]); + } + + protected String schemaUpdateComplete$str() { + return "HHH000232: Schema update complete"; + } + + public final void scopingTypesToSessionFactoryAfterAlreadyScoped(SessionFactoryImplementor arg0, SessionFactoryImplementor arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.scopingTypesToSessionFactoryAfterAlreadyScoped$str(), arg0, arg1); + } + + protected String scopingTypesToSessionFactoryAfterAlreadyScoped$str() { + return "HHH000233: Scoping types to session factory %s after already scoped %s"; + } + + public final void searchingForMappingDocuments(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.searchingForMappingDocuments$str(), arg0); + } + + protected String searchingForMappingDocuments$str() { + return "HHH000235: Searching for mapping documents in jar: %s"; + } + + public final void secondLevelCacheHits(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.secondLevelCacheHits$str(), arg0); + } + + protected String secondLevelCacheHits$str() { + return "HHH000237: Second level cache hits: %s"; + } + + public final void secondLevelCacheMisses(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.secondLevelCacheMisses$str(), arg0); + } + + protected String secondLevelCacheMisses$str() { + return "HHH000238: Second level cache misses: %s"; + } + + public final void secondLevelCachePuts(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.secondLevelCachePuts$str(), arg0); + } + + protected String secondLevelCachePuts$str() { + return "HHH000239: Second level cache puts: %s"; + } + + public final void serviceProperties(Properties arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.serviceProperties$str(), arg0); + } + + protected String serviceProperties$str() { + return "HHH000240: Service properties: %s"; + } + + public final void sessionsClosed(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.sessionsClosed$str(), arg0); + } + + protected String sessionsClosed$str() { + return "HHH000241: Sessions closed: %s"; + } + + public final void sessionsOpened(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.sessionsOpened$str(), arg0); + } + + protected String sessionsOpened$str() { + return "HHH000242: Sessions opened: %s"; + } + + public final void settersOfLazyClassesCannotBeFinal(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.settersOfLazyClassesCannotBeFinal$str(), arg0, arg1); + } + + protected String settersOfLazyClassesCannotBeFinal$str() { + return "HHH000243: Setters of lazy classes cannot be final: %s.%s"; + } + + public final void sortAnnotationIndexedCollection() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.sortAnnotationIndexedCollection$str(), new Object[0]); + } + + protected String sortAnnotationIndexedCollection$str() { + return "HHH000244: @Sort not allowed for an indexed collection, annotation ignored."; + } + + public final void splitQueries(String arg0, int arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.splitQueries$str(), arg0, arg1); + } + + protected String splitQueries$str() { + return "HHH000245: Manipulation query [%s] resulted in [%s] split queries"; + } + + public final void sqlWarning(int arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.sqlWarning$str(), arg0, arg1); + } + + protected String sqlWarning$str() { + return "HHH000247: SQL Error: %s, SQLState: %s"; + } + + public final void startingQueryCache(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.startingQueryCache$str(), arg0); + } + + protected String startingQueryCache$str() { + return "HHH000248: Starting query cache at region: %s"; + } + + public final void startingServiceAtJndiName(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.startingServiceAtJndiName$str(), arg0); + } + + protected String startingServiceAtJndiName$str() { + return "HHH000249: Starting service at JNDI name: %s"; + } + + public final void startingUpdateTimestampsCache(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.startingUpdateTimestampsCache$str(), arg0); + } + + protected String startingUpdateTimestampsCache$str() { + return "HHH000250: Starting update timestamps cache at region: %s"; + } + + public final void startTime(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.startTime$str(), arg0); + } + + protected String startTime$str() { + return "HHH000251: Start time: %s"; + } + + public final void statementsClosed(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.statementsClosed$str(), arg0); + } + + protected String statementsClosed$str() { + return "HHH000252: Statements closed: %s"; + } + + public final void statementsPrepared(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.statementsPrepared$str(), arg0); + } + + protected String statementsPrepared$str() { + return "HHH000253: Statements prepared: %s"; + } + + public final void stoppingService() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.stoppingService$str(), new Object[0]); + } + + protected String stoppingService$str() { + return "HHH000255: Stopping service"; + } + + public final void subResolverException(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.subResolverException$str(), arg0); + } + + protected String subResolverException$str() { + return "HHH000257: sub-resolver threw unexpected exception, continuing to next : %s"; + } + + public final void successfulTransactions(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.successfulTransactions$str(), arg0); + } + + protected String successfulTransactions$str() { + return "HHH000258: Successful transactions: %s"; + } + + public final void synchronizationAlreadyRegistered(Synchronization arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.synchronizationAlreadyRegistered$str(), arg0); + } + + protected String synchronizationAlreadyRegistered$str() { + return "HHH000259: Synchronization [%s] was already registered"; + } + + public final void synchronizationFailed(Synchronization arg0, Throwable arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.synchronizationFailed$str(), arg0, arg1); + } + + protected String synchronizationFailed$str() { + return "HHH000260: Exception calling user Synchronization [%s] : %s"; + } + + public final void tableFound(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.tableFound$str(), arg0); + } + + protected String tableFound$str() { + return "HHH000261: Table found: %s"; + } + + public final void tableNotFound(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.tableNotFound$str(), arg0); + } + + protected String tableNotFound$str() { + return "HHH000262: Table not found: %s"; + } + + public final void multipleTablesFound(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.multipleTablesFound$str(), arg0); + } + + protected String multipleTablesFound$str() { + return "HHH000263: More than one table found: %s"; + } + + public final void transactions(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.transactions$str(), arg0); + } + + protected String transactions$str() { + return "HHH000266: Transactions: %s"; + } + + public final void transactionStartedOnNonRootSession() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.transactionStartedOnNonRootSession$str(), new Object[0]); + } + + protected String transactionStartedOnNonRootSession$str() { + return "HHH000267: Transaction started on non-root session"; + } + + public final void transactionStrategy(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.transactionStrategy$str(), arg0); + } + + protected String transactionStrategy$str() { + return "HHH000268: Transaction strategy: %s"; + } + + public final void typeDefinedNoRegistrationKeys(BasicType arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.typeDefinedNoRegistrationKeys$str(), arg0); + } + + protected String typeDefinedNoRegistrationKeys$str() { + return "HHH000269: Type [%s] defined no registration keys; ignoring"; + } + + public final void typeRegistrationOverridesPrevious(String arg0, Type arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.typeRegistrationOverridesPrevious$str(), arg0, arg1); + } + + protected String typeRegistrationOverridesPrevious$str() { + return "HHH000270: Type registration [%s] overrides previous : %s"; + } + + public final void unableToAccessEjb3Configuration(NamingException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToAccessEjb3Configuration$str(), new Object[0]); + } + + protected String unableToAccessEjb3Configuration$str() { + return "HHH000271: Naming exception occurred accessing Ejb3Configuration"; + } + + public final void unableToAccessSessionFactory(String arg0, NamingException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.unableToAccessSessionFactory$str(), arg0); + } + + protected String unableToAccessSessionFactory$str() { + return "HHH000272: Error while accessing session factory with JNDI name %s"; + } + + public final void unableToAccessTypeInfoResultSet(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToAccessTypeInfoResultSet$str(), arg0); + } + + protected String unableToAccessTypeInfoResultSet$str() { + return "HHH000273: Error accessing type info result set : %s"; + } + + public final void unableToApplyConstraints(String arg0, Exception arg1) { + super.log.logf(FQCN, Logger.Level.WARN, arg1, this.unableToApplyConstraints$str(), arg0); + } + + protected String unableToApplyConstraints$str() { + return "HHH000274: Unable to apply constraints on DDL for %s"; + } + + public final void unableToBindEjb3ConfigurationToJndi(JndiException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToBindEjb3ConfigurationToJndi$str(), new Object[0]); + } + + protected String unableToBindEjb3ConfigurationToJndi$str() { + return "HHH000276: Could not bind Ejb3Configuration to JNDI"; + } + + public final void unableToBindFactoryToJndi(JndiException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToBindFactoryToJndi$str(), new Object[0]); + } + + protected String unableToBindFactoryToJndi$str() { + return "HHH000277: Could not bind factory to JNDI"; + } + + public final void unableToBindValueToParameter(String arg0, int arg1, String arg2) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToBindValueToParameter$str(), arg0, arg1, arg2); + } + + protected String unableToBindValueToParameter$str() { + return "HHH000278: Could not bind value '%s' to parameter: %s; %s"; + } + + public final void unableToBuildEnhancementMetamodel(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToBuildEnhancementMetamodel$str(), arg0); + } + + protected String unableToBuildEnhancementMetamodel$str() { + return "HHH000279: Unable to build enhancement metamodel for %s"; + } + + public final void unableToBuildSessionFactoryUsingMBeanClasspath(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToBuildSessionFactoryUsingMBeanClasspath$str(), arg0); + } + + protected String unableToBuildSessionFactoryUsingMBeanClasspath$str() { + return "HHH000280: Could not build SessionFactory using the MBean classpath - will try again using client classpath: %s"; + } + + public final void unableToCleanUpCallableStatement(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToCleanUpCallableStatement$str(), new Object[0]); + } + + protected String unableToCleanUpCallableStatement$str() { + return "HHH000281: Unable to clean up callable statement"; + } + + public final void unableToCleanUpPreparedStatement(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToCleanUpPreparedStatement$str(), new Object[0]); + } + + protected String unableToCleanUpPreparedStatement$str() { + return "HHH000282: Unable to clean up prepared statement"; + } + + public final void unableToCleanupTemporaryIdTable(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToCleanupTemporaryIdTable$str(), arg0); + } + + protected String unableToCleanupTemporaryIdTable$str() { + return "HHH000283: Unable to cleanup temporary id table after use [%s]"; + } + + public final void unableToCloseConnection(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCloseConnection$str(), new Object[0]); + } + + protected String unableToCloseConnection$str() { + return "HHH000284: Error closing connection"; + } + + public final void unableToCloseInitialContext(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToCloseInitialContext$str(), arg0); + } + + protected String unableToCloseInitialContext$str() { + return "HHH000285: Error closing InitialContext [%s]"; + } + + public final void unableToCloseInputFiles(String arg0, IOException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.unableToCloseInputFiles$str(), arg0); + } + + protected String unableToCloseInputFiles$str() { + return "HHH000286: Error closing input files: %s"; + } + + public final void unableToCloseInputStream(IOException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToCloseInputStream$str(), new Object[0]); + } + + protected String unableToCloseInputStream$str() { + return "HHH000287: Could not close input stream"; + } + + public final void unableToCloseInputStreamForResource(String arg0, IOException arg1) { + super.log.logf(FQCN, Logger.Level.WARN, arg1, this.unableToCloseInputStreamForResource$str(), arg0); + } + + protected String unableToCloseInputStreamForResource$str() { + return "HHH000288: Could not close input stream for %s"; + } + + public final void unableToCloseIterator(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.INFO, arg0, this.unableToCloseIterator$str(), new Object[0]); + } + + protected String unableToCloseIterator$str() { + return "HHH000289: Unable to close iterator"; + } + + public final void unableToCloseJar(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToCloseJar$str(), arg0); + } + + protected String unableToCloseJar$str() { + return "HHH000290: Could not close jar: %s"; + } + + public final void unableToCloseOutputFile(String arg0, IOException arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.unableToCloseOutputFile$str(), arg0); + } + + protected String unableToCloseOutputFile$str() { + return "HHH000291: Error closing output file: %s"; + } + + public final void unableToCloseOutputStream(IOException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToCloseOutputStream$str(), new Object[0]); + } + + protected String unableToCloseOutputStream$str() { + return "HHH000292: IOException occurred closing output stream"; + } + + public final void unableToCloseSession(HibernateException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCloseSession$str(), new Object[0]); + } + + protected String unableToCloseSession$str() { + return "HHH000294: Could not close session"; + } + + public final void unableToCloseSessionDuringRollback(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCloseSessionDuringRollback$str(), new Object[0]); + } + + protected String unableToCloseSessionDuringRollback$str() { + return "HHH000295: Could not close session during rollback"; + } + + public final void unableToCloseStream(IOException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToCloseStream$str(), new Object[0]); + } + + protected String unableToCloseStream$str() { + return "HHH000296: IOException occurred closing stream"; + } + + public final void unableToCloseStreamError(IOException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToCloseStreamError$str(), arg0); + } + + protected String unableToCloseStreamError$str() { + return "HHH000297: Could not close stream on hibernate.properties: %s"; + } + + protected String unableToCommitJta$str() { + return "HHH000298: JTA commit failed"; + } + + public final String unableToCommitJta() { + return String.format(this.getLoggingLocale(), this.unableToCommitJta$str()); + } + + public final void unableToCompleteSchemaUpdate(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCompleteSchemaUpdate$str(), new Object[0]); + } + + protected String unableToCompleteSchemaUpdate$str() { + return "HHH000299: Could not complete schema update"; + } + + public final void unableToCompleteSchemaValidation(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCompleteSchemaValidation$str(), new Object[0]); + } + + protected String unableToCompleteSchemaValidation$str() { + return "HHH000300: Could not complete schema validation"; + } + + public final void unableToConfigureSqlExceptionConverter(HibernateException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToConfigureSqlExceptionConverter$str(), arg0); + } + + protected String unableToConfigureSqlExceptionConverter$str() { + return "HHH000301: Unable to configure SQLExceptionConverter : %s"; + } + + public final void unableToConstructCurrentSessionContext(String arg0, Throwable arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, arg1, this.unableToConstructCurrentSessionContext$str(), arg0); + } + + protected String unableToConstructCurrentSessionContext$str() { + return "HHH000302: Unable to construct current session context [%s]"; + } + + public final void unableToConstructSqlExceptionConverter(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToConstructSqlExceptionConverter$str(), arg0); + } + + protected String unableToConstructSqlExceptionConverter$str() { + return "HHH000303: Unable to construct instance of specified SQLExceptionConverter : %s"; + } + + public final void unableToCopySystemProperties() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToCopySystemProperties$str(), new Object[0]); + } + + protected String unableToCopySystemProperties$str() { + return "HHH000304: Could not copy system properties, system properties will be ignored"; + } + + public final void unableToCreateProxyFactory(String arg0, HibernateException arg1) { + super.log.logf(FQCN, Logger.Level.WARN, arg1, this.unableToCreateProxyFactory$str(), arg0); + } + + protected String unableToCreateProxyFactory$str() { + return "HHH000305: Could not create proxy factory for:%s"; + } + + public final void unableToCreateSchema(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToCreateSchema$str(), new Object[0]); + } + + protected String unableToCreateSchema$str() { + return "HHH000306: Error creating schema "; + } + + public final void unableToDeserializeCache(String arg0, SerializationException arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToDeserializeCache$str(), arg0, arg1); + } + + protected String unableToDeserializeCache$str() { + return "HHH000307: Could not deserialize cache file: %s : %s"; + } + + public final void unableToDestroyCache(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToDestroyCache$str(), arg0); + } + + protected String unableToDestroyCache$str() { + return "HHH000308: Unable to destroy cache: %s"; + } + + public final void unableToDestroyQueryCache(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToDestroyQueryCache$str(), arg0, arg1); + } + + protected String unableToDestroyQueryCache$str() { + return "HHH000309: Unable to destroy query cache: %s: %s"; + } + + public final void unableToDestroyUpdateTimestampsCache(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToDestroyUpdateTimestampsCache$str(), arg0, arg1); + } + + protected String unableToDestroyUpdateTimestampsCache$str() { + return "HHH000310: Unable to destroy update timestamps cache: %s: %s"; + } + + public final void unableToDetermineLockModeValue(String arg0, Object arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToDetermineLockModeValue$str(), arg0, arg1); + } + + protected String unableToDetermineLockModeValue$str() { + return "HHH000311: Unable to determine lock mode value : %s -> %s"; + } + + protected String unableToDetermineTransactionStatus$str() { + return "HHH000312: Could not determine transaction status"; + } + + public final String unableToDetermineTransactionStatus() { + return String.format(this.getLoggingLocale(), this.unableToDetermineTransactionStatus$str()); + } + + protected String unableToDetermineTransactionStatusAfterCommit$str() { + return "HHH000313: Could not determine transaction status after commit"; + } + + public final String unableToDetermineTransactionStatusAfterCommit() { + return String.format(this.getLoggingLocale(), this.unableToDetermineTransactionStatusAfterCommit$str()); + } + + public final void unableToDropTemporaryIdTable(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToDropTemporaryIdTable$str(), arg0); + } + + protected String unableToDropTemporaryIdTable$str() { + return "HHH000314: Unable to drop temporary id table after use [%s]"; + } + + public final void unableToExecuteBatch(Exception arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToExecuteBatch$str(), arg0, arg1); + } + + protected String unableToExecuteBatch$str() { + return "HHH000315: Exception executing batch [%s], SQL: %s"; + } + + public final void unableToExecuteResolver(DialectResolver arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToExecuteResolver$str(), arg0, arg1); + } + + protected String unableToExecuteResolver$str() { + return "HHH000316: Error executing resolver [%s] : %s"; + } + + public final void unableToFindPersistenceXmlInClasspath() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToFindPersistenceXmlInClasspath$str(), new Object[0]); + } + + protected String unableToFindPersistenceXmlInClasspath$str() { + return "HHH000318: Could not find any META-INF/persistence.xml file in the classpath"; + } + + public final void unableToGetDatabaseMetadata(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToGetDatabaseMetadata$str(), new Object[0]); + } + + protected String unableToGetDatabaseMetadata$str() { + return "HHH000319: Could not get database metadata"; + } + + public final void unableToInstantiateConfiguredSchemaNameResolver(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToInstantiateConfiguredSchemaNameResolver$str(), arg0, arg1); + } + + protected String unableToInstantiateConfiguredSchemaNameResolver$str() { + return "HHH000320: Unable to instantiate configured schema name resolver [%s] %s"; + } + + public final void unableToLocateCustomOptimizerClass(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLocateCustomOptimizerClass$str(), arg0); + } + + protected String unableToLocateCustomOptimizerClass$str() { + return "HHH000321: Unable to interpret specified optimizer [%s], falling back to noop"; + } + + public final void unableToInstantiateOptimizer(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToInstantiateOptimizer$str(), arg0); + } + + protected String unableToInstantiateOptimizer$str() { + return "HHH000322: Unable to instantiate specified optimizer [%s], falling back to noop"; + } + + public final void unableToInstantiateUuidGenerationStrategy(Exception arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToInstantiateUuidGenerationStrategy$str(), arg0); + } + + protected String unableToInstantiateUuidGenerationStrategy$str() { + return "HHH000325: Unable to instantiate UUID generation strategy class : %s"; + } + + public final void unableToJoinTransaction(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToJoinTransaction$str(), arg0); + } + + protected String unableToJoinTransaction$str() { + return "HHH000326: Cannot join transaction: do not override %s"; + } + + public final void unableToLoadCommand(HibernateException arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToLoadCommand$str(), arg0); + } + + protected String unableToLoadCommand$str() { + return "HHH000327: Error performing load command : %s"; + } + + public final void unableToLoadDerbyDriver(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLoadDerbyDriver$str(), arg0); + } + + protected String unableToLoadDerbyDriver$str() { + return "HHH000328: Unable to load/access derby driver class sysinfo to check versions : %s"; + } + + public final void unableToLoadProperties() { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToLoadProperties$str(), new Object[0]); + } + + protected String unableToLoadProperties$str() { + return "HHH000329: Problem loading properties from hibernate.properties"; + } + + protected String unableToLocateConfigFile$str() { + return "HHH000330: Unable to locate config file: %s"; + } + + public final String unableToLocateConfigFile(String arg0) { + return String.format(this.getLoggingLocale(), this.unableToLocateConfigFile$str(), arg0); + } + + public final void unableToLocateConfiguredSchemaNameResolver(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLocateConfiguredSchemaNameResolver$str(), arg0, arg1); + } + + protected String unableToLocateConfiguredSchemaNameResolver$str() { + return "HHH000331: Unable to locate configured schema name resolver class [%s] %s"; + } + + public final void unableToLocateMBeanServer() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLocateMBeanServer$str(), new Object[0]); + } + + protected String unableToLocateMBeanServer$str() { + return "HHH000332: Unable to locate MBeanServer on JMX service shutdown"; + } + + public final void unableToLocateUuidGenerationStrategy(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLocateUuidGenerationStrategy$str(), arg0); + } + + protected String unableToLocateUuidGenerationStrategy$str() { + return "HHH000334: Unable to locate requested UUID generation strategy class : %s"; + } + + public final void unableToLogSqlWarnings(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToLogSqlWarnings$str(), arg0); + } + + protected String unableToLogSqlWarnings$str() { + return "HHH000335: Unable to log SQLWarnings : %s"; + } + + public final void unableToLogWarnings(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToLogWarnings$str(), new Object[0]); + } + + protected String unableToLogWarnings$str() { + return "HHH000336: Could not log warnings"; + } + + public final void unableToMarkForRollbackOnPersistenceException(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToMarkForRollbackOnPersistenceException$str(), new Object[0]); + } + + protected String unableToMarkForRollbackOnPersistenceException$str() { + return "HHH000337: Unable to mark for rollback on PersistenceException: "; + } + + public final void unableToMarkForRollbackOnTransientObjectException(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToMarkForRollbackOnTransientObjectException$str(), new Object[0]); + } + + protected String unableToMarkForRollbackOnTransientObjectException$str() { + return "HHH000338: Unable to mark for rollback on TransientObjectException: "; + } + + public final void unableToObjectConnectionMetadata(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToObjectConnectionMetadata$str(), arg0); + } + + protected String unableToObjectConnectionMetadata$str() { + return "HHH000339: Could not obtain connection metadata: %s"; + } + + public final void unableToObjectConnectionToQueryMetadata(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToObjectConnectionToQueryMetadata$str(), arg0); + } + + protected String unableToObjectConnectionToQueryMetadata$str() { + return "HHH000340: Could not obtain connection to query metadata: %s"; + } + + public final void unableToObtainConnectionMetadata(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToObtainConnectionMetadata$str(), arg0); + } + + protected String unableToObtainConnectionMetadata$str() { + return "HHH000341: Could not obtain connection metadata : %s"; + } + + public final void unableToObtainConnectionToQueryMetadata(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToObtainConnectionToQueryMetadata$str(), arg0); + } + + protected String unableToObtainConnectionToQueryMetadata$str() { + return "HHH000342: Could not obtain connection to query metadata : %s"; + } + + public final void unableToObtainInitialContext(NamingException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToObtainInitialContext$str(), new Object[0]); + } + + protected String unableToObtainInitialContext$str() { + return "HHH000343: Could not obtain initial context"; + } + + public final void unableToParseMetadata(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToParseMetadata$str(), arg0); + } + + protected String unableToParseMetadata$str() { + return "HHH000344: Could not parse the package-level metadata [%s]"; + } + + protected String unableToPerformJdbcCommit$str() { + return "HHH000345: JDBC commit failed"; + } + + public final String unableToPerformJdbcCommit() { + return String.format(this.getLoggingLocale(), this.unableToPerformJdbcCommit$str()); + } + + public final void unableToPerformManagedFlush(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToPerformManagedFlush$str(), arg0); + } + + protected String unableToPerformManagedFlush$str() { + return "HHH000346: Error during managed flush [%s]"; + } + + protected String unableToQueryDatabaseMetadata$str() { + return "HHH000347: Unable to query java.sql.DatabaseMetaData"; + } + + public final String unableToQueryDatabaseMetadata() { + return String.format(this.getLoggingLocale(), this.unableToQueryDatabaseMetadata$str()); + } + + public final void unableToReadClass(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToReadClass$str(), arg0); + } + + protected String unableToReadClass$str() { + return "HHH000348: Unable to read class: %s"; + } + + public final void unableToReadColumnValueFromResultSet(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToReadColumnValueFromResultSet$str(), arg0, arg1); + } + + protected String unableToReadColumnValueFromResultSet$str() { + return "HHH000349: Could not read column value from result set: %s; %s"; + } + + protected String unableToReadHiValue$str() { + return "HHH000350: Could not read a hi value - you need to populate the table: %s"; + } + + public final String unableToReadHiValue(String arg0) { + return String.format(this.getLoggingLocale(), this.unableToReadHiValue$str(), arg0); + } + + public final void unableToReadOrInitHiValue(SQLException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToReadOrInitHiValue$str(), new Object[0]); + } + + protected String unableToReadOrInitHiValue$str() { + return "HHH000351: Could not read or init a hi value"; + } + + public final void unableToReleaseBatchStatement() { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToReleaseBatchStatement$str(), new Object[0]); + } + + protected String unableToReleaseBatchStatement$str() { + return "HHH000352: Unable to release batch statement..."; + } + + public final void unableToReleaseCacheLock(CacheException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unableToReleaseCacheLock$str(), arg0); + } + + protected String unableToReleaseCacheLock$str() { + return "HHH000353: Could not release a cache lock : %s"; + } + + public final void unableToReleaseContext(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToReleaseContext$str(), arg0); + } + + protected String unableToReleaseContext$str() { + return "HHH000354: Unable to release initial context: %s"; + } + + public final void unableToReleaseCreatedMBeanServer(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToReleaseCreatedMBeanServer$str(), arg0); + } + + protected String unableToReleaseCreatedMBeanServer$str() { + return "HHH000355: Unable to release created MBeanServer : %s"; + } + + public final void unableToReleaseIsolatedConnection(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToReleaseIsolatedConnection$str(), arg0); + } + + protected String unableToReleaseIsolatedConnection$str() { + return "HHH000356: Unable to release isolated connection [%s]"; + } + + public final void unableToReleaseTypeInfoResultSet() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToReleaseTypeInfoResultSet$str(), new Object[0]); + } + + protected String unableToReleaseTypeInfoResultSet$str() { + return "HHH000357: Unable to release type info result set"; + } + + public final void unableToRemoveBagJoinFetch() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToRemoveBagJoinFetch$str(), new Object[0]); + } + + protected String unableToRemoveBagJoinFetch$str() { + return "HHH000358: Unable to erase previously added bag join fetch"; + } + + public final void unableToResolveAggregateFunction(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToResolveAggregateFunction$str(), arg0); + } + + protected String unableToResolveAggregateFunction$str() { + return "HHH000359: Could not resolve aggregate function [%s]; using standard definition"; + } + + public final void unableToResolveMappingFile(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToResolveMappingFile$str(), arg0); + } + + protected String unableToResolveMappingFile$str() { + return "HHH000360: Unable to resolve mapping file [%s]"; + } + + public final void unableToRetrieveCache(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToRetrieveCache$str(), arg0, arg1); + } + + protected String unableToRetrieveCache$str() { + return "HHH000361: Unable to retrieve cache from JNDI [%s]: %s"; + } + + public final void unableToRetrieveTypeInfoResultSet(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToRetrieveTypeInfoResultSet$str(), arg0); + } + + protected String unableToRetrieveTypeInfoResultSet$str() { + return "HHH000362: Unable to retrieve type info result set : %s"; + } + + public final void unableToRollbackConnection(Exception arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToRollbackConnection$str(), arg0); + } + + protected String unableToRollbackConnection$str() { + return "HHH000363: Unable to rollback connection on exception [%s]"; + } + + public final void unableToRollbackIsolatedTransaction(Exception arg0, Exception arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToRollbackIsolatedTransaction$str(), arg0, arg1); + } + + protected String unableToRollbackIsolatedTransaction$str() { + return "HHH000364: Unable to rollback isolated transaction on error [%s] : [%s]"; + } + + protected String unableToRollbackJta$str() { + return "HHH000365: JTA rollback failed"; + } + + public final String unableToRollbackJta() { + return String.format(this.getLoggingLocale(), this.unableToRollbackJta$str()); + } + + public final void unableToRunSchemaUpdate(Exception arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToRunSchemaUpdate$str(), new Object[0]); + } + + protected String unableToRunSchemaUpdate$str() { + return "HHH000366: Error running schema update"; + } + + public final void unableToSetTransactionToRollbackOnly(SystemException arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, arg0, this.unableToSetTransactionToRollbackOnly$str(), new Object[0]); + } + + protected String unableToSetTransactionToRollbackOnly$str() { + return "HHH000367: Could not set transaction to rollback only"; + } + + public final void unableToStopHibernateService(Exception arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToStopHibernateService$str(), new Object[0]); + } + + protected String unableToStopHibernateService$str() { + return "HHH000368: Exception while stopping service"; + } + + public final void unableToStopService(Class arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToStopService$str(), arg0, arg1); + } + + protected String unableToStopService$str() { + return "HHH000369: Error stopping service [%s] : %s"; + } + + public final void unableToSwitchToMethodUsingColumnIndex(Method arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unableToSwitchToMethodUsingColumnIndex$str(), arg0); + } + + protected String unableToSwitchToMethodUsingColumnIndex$str() { + return "HHH000370: Exception switching from method: [%s] to a method using the column index. Reverting to using: [% arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unknownSqlServerVersion$str(), arg0, arg1); + } + + protected String unknownSqlServerVersion$str() { + return "HHH000385: Unknown Microsoft SQL Server major version [%s] using [%s] dialect"; + } + + public final void unregisteredResultSetWithoutStatement() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unregisteredResultSetWithoutStatement$str(), new Object[0]); + } + + protected String unregisteredResultSetWithoutStatement$str() { + return "HHH000386: ResultSet had no statement associated with it, but was not yet registered"; + } + + public final void unregisteredStatement() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.unregisteredStatement$str(), new Object[0]); + } + + protected String unregisteredStatement$str() { + return "HHH000387: ResultSet's statement was not registered"; + } + + public final void unsuccessful(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unsuccessful$str(), arg0); + } + + protected String unsuccessful$str() { + return "HHH000388: Unsuccessful: %s"; + } + + public final void unsuccessfulCreate(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unsuccessfulCreate$str(), arg0); + } + + protected String unsuccessfulCreate$str() { + return "HHH000389: Unsuccessful: %s"; + } + + public final void unsupportedAfterStatement() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedAfterStatement$str(), new Object[0]); + } + + protected String unsupportedAfterStatement$str() { + return "HHH000390: Overriding release mode as connection provider does not support 'after_statement'"; + } + + public final void unsupportedIngresVersion() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedIngresVersion$str(), new Object[0]); + } + + protected String unsupportedIngresVersion$str() { + return "HHH000391: Ingres 10 is not yet fully supported; using Ingres 9.3 dialect"; + } + + public final void unsupportedInitialValue(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedInitialValue$str(), arg0); + } + + protected String unsupportedInitialValue$str() { + return "HHH000392: Hibernate does not support SequenceGenerator.initialValue() unless '%s' set"; + } + + public final void unsupportedMultiTableBulkHqlJpaql(int arg0, int arg1, int arg2) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedMultiTableBulkHqlJpaql$str(), arg0, arg1, arg2); + } + + protected String unsupportedMultiTableBulkHqlJpaql$str() { + return "HHH000393: The %s.%s.%s version of H2 implements temporary table creation such that it commits current transaction; multi-table, bulk hql/jpaql will not work properly"; + } + + public final void unsupportedOracleVersion() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedOracleVersion$str(), new Object[0]); + } + + protected String unsupportedOracleVersion$str() { + return "HHH000394: Oracle 11g is not yet fully supported; using Oracle 10g dialect"; + } + + public final void unsupportedProperty(Object arg0, Object arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedProperty$str(), arg0, arg1); + } + + protected String unsupportedProperty$str() { + return "HHH000395: Usage of obsolete property: %s no longer supported, use: %s"; + } + + public final void updatingSchema() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.updatingSchema$str(), new Object[0]); + } + + protected String updatingSchema$str() { + return "HHH000396: Updating schema"; + } + + public final void usingAstQueryTranslatorFactory() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingAstQueryTranslatorFactory$str(), new Object[0]); + } + + protected String usingAstQueryTranslatorFactory$str() { + return "HHH000397: Using ASTQueryTranslatorFactory"; + } + + public final void usingDefaultIdGeneratorSegmentValue(String arg0, String arg1, String arg2) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingDefaultIdGeneratorSegmentValue$str(), arg0, arg1, arg2); + } + + protected String usingDefaultIdGeneratorSegmentValue$str() { + return "HHH000398: Explicit segment value for id generator [%s.%s] suggested; using default [%s]"; + } + + public final void usingDefaultTransactionStrategy() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingDefaultTransactionStrategy$str(), new Object[0]); + } + + protected String usingDefaultTransactionStrategy$str() { + return "HHH000399: Using default transaction strategy (direct JDBC transactions)"; + } + + public final void usingDialect(Dialect arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingDialect$str(), arg0); + } + + protected String usingDialect$str() { + return "HHH000400: Using dialect: %s"; + } + + public final void usingOldDtd() { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.usingOldDtd$str(), new Object[0]); + } + + protected String usingOldDtd$str() { + return "HHH000404: Don't use old DTDs, read the Hibernate 3.x Migration Guide!"; + } + + public final void usingReflectionOptimizer() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingReflectionOptimizer$str(), new Object[0]); + } + + protected String usingReflectionOptimizer$str() { + return "HHH000406: Using bytecode reflection optimizer"; + } + + public final void usingStreams() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingStreams$str(), new Object[0]); + } + + protected String usingStreams$str() { + return "HHH000407: Using java.io streams to persist binary types"; + } + + public final void usingTimestampWorkaround() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.usingTimestampWorkaround$str(), new Object[0]); + } + + protected String usingTimestampWorkaround$str() { + return "HHH000408: Using workaround for JVM bug in java.sql.Timestamp"; + } + + public final void usingUuidHexGenerator(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.usingUuidHexGenerator$str(), arg0, arg1); + } + + protected String usingUuidHexGenerator$str() { + return "HHH000409: Using %s which does not generate IETF RFC 4122 compliant UUID values; consider using %s instead"; + } + + public final void validatorNotFound() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.validatorNotFound$str(), new Object[0]); + } + + protected String validatorNotFound$str() { + return "HHH000410: Hibernate Validator not found: ignoring"; + } + + public final void version(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.version$str(), arg0); + } + + protected String version$str() { + return "HHH000412: Hibernate Core {%s}"; + } + + public final void warningsCreatingTempTable(SQLWarning arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.warningsCreatingTempTable$str(), arg0); + } + + protected String warningsCreatingTempTable$str() { + return "HHH000413: Warnings creating temp table : %s"; + } + + public final void willNotRegisterListeners() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.willNotRegisterListeners$str(), new Object[0]); + } + + protected String willNotRegisterListeners$str() { + return "HHH000414: Property hibernate.search.autoregister_listeners is set to false. No attempt will be made to register Hibernate Search event listeners."; + } + + public final void writeLocksNotSupported(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.writeLocksNotSupported$str(), arg0); + } + + protected String writeLocksNotSupported$str() { + return "HHH000416: Write locks via update not supported for non-versioned entities [%s]"; + } + + public final void writingGeneratedSchemaToFile(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.writingGeneratedSchemaToFile$str(), arg0); + } + + protected String writingGeneratedSchemaToFile$str() { + return "HHH000417: Writing generated schema to file: %s"; + } + + public final void addingOverrideFor(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.addingOverrideFor$str(), arg0, arg1); + } + + protected String addingOverrideFor$str() { + return "HHH000418: Adding override for %s: %s"; + } + + public final void resolvedSqlTypeDescriptorForDifferentSqlCode(String arg0, String arg1, String arg2, String arg3) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.resolvedSqlTypeDescriptorForDifferentSqlCode$str(), new Object[]{arg0, arg1, arg2, arg3}); + } + + protected String resolvedSqlTypeDescriptorForDifferentSqlCode$str() { + return "HHH000419: Resolved SqlTypeDescriptor is for a different SQL code. %s has sqlCode=%s; type override %s has sqlCode=%s"; + } + + public final void closingUnreleasedBatch() { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.closingUnreleasedBatch$str(), new Object[0]); + } + + protected String closingUnreleasedBatch$str() { + return "HHH000420: Closing un-released batch"; + } + + public final void disablingContextualLOBCreation(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.disablingContextualLOBCreation$str(), arg0); + } + + protected String disablingContextualLOBCreation$str() { + return "HHH000421: Disabling contextual LOB creation as %s is true"; + } + + public final void disablingContextualLOBCreationSinceConnectionNull() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.disablingContextualLOBCreationSinceConnectionNull$str(), new Object[0]); + } + + protected String disablingContextualLOBCreationSinceConnectionNull$str() { + return "HHH000422: Disabling contextual LOB creation as connection was null"; + } + + public final void disablingContextualLOBCreationSinceOldJdbcVersion(int arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.disablingContextualLOBCreationSinceOldJdbcVersion$str(), arg0); + } + + protected String disablingContextualLOBCreationSinceOldJdbcVersion$str() { + return "HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [%s] less than 4"; + } + + public final void disablingContextualLOBCreationSinceCreateClobFailed(Throwable arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.disablingContextualLOBCreationSinceCreateClobFailed$str(), arg0); + } + + protected String disablingContextualLOBCreationSinceCreateClobFailed$str() { + return "HHH000424: Disabling contextual LOB creation as createClob() method threw error : %s"; + } + + public final void unableToCloseSessionButSwallowingError(HibernateException arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.unableToCloseSessionButSwallowingError$str(), arg0); + } + + protected String unableToCloseSessionButSwallowingError$str() { + return "HHH000425: Could not close session; swallowing exception[%s] as transaction completed"; + } + + public final void setManagerLookupClass() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.setManagerLookupClass$str(), new Object[0]); + } + + protected String setManagerLookupClass$str() { + return "HHH000426: You should set hibernate.transaction.jta.platform if cache is enabled"; + } + + public final void legacyTransactionManagerStrategy(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.legacyTransactionManagerStrategy$str(), arg0, arg1); + } + + protected String legacyTransactionManagerStrategy$str() { + return "HHH000428: Encountered legacy TransactionManagerLookup specified; convert to newer %s contract specified via %s setting"; + } + + public final void entityIdentifierValueBindingExists(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.entityIdentifierValueBindingExists$str(), arg0); + } + + protected String entityIdentifierValueBindingExists$str() { + return "HHH000429: Setting entity-identifier value binding where one already existed : %s."; + } + + public final void deprecatedDerbyDialect() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedDerbyDialect$str(), new Object[0]); + } + + protected String deprecatedDerbyDialect$str() { + return "HHH000430: The DerbyDialect dialect has been deprecated; use one of the version-specific dialects instead"; + } + + public final void undeterminedH2Version() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.undeterminedH2Version$str(), new Object[0]); + } + + protected String undeterminedH2Version$str() { + return "HHH000431: Unable to determine H2 database version, certain features may not work"; + } + + public final void noColumnsSpecifiedForIndex(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.noColumnsSpecifiedForIndex$str(), arg0, arg1); + } + + protected String noColumnsSpecifiedForIndex$str() { + return "HHH000432: There were not column names specified for index %s on table %s"; + } + + public final void timestampCachePuts(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.timestampCachePuts$str(), arg0); + } + + protected String timestampCachePuts$str() { + return "HHH000433: update timestamps cache puts: %s"; + } + + public final void timestampCacheHits(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.timestampCacheHits$str(), arg0); + } + + protected String timestampCacheHits$str() { + return "HHH000434: update timestamps cache hits: %s"; + } + + public final void timestampCacheMisses(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.timestampCacheMisses$str(), arg0); + } + + protected String timestampCacheMisses$str() { + return "HHH000435: update timestamps cache misses: %s"; + } + + public final void entityManagerFactoryAlreadyRegistered(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.entityManagerFactoryAlreadyRegistered$str(), arg0, arg1); + } + + protected String entityManagerFactoryAlreadyRegistered$str() { + return "HHH000436: Entity manager factory name (%s) is already registered. If entity manager will be clustered or passivated, specify a unique value for property '%s'"; + } + + public final void cannotResolveNonNullableTransientDependencies(String arg0, Set arg1, Set arg2) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.cannotResolveNonNullableTransientDependencies$str(), arg0, arg1, arg2); + } + + protected String cannotResolveNonNullableTransientDependencies$str() { + return "HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.\n\tUnsaved transient entity: (%s)\n\tDependent entities: (%s)\n\tNon-nullable association(s): (%s)"; + } + + public final void naturalIdCachePuts(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.naturalIdCachePuts$str(), arg0); + } + + protected String naturalIdCachePuts$str() { + return "HHH000438: NaturalId cache puts: %s"; + } + + public final void naturalIdCacheHits(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.naturalIdCacheHits$str(), arg0); + } + + protected String naturalIdCacheHits$str() { + return "HHH000439: NaturalId cache hits: %s"; + } + + public final void naturalIdCacheMisses(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.naturalIdCacheMisses$str(), arg0); + } + + protected String naturalIdCacheMisses$str() { + return "HHH000440: NaturalId cache misses: %s"; + } + + public final void naturalIdMaxQueryTime(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.naturalIdMaxQueryTime$str(), arg0); + } + + protected String naturalIdMaxQueryTime$str() { + return "HHH000441: Max NaturalId query time: %sms"; + } + + public final void naturalIdQueriesExecuted(long arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.naturalIdQueriesExecuted$str(), arg0); + } + + protected String naturalIdQueriesExecuted$str() { + return "HHH000442: NaturalId queries executed to database: %s"; + } + + public final void tooManyInExpressions(String arg0, int arg1, String arg2, int arg3) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.tooManyInExpressions$str(), new Object[]{arg0, arg1, arg2, arg3}); + } + + protected String tooManyInExpressions$str() { + return "HHH000443: Dialect [%s] limits the number of elements in an IN predicate to %s entries. However, the given parameter list [%s] contained %s entries, which will likely cause failures to execute the query in the database"; + } + + public final void usingFollowOnLocking() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.usingFollowOnLocking$str(), new Object[0]); + } + + protected String usingFollowOnLocking$str() { + return "HHH000444: Encountered request for locking however dialect reports that database prefers locking be done in a separate select (follow-on locking); results will be locked after initial query executes"; + } + + public final void aliasSpecificLockingWithFollowOnLocking(LockMode arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.aliasSpecificLockingWithFollowOnLocking$str(), arg0); + } + + protected String aliasSpecificLockingWithFollowOnLocking$str() { + return "HHH000445: Alias-specific lock modes requested, which is not currently supported with follow-on locking; all acquired locks will be [%s]"; + } + + public final void embedXmlAttributesNoLongerSupported() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.embedXmlAttributesNoLongerSupported$str(), new Object[0]); + } + + protected String embedXmlAttributesNoLongerSupported$str() { + return "HHH000446: embed-xml attributes were intended to be used for DOM4J entity mode. Since that entity mode has been removed, embed-xml attributes are no longer supported and should be removed from mappings."; + } + + public final void explicitSkipLockedLockCombo() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.explicitSkipLockedLockCombo$str(), new Object[0]); + } + + protected String explicitSkipLockedLockCombo$str() { + return "HHH000447: Explicit use of UPGRADE_SKIPLOCKED in lock() calls is not recommended; use normal UPGRADE locking instead"; + } + + public final void multipleValidationModes(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.multipleValidationModes$str(), arg0); + } + + protected String multipleValidationModes$str() { + return "HHH000448: 'javax.persistence.validation.mode' named multiple values : %s"; + } + + public final void nonCompliantMapConversion(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.nonCompliantMapConversion$str(), arg0); + } + + protected String nonCompliantMapConversion$str() { + return "HHH000449: @Convert annotation applied to Map attribute [%s] did not explicitly specify attributeName using 'key'/'value' as required by spec; attempting to DoTheRightThing"; + } + + public final void alternateServiceRole(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.alternateServiceRole$str(), arg0, arg1); + } + + protected String alternateServiceRole$str() { + return "HHH000450: Encountered request for Service by non-primary service role [%s -> %s]; please update usage"; + } + + public final void rollbackFromBackgroundThread(int arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.rollbackFromBackgroundThread$str(), arg0); + } + + protected String rollbackFromBackgroundThread$str() { + return "HHH000451: Transaction afterCompletion called by a background thread; delaying afterCompletion processing until the original thread can handle it. [status=%s]"; + } + + public final void unableToLoadScannedClassOrResource(Exception arg0) { + super.log.logf(FQCN, Logger.Level.WARN, arg0, this.unableToLoadScannedClassOrResource$str(), new Object[0]); + } + + protected String unableToLoadScannedClassOrResource$str() { + return "HHH000452: Exception while loading a class or resource found during scanning"; + } + + public final void unableToDiscoverOsgiService(String arg0, Exception arg1) { + super.log.logf(FQCN, Logger.Level.WARN, arg1, this.unableToDiscoverOsgiService$str(), arg0); + } + + protected String unableToDiscoverOsgiService$str() { + return "HHH000453: Exception while discovering OSGi service implementations : %s"; + } + + public final void deprecatedManyToManyOuterJoin() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedManyToManyOuterJoin$str(), new Object[0]); + } + + protected String deprecatedManyToManyOuterJoin$str() { + return "HHH000454: The outer-join attribute on has been deprecated. Instead of outer-join=\"false\", use lazy=\"extra\" with , , , , or , which will only initialize entities (not as a proxy) as needed."; + } + + public final void deprecatedManyToManyFetch() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.deprecatedManyToManyFetch$str(), new Object[0]); + } + + protected String deprecatedManyToManyFetch$str() { + return "HHH000455: The fetch attribute on has been deprecated. Instead of fetch=\"select\", use lazy=\"extra\" with , , , , or , which will only initialize entities (not as a proxy) as needed."; + } + + public final void unsupportedNamedParameters() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unsupportedNamedParameters$str(), new Object[0]); + } + + protected String unsupportedNamedParameters$str() { + return "HHH000456: Named parameters are used for a callable statement, but database metadata indicates named parameters are not supported."; + } + + public final void applyingExplicitDiscriminatorColumnForJoined(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.applyingExplicitDiscriminatorColumnForJoined$str(), arg0, arg1); + } + + protected String applyingExplicitDiscriminatorColumnForJoined$str() { + return "HHH000457: Joined inheritance hierarchy [%1$s] defined explicit @DiscriminatorColumn. Legacy Hibernate behavior was to ignore the @DiscriminatorColumn. However, as part of issue HHH-6911 we now apply the explicit @DiscriminatorColumn. If you would prefer the legacy behavior, enable the `%2$s` setting (%2$s=true)"; + } + + public final void creatingPooledLoOptimizer(int arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.DEBUG, (Throwable)null, this.creatingPooledLoOptimizer$str(), arg0, arg1); + } + + protected String creatingPooledLoOptimizer$str() { + return "HHH000467: Creating pooled optimizer (lo) with [incrementSize=%s; returnClass=%s]"; + } + + public final void logBadHbmAttributeConverterType(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.logBadHbmAttributeConverterType$str(), arg0, arg1); + } + + protected String logBadHbmAttributeConverterType$str() { + return "HHH000468: Unable to interpret type [%s] as an AttributeConverter due to an exception : %s"; + } + + protected String usingStoppedClassLoaderService$str() { + return "HHH000469: The ClassLoaderService can not be reused. This instance was stopped already."; + } + + public final HibernateException usingStoppedClassLoaderService() { + HibernateException result = new HibernateException(String.format(this.getLoggingLocale(), this.usingStoppedClassLoaderService$str())); + StackTraceElement[] st = result.getStackTrace(); + result.setStackTrace((StackTraceElement[])Arrays.copyOfRange(st, 1, st.length)); + return result; + } + + public final void logUnexpectedSessionInCollectionNotConnected(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.logUnexpectedSessionInCollectionNotConnected$str(), arg0); + } + + protected String logUnexpectedSessionInCollectionNotConnected$str() { + return "HHH000470: An unexpected session is defined for a collection, but the collection is not connected to that session. A persistent collection may only be associated with one session at a time. Overwriting session. %s"; + } + + public final void logCannotUnsetUnexpectedSessionInCollection(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.logCannotUnsetUnexpectedSessionInCollection$str(), arg0); + } + + protected String logCannotUnsetUnexpectedSessionInCollection$str() { + return "HHH000471: Cannot unset session in a collection because an unexpected session is defined. A persistent collection may only be associated with one session at a time. %s"; + } + + public final void hikariProviderClassNotFound() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.hikariProviderClassNotFound$str(), new Object[0]); + } + + protected String hikariProviderClassNotFound$str() { + return "HHH000472: Hikari properties were encountered, but the Hikari ConnectionProvider was not found on the classpath; these properties are going to be ignored."; + } + + public final void cachedFileObsolete(File arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.cachedFileObsolete$str(), arg0); + } + + protected String cachedFileObsolete$str() { + return "HHH000473: Omitting cached file [%s] as the mapping file is newer"; + } + + protected String ambiguousPropertyMethods$str() { + return "HHH000474: Ambiguous persistent property methods detected on %s; mark one as @Transient : [%s] and [%s]"; + } + + public final String ambiguousPropertyMethods(String arg0, String arg1, String arg2) { + return String.format(this.getLoggingLocale(), this.ambiguousPropertyMethods$str(), arg0, arg1, arg2); + } + + public final void logCannotLocateIndexColumnInformation(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.logCannotLocateIndexColumnInformation$str(), arg0, arg1); + } + + protected String logCannotLocateIndexColumnInformation$str() { + return "HHH000475: Cannot locate column information using identifier [%s]; ignoring index [%s]"; + } + + public final void executingImportScript(String arg0) { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.executingImportScript$str(), arg0); + } + + protected String executingImportScript$str() { + return "HHH000476: Executing import script '%s'"; + } + + public final void startingDelayedSchemaDrop() { + super.log.logf(FQCN, Logger.Level.INFO, (Throwable)null, this.startingDelayedSchemaDrop$str(), new Object[0]); + } + + protected String startingDelayedSchemaDrop$str() { + return "HHH000477: Starting delayed drop of schema as part of SessionFactory shut-down'"; + } + + public final void unsuccessfulSchemaManagementCommand(String arg0) { + super.log.logf(FQCN, Logger.Level.ERROR, (Throwable)null, this.unsuccessfulSchemaManagementCommand$str(), arg0); + } + + protected String unsuccessfulSchemaManagementCommand$str() { + return "HHH000478: Unsuccessful: %s"; + } + + protected String collectionNotProcessedByFlush$str() { + return "HHH000479: Collection [%s] was not processed by flush(). This is likely due to unsafe use of the session (e.g. used in multiple threads concurrently, updates during entity lifecycle hooks)."; + } + + public final String collectionNotProcessedByFlush(String arg0) { + return String.format(this.getLoggingLocale(), this.collectionNotProcessedByFlush$str(), arg0); + } + + public final void stalePersistenceContextInEntityEntry(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.stalePersistenceContextInEntityEntry$str(), arg0); + } + + protected String stalePersistenceContextInEntityEntry$str() { + return "HHH000480: A ManagedEntity was associated with a stale PersistenceContext. A ManagedEntity may only be associated with one PersistenceContext at a time; %s"; + } + + public final void unknownJavaTypeNoEqualsHashCode(Class arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.unknownJavaTypeNoEqualsHashCode$str(), arg0); + } + + protected String unknownJavaTypeNoEqualsHashCode$str() { + return "HHH000481: Encountered Java type [%s] for which we could not locate a JavaTypeDescriptor and which does not appear to implement equals and/or hashCode. This can lead to significant performance problems when performing equality/dirty checking involving this Java type. Consider registering a custom JavaTypeDescriptor or at least implementing equals/hashCode."; + } + + public final void cacheOrCacheableAnnotationOnNonRoot(String arg0) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.cacheOrCacheableAnnotationOnNonRoot$str(), arg0); + } + + protected String cacheOrCacheableAnnotationOnNonRoot$str() { + return "HHH000482: @javax.persistence.Cacheable or @org.hibernate.annotations.Cache used on a non-root entity: ignored for %s"; + } + + public final void emptyCompositesEnabled() { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.emptyCompositesEnabled$str(), new Object[0]); + } + + protected String emptyCompositesEnabled$str() { + return "HHH000483: An experimental feature has been enabled (hibernate.create_empty_composites.enabled=true) that instantiates empty composite/embedded objects when all of its attribute values are null. This feature has known issues and should not be used in production until it is stabilized. See Hibernate Jira issue HHH-11936 for details."; + } + + public final void immutableEntityUpdateQuery(String arg0, String arg1) { + super.log.logf(FQCN, Logger.Level.WARN, (Throwable)null, this.immutableEntityUpdateQuery$str(), arg0, arg1); + } + + protected String immutableEntityUpdateQuery$str() { + return "HHH000487: The query: [%s] attempts to update an immutable entity: %s"; + } + + static { + LOCALE = Locale.ROOT; + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/HibernateNonstopCacheExceptionHandler.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/HibernateNonstopCacheExceptionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..9e2a6825afb7fdbb98bfb1cfe9a49d3bf8cbbd32 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/HibernateNonstopCacheExceptionHandler.java @@ -0,0 +1,32 @@ +package net.oschina.j2cache.hibernate5.nonstop; + +import net.oschina.j2cache.hibernate5.log.J2CacheMessageLogger; +import org.jboss.logging.Logger; + +public final class HibernateNonstopCacheExceptionHandler { + + public static final String HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY = "J2Cache.hibernate.propagateNonStopCacheException"; + public static final String HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY = "J2Cache.hibernate.logNonStopCacheExceptionStackTrace"; + + private static final J2CacheMessageLogger LOG = Logger.getMessageLogger(J2CacheMessageLogger.class, HibernateNonstopCacheExceptionHandler.class.getName()); + private static final HibernateNonstopCacheExceptionHandler INSTANCE = new HibernateNonstopCacheExceptionHandler(); + + private HibernateNonstopCacheExceptionHandler() { + } + + public static HibernateNonstopCacheExceptionHandler getInstance() { + return INSTANCE; + } + + public void handleNonstopCacheException(NonStopCacheException nonStopCacheException) { + if (Boolean.getBoolean(HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY)) { + throw nonStopCacheException; + } else { + if (Boolean.getBoolean(HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY)) { + LOG.debug("Ignoring NonstopCacheException - " + nonStopCacheException.getMessage(), nonStopCacheException); + } else { + LOG.debug("Ignoring NonstopCacheException - " + nonStopCacheException.getMessage()); + } + } + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonStopCacheException.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonStopCacheException.java new file mode 100644 index 0000000000000000000000000000000000000000..68bb0c2f0bef41669a38e119a7ddd711251d0675 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonStopCacheException.java @@ -0,0 +1,18 @@ +package net.oschina.j2cache.hibernate5.nonstop; + +import org.hibernate.cache.CacheException; + +public class NonStopCacheException extends CacheException { + + public NonStopCacheException(final String message, final Throwable cause) { + super(message, cause); + } + + public NonStopCacheException(final String message) { + super(message); + } + + public NonStopCacheException(final Throwable cause) { + super(cause); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareCollectionRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareCollectionRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..c720711c32c810e4491942b92c323d2c3af33337 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareCollectionRegionAccessStrategy.java @@ -0,0 +1,142 @@ +package net.oschina.j2cache.hibernate5.nonstop; + + +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CollectionRegion; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.collection.CollectionPersister; + +public class NonstopAwareCollectionRegionAccessStrategy implements CollectionRegionAccessStrategy { + + private final CollectionRegionAccessStrategy actualStrategy; + private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler; + + public NonstopAwareCollectionRegionAccessStrategy(CollectionRegionAccessStrategy actualStrategy, HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) { + this.actualStrategy = actualStrategy; + this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler; + } + + @Override + public CollectionRegion getRegion() { + return this.actualStrategy.getRegion(); + } + + @Override + public void evict(Object key) throws CacheException { + try { + this.actualStrategy.evict(key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void evictAll() throws CacheException { + try { + this.actualStrategy.evictAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + try { + return this.actualStrategy.get(session, key, txTimestamp); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + try { + return this.actualStrategy.lockItem(session, key, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public SoftLock lockRegion() throws CacheException { + try { + return this.actualStrategy.lockRegion(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) + throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version, minimalPutOverride); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + try { + this.actualStrategy.remove(session, key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void removeAll() throws CacheException { + try { + this.actualStrategy.removeAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockItem(session, key, lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockRegion(SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockRegion(lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareEntityRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareEntityRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..98db36f7de258156c41e567b6a426629b30033d8 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareEntityRegionAccessStrategy.java @@ -0,0 +1,180 @@ +package net.oschina.j2cache.hibernate5.nonstop; + +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + +public class NonstopAwareEntityRegionAccessStrategy implements EntityRegionAccessStrategy { + + private final EntityRegionAccessStrategy actualStrategy; + private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler; + + public NonstopAwareEntityRegionAccessStrategy(EntityRegionAccessStrategy actualStrategy, HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) { + this.actualStrategy = actualStrategy; + this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler; + } + + @Override + public EntityRegion getRegion() { + return this.actualStrategy.getRegion(); + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + try { + return this.actualStrategy.afterInsert(session, key, value, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { + try { + return this.actualStrategy.afterUpdate(session, key, value, currentVersion, previousVersion, lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public void evict(Object key) throws CacheException { + try { + this.actualStrategy.evict(key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void evictAll() throws CacheException { + try { + this.actualStrategy.evictAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + try { + return this.actualStrategy.get(session, key, txTimestamp); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + try { + return this.actualStrategy.insert(session, key, value, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + try { + return this.actualStrategy.lockItem(session, key, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public SoftLock lockRegion() throws CacheException { + try { + return this.actualStrategy.lockRegion(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version, minimalPutOverride); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + try { + this.actualStrategy.remove(session, key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void removeAll() throws CacheException { + try { + this.actualStrategy.removeAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockItem(session, key, lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockRegion(SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockRegion(lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException { + try { + return this.actualStrategy.update(session, key, value, currentVersion, previousVersion); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..b11a239f4506459e7edb750fad94ead0ced27b6e --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/nonstop/NonstopAwareNaturalIdRegionAccessStrategy.java @@ -0,0 +1,181 @@ +package net.oschina.j2cache.hibernate5.nonstop; + +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.NaturalIdRegion; +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; + +public class NonstopAwareNaturalIdRegionAccessStrategy implements NaturalIdRegionAccessStrategy { + + private final NaturalIdRegionAccessStrategy actualStrategy; + private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler; + + public NonstopAwareNaturalIdRegionAccessStrategy(NaturalIdRegionAccessStrategy actualStrategy, HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) { + this.actualStrategy = actualStrategy; + this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler; + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + try { + return this.actualStrategy.insert(session, key, value); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + try { + return this.actualStrategy.afterInsert(session, key, value); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + try { + return this.actualStrategy.update(session, key, value); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException { + try { + return this.actualStrategy.afterUpdate(session, key, value, lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public NaturalIdRegion getRegion() { + return this.actualStrategy.getRegion(); + } + + @Override + public void evict(Object key) throws CacheException { + try { + this.actualStrategy.evict(key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void evictAll() throws CacheException { + try { + this.actualStrategy.evictAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + try { + return this.actualStrategy.get(session, key, txTimestamp); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + try { + return this.actualStrategy.lockItem(session, key, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public SoftLock lockRegion() throws CacheException { + try { + return this.actualStrategy.lockRegion(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return null; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) + throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version, minimalPutOverride); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException { + try { + return this.actualStrategy.putFromLoad(session, key, value, txTimestamp, version); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + return false; + } + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + try { + this.actualStrategy.remove(session, key); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void removeAll() throws CacheException { + try { + this.actualStrategy.removeAll(); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockItem(session, key, lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public void unlockRegion(SoftLock lock) throws CacheException { + try { + this.actualStrategy.unlockRegion(lock); + } catch (NonStopCacheException nonStopCacheException) { + hibernateNonstopExceptionHandler.handleNonstopCacheException(nonStopCacheException); + } + } + + @Override + public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) { + return DefaultCacheKeysFactory.staticCreateNaturalIdKey( naturalIdValues, persister, session ); + } + + @Override + public Object[] getNaturalIdValues(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + } + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheCollectionRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheCollectionRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..b83880373822b72f96a673b9057cd0eb7d0e7f7d --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheCollectionRegion.java @@ -0,0 +1,25 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +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.access.AccessType; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; + +import java.util.Properties; + +public class J2CacheCollectionRegion extends J2CacheTransactionalDataRegion implements CollectionRegion { + + public J2CacheCollectionRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, SessionFactoryOptions settings, CacheDataDescription metadata, Properties properties) { + super(accessStrategyFactory, underlyingCache, settings, metadata, properties); + } + + @Override + public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException { + return this.getAccessStrategyFactory().createCollectionRegionAccessStrategy(this, accessType); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheDataRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheDataRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..0cc76ded27e6debc4041e5be7ce18cd17cc9bf88 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheDataRegion.java @@ -0,0 +1,105 @@ +package net.oschina.j2cache.hibernate5.regions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import net.oschina.j2cache.hibernate5.log.J2CacheMessageLogger; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.Region; + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import net.oschina.j2cache.hibernate5.util.Timestamper; + +public abstract class J2CacheDataRegion implements Region { + + private static final J2CacheMessageLogger LOG = org.jboss.logging.Logger.getMessageLogger( + J2CacheMessageLogger.class, + J2CacheDataRegion.class.getName() + ); + private static final String CACHE_LOCK_TIMEOUT_PROPERTY = "hibernate.cache_lock_timeout"; + private static final int DEFAULT_CACHE_LOCK_TIMEOUT = 60000; + + private final CacheRegion cache; + private final J2CacheAccessStrategyFactory accessStrategyFactory; + private final int cacheLockTimeout; + + J2CacheDataRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion cache, Properties properties) { + this.accessStrategyFactory = accessStrategyFactory; + this.cache = cache; + String timeout = properties.getProperty(CACHE_LOCK_TIMEOUT_PROPERTY, Integer.toString(DEFAULT_CACHE_LOCK_TIMEOUT)); + this.cacheLockTimeout = Timestamper.ONE_MS * Integer.decode(timeout); + } + + protected CacheRegion getCache() { + return this.cache; + } + + public CacheRegion getJ2Cache() { + return this.getCache(); + } + + protected J2CacheAccessStrategyFactory getAccessStrategyFactory() { + return this.accessStrategyFactory; + } + + public String getName() { + return this.getCache().getName(); + } + + public void destroy() throws CacheException { + try { + this.getCache().clear(); + } catch (IllegalStateException e) { + LOG.debug("This can happen if multiple frameworks both try to shutdown ehcache", e); + } + } + + public long getSizeInMemory() { + return -1; + } + + @Override + public long getElementCountInMemory() { + return -1; + } + + @Override + public long getElementCountOnDisk() { + return -1; + } + + @Override + public Map toMap() { + try { + Map result = new HashMap(); + for (Object key : this.cache.keys()) { + CacheObject e = this.cache.get(key); + if (e != null) { + result.put(key, e.getValue()); + } + } + return result; + } catch (Exception e) { + throw new CacheException(e); + } + } + + @Override + public long nextTimestamp() { + return Timestamper.next(); + } + + @Override + public int getTimeout() { + return this.cacheLockTimeout; + } + + @Override + public boolean contains(Object key) { + return false; + } + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheEntityRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheEntityRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..7ba3e0c2ecc05afecf44018d774a19f13d22f66d --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheEntityRegion.java @@ -0,0 +1,25 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; + +import java.util.Properties; + +public class J2CacheEntityRegion extends J2CacheTransactionalDataRegion implements EntityRegion { + + public J2CacheEntityRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, SessionFactoryOptions settings, CacheDataDescription metadata, Properties properties) { + super(accessStrategyFactory,underlyingCache, settings, metadata, properties); + } + + @Override + public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException { + return this.getAccessStrategyFactory().createEntityRegionAccessStrategy( this, accessType ); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheGeneralDataRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheGeneralDataRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..afd145d1d445c9666e0a0cec88bc136b57e6a2f2 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheGeneralDataRegion.java @@ -0,0 +1,69 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.log.J2CacheMessageLogger; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.GeneralDataRegion; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.jboss.logging.Logger; + +import java.util.Properties; + +public class J2CacheGeneralDataRegion extends J2CacheDataRegion implements GeneralDataRegion { + + private static final J2CacheMessageLogger LOG = Logger.getMessageLogger(J2CacheMessageLogger.class, J2CacheGeneralDataRegion.class.getName()); + + public J2CacheGeneralDataRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, Properties properties) { + super(accessStrategyFactory, underlyingCache, properties); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key) throws CacheException { + LOG.debugf("key: %s", key); + if (key == null) { + return null; + } else { + CacheObject value = this.getCache().get(key); + if (value == null) { + LOG.debugf("value for key %s is null", key); + return null; + } else { + return value.getValue(); + } + } + } + + @Override + public void put(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + LOG.debugf("key: %s value: %s", key, value); + try { + this.getCache().put(key, value); + } catch (IllegalArgumentException e) { + throw new CacheException(e); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } + + @Override + public void evict(Object key) throws CacheException { + try { + this.getCache().evict(key); + } catch (ClassCastException e) { + throw new CacheException(e); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } + + @Override + public void evictAll() throws CacheException { + try { + this.getCache().clear(); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheNaturalIdRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheNaturalIdRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..87e0538d48e86297ccbbee692de034d1aad7f040 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheNaturalIdRegion.java @@ -0,0 +1,25 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +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.cfg.Settings; + +import java.util.Properties; + +public class J2CacheNaturalIdRegion extends J2CacheTransactionalDataRegion implements NaturalIdRegion { + + public J2CacheNaturalIdRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, SessionFactoryOptions settings, CacheDataDescription metadata, Properties properties) { + super(accessStrategyFactory, underlyingCache, settings, metadata, properties); + } + + @Override + public NaturalIdRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException { + return getAccessStrategyFactory().createNaturalIdRegionAccessStrategy(this, accessType); + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheQueryResultsRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheQueryResultsRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..bbc455ee92f1c898bd79185f6520a8ca0de60211 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheQueryResultsRegion.java @@ -0,0 +1,15 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.cache.spi.QueryResultsRegion; + +import java.util.Properties; + +public class J2CacheQueryResultsRegion extends J2CacheGeneralDataRegion implements QueryResultsRegion { + + public J2CacheQueryResultsRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, Properties properties) { + super( accessStrategyFactory, underlyingCache, properties ); + } + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTimestampsRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTimestampsRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..a87b6820fcbfe3432fb64ef4381731adaed69114 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTimestampsRegion.java @@ -0,0 +1,15 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.cache.spi.TimestampsRegion; + +import java.util.Properties; + +public class J2CacheTimestampsRegion extends J2CacheGeneralDataRegion implements TimestampsRegion { + + public J2CacheTimestampsRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion underlyingCache, Properties properties) { + super(accessStrategyFactory, underlyingCache, properties); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTransactionalDataRegion.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTransactionalDataRegion.java new file mode 100644 index 0000000000000000000000000000000000000000..a33edd43b2aca255d0e9af1c6980da20cef3bd91 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/regions/J2CacheTransactionalDataRegion.java @@ -0,0 +1,94 @@ +package net.oschina.j2cache.hibernate5.regions; + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.CacheDataDescription; +import org.hibernate.cache.spi.TransactionalDataRegion; + +import java.util.Properties; + +public class J2CacheTransactionalDataRegion extends J2CacheDataRegion implements TransactionalDataRegion { + + private static final int LOCAL_LOCK_PROVIDER_CONCURRENCY = 128; + + private final SessionFactoryOptions settings; + + protected final CacheDataDescription metadata; + + J2CacheTransactionalDataRegion(J2CacheAccessStrategyFactory accessStrategyFactory, CacheRegion cache, SessionFactoryOptions settings, CacheDataDescription metadata, Properties properties) { + super(accessStrategyFactory, cache, properties); + this.settings = settings; + this.metadata = metadata; + } + + public SessionFactoryOptions getSettings() { + return this.settings; + } + + @Override + public boolean isTransactionAware() { + return false; + } + + @Override + public CacheDataDescription getCacheDataDescription() { + return this.metadata; + } + + public final Object get(Object key) { + CacheObject object = this.getCache().get(key); + return object != null ? object.getValue() : null; + } + + public final void put(Object key, Object value) throws CacheException { + try { + this.getCache().put(key, value); + } catch (IllegalArgumentException e) { + throw new CacheException(e); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } + + public final void remove(Object key) throws CacheException { + try { + this.getCache().evict(key); + } catch (ClassCastException e) { + throw new CacheException(e); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } + + public final void clear() throws CacheException { + try { + this.getCache().clear(); + } catch (IllegalStateException e) { + throw new CacheException(e); + } + } + + public final void writeLock(Object key) throws CacheException { + + } + + public final void writeUnlock(Object key) throws CacheException { + + } + + public final void readLock(Object key) throws CacheException { + + } + + public final void readUnlock(Object key) throws CacheException { + + } + + public final boolean locksAreIndependentOfCache() { + return false; + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractJ2CacheAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractJ2CacheAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..75c4dd7d4184acfd7b7776f2c98827c7a31c7600 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractJ2CacheAccessStrategy.java @@ -0,0 +1,59 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheTransactionalDataRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.Settings; +import org.hibernate.engine.spi.SharedSessionContractImplementor; + + +abstract class AbstractJ2CacheAccessStrategy { + + private final T region; + private final SessionFactoryOptions settings; + + AbstractJ2CacheAccessStrategy(T region, SessionFactoryOptions settings) { + this.region = region; + this.settings = settings; + } + + protected T region() { + return this.region; + } + + protected SessionFactoryOptions settings() { + return this.settings; + } + + public final boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException { + return putFromLoad( session, key, value, txTimestamp, version, settings.isMinimalPutsEnabled() ); + } + + public abstract boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) + throws CacheException; + + public final SoftLock lockRegion() { + return null; + } + + public final void unlockRegion(SoftLock lock) throws CacheException { + region.clear(); + } + + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + } + + public final void removeAll() throws CacheException { + region.clear(); + } + + public final void evict(Object key) throws CacheException { + region.remove( key ); + } + + public final void evictAll() throws CacheException { + region.clear(); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractReadWriteJ2CacheAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractReadWriteJ2CacheAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..8716a47e59123e03972f619355d463b47954780d --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/AbstractReadWriteJ2CacheAccessStrategy.java @@ -0,0 +1,268 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.log.J2CacheMessageLogger; +import net.oschina.j2cache.hibernate5.regions.J2CacheTransactionalDataRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.jboss.logging.Logger; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +abstract class AbstractReadWriteJ2CacheAccessStrategy extends AbstractJ2CacheAccessStrategy { + + private static final J2CacheMessageLogger LOG = Logger.getMessageLogger(J2CacheMessageLogger.class, AbstractReadWriteJ2CacheAccessStrategy.class.getName()); + + private final UUID uuid = UUID.randomUUID(); + private final AtomicLong nextLockId = new AtomicLong(); + + private final Comparator versionComparator; + + public AbstractReadWriteJ2CacheAccessStrategy(T region, SessionFactoryOptions settings) { + super(region, settings); + this.versionComparator = region.getCacheDataDescription().getVersionComparator(); + } + + public final Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + readLockIfNeeded(key); + try { + final Lockable item = (Lockable) region().get(key); + final boolean readable = item != null && item.isReadable(txTimestamp); + if (readable) { + return item.getValue(); + } else { + return null; + } + } finally { + readUnlockIfNeeded(key); + } + } + + @Override + public final boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + region().writeLock(key); + try { + final Lockable item = (Lockable) region().get(key); + final boolean writeable = item == null || item.isWriteable(txTimestamp, version, versionComparator); + if (writeable) { + region().put(key, new Item(value, version, region().nextTimestamp())); + return true; + } else { + return false; + } + } finally { + region().writeUnlock(key); + } + } + + public final SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + region().writeLock(key); + try { + final Lockable item = (Lockable) region().get(key); + final long timeout = region().nextTimestamp() + region().getTimeout(); + final Lock lock = (item == null) ? new Lock(timeout, uuid, nextLockId(), version) : item.lock(timeout, uuid, nextLockId()); + region().put(key, lock); + return lock; + } finally { + region().writeUnlock(key); + } + } + + public final void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + region().writeLock(key); + try { + final Lockable item = (Lockable) region().get(key); + if ((item != null) && item.isUnlockable(lock)) { + decrementLock(key, (Lock) item); + } else { + handleLockExpiry(key, item); + } + } finally { + region().writeUnlock(key); + } + } + + private long nextLockId() { + return nextLockId.getAndIncrement(); + } + + protected void decrementLock(Object key, Lock lock) { + lock.unlock(region().nextTimestamp()); + region().put(key, lock); + } + + protected void handleLockExpiry(Object key, Lockable lock) { + LOG.softLockedCacheExpired(region().getName(), key, lock == null ? "(null)" : lock.toString()); + final long ts = region().nextTimestamp() + region().getTimeout(); + final Lock newLock = new Lock(ts, uuid, nextLockId.getAndIncrement(), null); + newLock.unlock(ts); + region().put(key, newLock); + } + + private void readLockIfNeeded(Object key) { + if (region().locksAreIndependentOfCache()) { + region().readLock(key); + } + } + + private void readUnlockIfNeeded(Object key) { + if (region().locksAreIndependentOfCache()) { + region().readUnlock(key); + } + } + + protected interface Lockable { + + boolean isReadable(long txTimestamp); + + boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator); + + Object getValue(); + + boolean isUnlockable(SoftLock lock); + + Lock lock(long timeout, UUID uuid, long lockId); + } + + protected static final class Item implements Serializable, Lockable { + private static final long serialVersionUID = 1L; + private final Object value; + private final Object version; + private final long timestamp; + + Item(Object value, Object version, long timestamp) { + this.value = value; + this.version = version; + this.timestamp = timestamp; + } + + @Override + public boolean isReadable(long txTimestamp) { + return txTimestamp > timestamp; + } + + @Override + @SuppressWarnings("unchecked") + public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { + return version != null && versionComparator.compare(version, newVersion) < 0; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public boolean isUnlockable(SoftLock lock) { + return false; + } + + @Override + public Lock lock(long timeout, UUID uuid, long lockId) { + return new Lock(timeout, uuid, lockId, version); + } + } + + protected static final class Lock implements Serializable, Lockable, SoftLock { + private static final long serialVersionUID = 2L; + + private final UUID sourceUuid; + private final long lockId; + private final Object version; + + private long timeout; + private boolean concurrent; + private int multiplicity = 1; + private long unlockTimestamp; + + Lock(long timeout, UUID sourceUuid, long lockId, Object version) { + this.timeout = timeout; + this.lockId = lockId; + this.version = version; + this.sourceUuid = sourceUuid; + } + + @Override + public boolean isReadable(long txTimestamp) { + return false; + } + + @Override + @SuppressWarnings({"SimplifiableIfStatement", "unchecked"}) + public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) { + if (txTimestamp > timeout) { + return true; + } + if (multiplicity > 0) { + return false; + } + return version == null + ? txTimestamp > unlockTimestamp + : versionComparator.compare(version, newVersion) < 0; + } + + @Override + public Object getValue() { + return null; + } + + @Override + public boolean isUnlockable(SoftLock lock) { + return equals(lock); + } + + @Override + @SuppressWarnings("SimplifiableIfStatement") + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o instanceof Lock) { + return (lockId == ((Lock) o).lockId) && sourceUuid.equals(((Lock) o).sourceUuid); + } else { + return false; + } + } + + @Override + public int hashCode() { + final int hash = (sourceUuid != null ? sourceUuid.hashCode() : 0); + int temp = (int) lockId; + for (int i = 1; i < Long.SIZE / Integer.SIZE; i++) { + temp ^= (lockId >>> (i * Integer.SIZE)); + } + return hash + temp; + } + + /** + * Returns true if this Lock has been concurrently locked by more than one transaction. + */ + public boolean wasLockedConcurrently() { + return concurrent; + } + + @Override + public Lock lock(long timeout, UUID uuid, long lockId) { + concurrent = true; + multiplicity++; + this.timeout = timeout; + return this; + } + + public void unlock(long timestamp) { + if (--multiplicity == 0) { + unlockTimestamp = timestamp; + } + } + + @Override + public String toString() { + return "Lock Source-UUID:" + sourceUuid + " Lock-ID:" + lockId; + } + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactory.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..0abfefecd736665f6bb5cc87c27b9adfdf6bd6b3 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactory.java @@ -0,0 +1,18 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; + +public interface J2CacheAccessStrategyFactory { + + EntityRegionAccessStrategy createEntityRegionAccessStrategy(J2CacheEntityRegion entityRegion, AccessType accessType); + + CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(J2CacheCollectionRegion collectionRegion, AccessType accessType); + + NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion naturalIdRegion, AccessType accessType); +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactoryImpl.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..36bf05c67e74298147a9679f2f2055b162a1c799 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/J2CacheAccessStrategyFactoryImpl.java @@ -0,0 +1,75 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.log.J2CacheMessageLogger; +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.jboss.logging.Logger; + +public class J2CacheAccessStrategyFactoryImpl implements J2CacheAccessStrategyFactory { + + private static final J2CacheMessageLogger LOG = Logger.getMessageLogger(J2CacheMessageLogger.class, J2CacheAccessStrategyFactoryImpl.class.getName()); + + public EntityRegionAccessStrategy createEntityRegionAccessStrategy(J2CacheEntityRegion entityRegion, AccessType accessType) { + switch (accessType) { + case READ_ONLY: + if (entityRegion.getCacheDataDescription().isMutable()) { + LOG.readOnlyCacheConfiguredForMutableEntity(entityRegion.getName()); + } + return new ReadOnlyJ2CacheEntityRegionAccessStrategy(entityRegion, entityRegion.getSettings()); + case READ_WRITE: + return new ReadWriteJ2CacheEntityRegionAccessStrategy(entityRegion, entityRegion.getSettings()); + case NONSTRICT_READ_WRITE: + return new NonStrictReadWriteJ2CacheEntityRegionAccessStrategy(entityRegion, entityRegion.getSettings()); + case TRANSACTIONAL: + return new TransactionalJ2CacheEntityRegionAccessStrategy(entityRegion, entityRegion.getJ2Cache(), entityRegion.getSettings()); + default: + throw new IllegalArgumentException("unrecognized access strategy type [" + accessType + "]"); + + } + + } + + public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(J2CacheCollectionRegion collectionRegion, AccessType accessType) { + switch (accessType) { + case READ_ONLY: + if (collectionRegion.getCacheDataDescription().isMutable()) { + LOG.readOnlyCacheConfiguredForMutableEntity(collectionRegion.getName()); + } + return new ReadOnlyJ2CacheCollectionRegionAccessStrategy(collectionRegion, collectionRegion.getSettings()); + case READ_WRITE: + return new ReadWriteJ2CacheCollectionRegionAccessStrategy(collectionRegion, collectionRegion.getSettings()); + case NONSTRICT_READ_WRITE: + return new NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy(collectionRegion, collectionRegion.getSettings()); + case TRANSACTIONAL: + return new TransactionalJ2CacheCollectionRegionAccessStrategy(collectionRegion, collectionRegion.getJ2Cache(), collectionRegion.getSettings()); + default: + throw new IllegalArgumentException("unrecognized access strategy type [" + accessType + "]"); + } + } + + @Override + public NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion naturalIdRegion, AccessType accessType) { + switch (accessType) { + case READ_ONLY: + if (naturalIdRegion.getCacheDataDescription().isMutable()) { + LOG.readOnlyCacheConfiguredForMutableEntity(naturalIdRegion.getName()); + } + return new ReadOnlyJ2CacheNaturalIdRegionAccessStrategy(naturalIdRegion, naturalIdRegion.getSettings()); + case READ_WRITE: + return new ReadWriteJ2CacheNaturalIdRegionAccessStrategy(naturalIdRegion, naturalIdRegion.getSettings()); + case NONSTRICT_READ_WRITE: + return new NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy(naturalIdRegion, naturalIdRegion.getSettings()); + case TRANSACTIONAL: + return new TransactionalJ2CacheNaturalIdRegionAccessStrategy(naturalIdRegion, naturalIdRegion.getJ2Cache(), naturalIdRegion.getSettings()); + default: + throw new IllegalArgumentException("unrecognized access strategy type [" + accessType + "]"); + } + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..d8f4a2f232918fc0435171a44a9a91ea9d3a3ecf --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy.java @@ -0,0 +1,67 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CollectionRegion; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.Settings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.collection.CollectionPersister; + + +public class NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements CollectionRegionAccessStrategy { + + public NonStrictReadWriteJ2CacheCollectionRegionAccessStrategy(J2CacheCollectionRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public CollectionRegion getRegion() { + return region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) + throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + region().remove(key); + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + region().remove(key); + } + + @Override + public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetCollectionId( cacheKey ); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheEntityRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheEntityRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..22d1900d3779254ee7d45d0c2d967b833e958af1 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheEntityRegionAccessStrategy.java @@ -0,0 +1,87 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.Settings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + +public class NonStrictReadWriteJ2CacheEntityRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements EntityRegionAccessStrategy { + + public NonStrictReadWriteJ2CacheEntityRegionAccessStrategy(J2CacheEntityRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public EntityRegion getRegion() { + return super.region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + region().remove(key); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + return false; + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException { + remove(session, key); + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { + unlockItem(session, key, lock); + return false; + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + region().remove(key); + } + + @Override + public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetEntityId( cacheKey ); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..92218b40a149af764b9b0ea91c0e6699d8216471 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy.java @@ -0,0 +1,88 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.NaturalIdRegion; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.Settings; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + +public class NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements NaturalIdRegionAccessStrategy { + + public NonStrictReadWriteJ2CacheNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public NaturalIdRegion getRegion() { + return region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + region().remove(key); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + return false; + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + remove(session, key); + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException { + unlockItem(session, key, lock); + return false; + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + region().remove(key); + } + + @Override + public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) { + return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + } + + @Override + public Object[] getNaturalIdValues(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetNaturalIdValues( cacheKey ); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonstopAccessStrategyFactory.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonstopAccessStrategyFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..bfa418b53a80c56d1d22c1fadc3e658697198961 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/NonstopAccessStrategyFactory.java @@ -0,0 +1,38 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.nonstop.HibernateNonstopCacheExceptionHandler; +import net.oschina.j2cache.hibernate5.nonstop.NonstopAwareCollectionRegionAccessStrategy; +import net.oschina.j2cache.hibernate5.nonstop.NonstopAwareEntityRegionAccessStrategy; +import net.oschina.j2cache.hibernate5.nonstop.NonstopAwareNaturalIdRegionAccessStrategy; +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import net.oschina.j2cache.hibernate5.strategy.J2CacheAccessStrategyFactory; +import org.hibernate.cache.spi.access.AccessType; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy; + +public class NonstopAccessStrategyFactory implements J2CacheAccessStrategyFactory { + + private final J2CacheAccessStrategyFactory actualFactory; + + public NonstopAccessStrategyFactory(J2CacheAccessStrategyFactory actualFactory) { + this.actualFactory = actualFactory; + } + + @Override + public EntityRegionAccessStrategy createEntityRegionAccessStrategy(J2CacheEntityRegion entityRegion, AccessType accessType) { + return new NonstopAwareEntityRegionAccessStrategy(this.actualFactory.createEntityRegionAccessStrategy(entityRegion, accessType), HibernateNonstopCacheExceptionHandler.getInstance()); + } + + @Override + public NaturalIdRegionAccessStrategy createNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion naturalIdRegion, AccessType accessType) { + return new NonstopAwareNaturalIdRegionAccessStrategy(this.actualFactory.createNaturalIdRegionAccessStrategy(naturalIdRegion, accessType), HibernateNonstopCacheExceptionHandler.getInstance()); + } + + @Override + public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(J2CacheCollectionRegion collectionRegion, AccessType accessType) { + return new NonstopAwareCollectionRegionAccessStrategy(this.actualFactory.createCollectionRegionAccessStrategy(collectionRegion, accessType ), HibernateNonstopCacheExceptionHandler.getInstance()); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheCollectionRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheCollectionRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..9f99e05c90a7a8b81ab8b9e535147442f3ec1705 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheCollectionRegionAccessStrategy.java @@ -0,0 +1,60 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CollectionRegion; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.collection.CollectionPersister; + +public class ReadOnlyJ2CacheCollectionRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements CollectionRegionAccessStrategy { + + public ReadOnlyJ2CacheCollectionRegionAccessStrategy(J2CacheCollectionRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public CollectionRegion getRegion() { + return region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws UnsupportedOperationException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + } + + @Override + public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + } + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheEntityRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheEntityRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..8737ae9167e1f3a458ab71a0c49e0c6a606481b6 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheEntityRegionAccessStrategy.java @@ -0,0 +1,81 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + +public class ReadOnlyJ2CacheEntityRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements EntityRegionAccessStrategy { + + public ReadOnlyJ2CacheEntityRegionAccessStrategy(J2CacheEntityRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public EntityRegion getRegion() { + return region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) + throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws UnsupportedOperationException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + evict(key); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + region().put(key, value); + return true; + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Can't write to a readonly object"); + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Can't write to a readonly object"); + } + + @Override + public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateEntityKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheNaturalIdRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheNaturalIdRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..9312f031179471554382c908ed1d9c336e467af5 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadOnlyJ2CacheNaturalIdRegionAccessStrategy.java @@ -0,0 +1,80 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.NaturalIdRegion; +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; + +public class ReadOnlyJ2CacheNaturalIdRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements NaturalIdRegionAccessStrategy { + + public ReadOnlyJ2CacheNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public NaturalIdRegion getRegion() { + return region(); + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + return region().get(key); + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && region().contains(key)) { + return false; + } else { + region().put(key, value); + return true; + } + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws UnsupportedOperationException { + return null; + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + region().remove(key); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + region().put(key, value); + return true; + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Can't write to a readonly object"); + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Can't write to a readonly object"); + } + + @Override + public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) { + return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + } + + @Override + public Object[] getNaturalIdValues(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheCollectionRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheCollectionRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..60ab7585641c0f768b941c86a29d9e1b0fb4ef20 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheCollectionRegionAccessStrategy.java @@ -0,0 +1,32 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CollectionRegion; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.persister.collection.CollectionPersister; + +public class ReadWriteJ2CacheCollectionRegionAccessStrategy extends AbstractReadWriteJ2CacheAccessStrategy implements CollectionRegionAccessStrategy { + + public ReadWriteJ2CacheCollectionRegionAccessStrategy(J2CacheCollectionRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public CollectionRegion getRegion() { + return region(); + } + + @Override + public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheEntityRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheEntityRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..1bdb29f92950daa1da0fbddba3e8c3c23eb5ecbc --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheEntityRegionAccessStrategy.java @@ -0,0 +1,95 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.cfg.Settings; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + + +public class ReadWriteJ2CacheEntityRegionAccessStrategy extends AbstractReadWriteJ2CacheAccessStrategy implements EntityRegionAccessStrategy { + + public ReadWriteJ2CacheEntityRegionAccessStrategy(J2CacheEntityRegion region, SessionFactoryOptions settings) { + super( region, settings ); + } + + @Override + public EntityRegion getRegion() { + return region(); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + region().writeLock( key ); + try { + final AbstractReadWriteJ2CacheAccessStrategy.Lockable item = (AbstractReadWriteJ2CacheAccessStrategy.Lockable) region().get( key ); + if ( item == null ) { + region().put( key, new AbstractReadWriteJ2CacheAccessStrategy.Item( value, version, region().nextTimestamp() ) ); + return true; + } + else { + return false; + } + } + finally { + region().writeUnlock( key ); + } + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) + throws CacheException { + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) + throws CacheException { + //what should we do with previousVersion here? + region().writeLock( key ); + try { + final AbstractReadWriteJ2CacheAccessStrategy.Lockable item = (AbstractReadWriteJ2CacheAccessStrategy.Lockable) region().get( key ); + + if ( item != null && item.isUnlockable( lock ) ) { + final AbstractReadWriteJ2CacheAccessStrategy.Lock lockItem = (AbstractReadWriteJ2CacheAccessStrategy.Lock) item; + if ( lockItem.wasLockedConcurrently() ) { + decrementLock( key, lockItem ); + return false; + } + else { + region().put( key, new AbstractReadWriteJ2CacheAccessStrategy.Item( value, currentVersion, region().nextTimestamp() ) ); + return true; + } + } + else { + handleLockExpiry( key, item ); + return false; + } + } + finally { + region().writeUnlock( key ); + } + } + + @Override + public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateEntityKey(id, persister, factory, tenantIdentifier); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheNaturalIdRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheNaturalIdRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..9c64df8be97f1580ef4086c73cd27c0dc0b529ed --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/ReadWriteJ2CacheNaturalIdRegionAccessStrategy.java @@ -0,0 +1,82 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.NaturalIdRegion; +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; + +public class ReadWriteJ2CacheNaturalIdRegionAccessStrategy extends AbstractReadWriteJ2CacheAccessStrategy implements NaturalIdRegionAccessStrategy { + + public ReadWriteJ2CacheNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion region, SessionFactoryOptions settings) { + super(region, settings); + } + + @Override + public NaturalIdRegion getRegion() { + return region(); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + return false; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + region().writeLock(key); + try { + final Lockable item = (Lockable) region().get(key); + if (item == null) { + region().put(key, new Item(value, null, region().nextTimestamp())); + return true; + } else { + return false; + } + } finally { + region().writeUnlock(key); + } + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) throws CacheException { + region().writeLock(key); + try { + final Lockable item = (Lockable) region().get(key); + if (item != null && item.isUnlockable(lock)) { + final Lock lockItem = (Lock) item; + if (lockItem.wasLockedConcurrently()) { + decrementLock(key, lockItem); + return false; + } else { + region().put(key, new Item(value, null, region().nextTimestamp())); + return true; + } + } else { + handleLockExpiry(key, item); + return false; + } + } finally { + region().writeUnlock(key); + } + } + + @Override + public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) { + return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + } + + @Override + public Object[] getNaturalIdValues(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + } +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheCollectionRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheCollectionRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..ae56ab7d7e9eb8b9860688cabaa115eafd6ceee9 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheCollectionRegionAccessStrategy.java @@ -0,0 +1,70 @@ +package net.oschina.j2cache.hibernate5.strategy; + + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheCollectionRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.CollectionRegion; +import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.collection.CollectionPersister; + +public class TransactionalJ2CacheCollectionRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements CollectionRegionAccessStrategy { + + private final CacheRegion cache; + + public TransactionalJ2CacheCollectionRegionAccessStrategy(J2CacheCollectionRegion region, CacheRegion cache, SessionFactoryOptions settings) { + super(region, settings); + this.cache = cache; + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + CacheObject object = cache.get(key); + return object != null ? object.getValue() : null; + } + + @Override + public CollectionRegion getRegion() { + return region(); + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && cache.get(key) != null) { + return false; + } + cache.put(key, value); + return true; + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + cache.evict(key); + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + } + + @Override + public Object generateCacheKey(Object id, CollectionPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateCollectionKey( id, persister, factory, tenantIdentifier ); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetCollectionId(cacheKey); + } + +} \ No newline at end of file diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheEntityRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheEntityRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..9e04a88a83e9c02ae69b7b06c386a6208dce107f --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheEntityRegionAccessStrategy.java @@ -0,0 +1,95 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheEntityRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.EntityRegion; +import org.hibernate.cache.spi.access.EntityRegionAccessStrategy; +import org.hibernate.cache.spi.access.SoftLock; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.persister.entity.EntityPersister; + + +public class TransactionalJ2CacheEntityRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements EntityRegionAccessStrategy { + + private final CacheRegion cache; + + public TransactionalJ2CacheEntityRegionAccessStrategy( + J2CacheEntityRegion region, + CacheRegion cache, + SessionFactoryOptions settings) { + super(region, settings); + this.cache = cache; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) { + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) { + return false; + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + final CacheObject element = cache.get(key); + return element == null ? null : element.getValue(); + } + + @Override + public EntityRegion getRegion() { + return region(); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException { + cache.put(key, value); + return true; + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && cache.get(key) != null) { + return false; + } + cache.put(key, value); + return true; + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + cache.evict(key); + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException { + cache.put(key, value); + return true; + } + + @Override + public Object generateCacheKey(Object id, EntityPersister persister, SessionFactoryImplementor factory, String tenantIdentifier) { + return DefaultCacheKeysFactory.staticCreateEntityKey(id, persister, factory, tenantIdentifier); + } + + @Override + public Object getCacheKeyId(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetEntityId(cacheKey); + } + +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheNaturalIdRegionAccessStrategy.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheNaturalIdRegionAccessStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..499a0bab2ef7f8eb4e70d5475059118b612ed1ba --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/strategy/TransactionalJ2CacheNaturalIdRegionAccessStrategy.java @@ -0,0 +1,89 @@ +package net.oschina.j2cache.hibernate5.strategy; + +import net.oschina.j2cache.CacheObject; +import net.oschina.j2cache.hibernate5.CacheRegion; +import net.oschina.j2cache.hibernate5.regions.J2CacheNaturalIdRegion; +import org.hibernate.boot.spi.SessionFactoryOptions; +import org.hibernate.cache.CacheException; +import org.hibernate.cache.internal.DefaultCacheKeysFactory; +import org.hibernate.cache.spi.NaturalIdRegion; +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; + +public class TransactionalJ2CacheNaturalIdRegionAccessStrategy extends AbstractJ2CacheAccessStrategy implements NaturalIdRegionAccessStrategy { + + private final CacheRegion cache; + + public TransactionalJ2CacheNaturalIdRegionAccessStrategy(J2CacheNaturalIdRegion region, CacheRegion cache, SessionFactoryOptions settings) { + super(region, settings); + this.cache = cache; + } + + @Override + public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) { + return false; + } + + @Override + public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock) { + return false; + } + + @Override + public Object get(SharedSessionContractImplementor session, Object key, long txTimestamp) throws CacheException { + final CacheObject element = cache.get(key); + return element == null ? null : element.getValue(); + } + + @Override + public NaturalIdRegion getRegion() { + return region(); + } + + @Override + public boolean insert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + cache.put(key, value); + return true; + } + + @Override + public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException { + return null; + } + + @Override + public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { + if (minimalPutOverride && cache.get(key) != null) { + return false; + } + cache.put(key, value); + return true; + } + + @Override + public void remove(SharedSessionContractImplementor session, Object key) throws CacheException { + cache.evict(key); + } + + @Override + public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException { + } + + @Override + public boolean update(SharedSessionContractImplementor session, Object key, Object value) throws CacheException { + cache.put(key, value); + return true; + } + + @Override + public Object generateCacheKey(Object[] naturalIdValues, EntityPersister persister, SharedSessionContractImplementor session) { + return DefaultCacheKeysFactory.staticCreateNaturalIdKey(naturalIdValues, persister, session); + } + + @Override + public Object[] getNaturalIdValues(Object cacheKey) { + return DefaultCacheKeysFactory.staticGetNaturalIdValues(cacheKey); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/SlewClock.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/SlewClock.java new file mode 100644 index 0000000000000000000000000000000000000000..843898ad059259d9b2c98813590874e15015cbab --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/SlewClock.java @@ -0,0 +1,105 @@ +package net.oschina.j2cache.hibernate5.util; + +import java.util.concurrent.atomic.AtomicLong; + +import net.oschina.j2cache.hibernate5.util.TimeProviderLoader; +import net.oschina.j2cache.hibernate5.util.lang.VicariousThreadLocal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class SlewClock { + + private static final Logger LOG = LoggerFactory.getLogger(net.oschina.j2cache.hibernate5.util.SlewClock.class); + private static final net.oschina.j2cache.hibernate5.util.SlewClock.TimeProvider PROVIDER = TimeProviderLoader.getTimeProvider(); + private static final long DRIFT_MAXIMAL = (long)Integer.getInteger("net.oschina.j2cache.hibernate5.util.Timestamper.drift.max", 50); + private static final long SLEEP_MAXIMAL = (long)Integer.getInteger("net.oschina.j2cache.hibernate5.util.Timestamper.sleep.max", 50); + private static final int SLEEP_BASE = Integer.getInteger("net.oschina.j2cache.hibernate5.util.Timestamper.sleep.min", 25); + private static final AtomicLong CURRENT = new AtomicLong(-9223372036854775808L); + private static final VicariousThreadLocal OFFSET = new VicariousThreadLocal(); + + private SlewClock() { + } + + /** @deprecated */ + @Deprecated + static void realignWithTimeProvider() { + CURRENT.set(getCurrentTime()); + } + + static long timeMillis() { + boolean interrupted = false; + + try { + while(true) { + long mono = CURRENT.get(); + long wall = getCurrentTime(); + long delta; + if (wall == mono) { + OFFSET.remove(); + delta = wall; + return delta; + } + + if (wall > mono) { + if (CURRENT.compareAndSet(mono, wall)) { + OFFSET.remove(); + delta = wall; + return delta; + } + } else { + delta = mono - wall; + if (delta < DRIFT_MAXIMAL) { + OFFSET.remove(); + long var15 = mono; + return var15; + } + + Long lastDelta = (Long)OFFSET.get(); + long sleep; + if (lastDelta != null && delta >= lastDelta) { + OFFSET.set(Math.max(delta, lastDelta)); + + try { + sleep = sleepTime(delta, lastDelta); + LOG.trace("{} sleeping for {}ms to adjust for wall-clock drift.", Thread.currentThread(), sleep); + Thread.sleep(sleep); + } catch (InterruptedException var13) { + interrupted = true; + } + } else if (CURRENT.compareAndSet(mono, mono + 1L)) { + OFFSET.set(delta); + sleep = mono + 1L; + return sleep; + } + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + + } + } + + static boolean isThreadCatchingUp() { + return OFFSET.get() != null; + } + + static long behind() { + Long offset = (Long)OFFSET.get(); + return offset == null ? 0L : offset; + } + + private static long sleepTime(long current, long previous) { + long target = (long)SLEEP_BASE + (current - previous) * 2L; + return Math.min(target > 0L ? target : (long)SLEEP_BASE, SLEEP_MAXIMAL); + } + + private static long getCurrentTime() { + return PROVIDER.currentTimeMillis(); + } + + interface TimeProvider { + long currentTimeMillis(); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/TimeProviderLoader.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/TimeProviderLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..50b2980656fc52e521df8e012d2213b5a7a4ad3b --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/TimeProviderLoader.java @@ -0,0 +1,23 @@ +package net.oschina.j2cache.hibernate5.util; + +import net.oschina.j2cache.hibernate5.util.SlewClock.TimeProvider; + +final class TimeProviderLoader { + + private static TimeProvider timeProvider = new TimeProvider() { + public final long currentTimeMillis() { + return System.currentTimeMillis(); + } + }; + + private TimeProviderLoader() { + } + + public static synchronized TimeProvider getTimeProvider() { + return timeProvider; + } + + public static synchronized void setTimeProvider(TimeProvider timeProvider) { + timeProvider = timeProvider; + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/Timestamper.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/Timestamper.java new file mode 100644 index 0000000000000000000000000000000000000000..8dca4acd909894d2377eff81f88f003ac7542d8c --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/Timestamper.java @@ -0,0 +1,62 @@ +package net.oschina.j2cache.hibernate5.util; + +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class Timestamper { + + public static final int BIN_DIGITS = Integer.getInteger("net.oschina.j2cache.hibernate5.util.shift", 12); + public static final int ONE_MS; + private static final Logger LOG; + private static final int MAX_LOG; + private static final AtomicLong VALUE; + private static final AtomicLong LOGGED; + + private Timestamper() { + } + + public static long next() { + int runs = 0; + + while(true) { + long base = SlewClock.timeMillis() << BIN_DIGITS; + long maxValue = base + (long)ONE_MS - 1L; + long current = VALUE.get(); + + for(long update = Math.max(base, current + 1L); update < maxValue; update = Math.max(base, current + 1L)) { + if (VALUE.compareAndSet(current, update)) { + if (runs > 1) { + log(base, "Thread spin-waits on time to pass. Looped {} times, you might want to increase -Dnet.oschina.j2cache.hibernate5.util.shift", runs); + } + + return update; + } + + current = VALUE.get(); + } + + ++runs; + } + } + + private static void log(long base, String message, Object... params) { + if (LOG.isInfoEnabled()) { + long thisLog = (base >> BIN_DIGITS) / (long)MAX_LOG; + long previousLog = LOGGED.get(); + if (previousLog != thisLog && LOGGED.compareAndSet(previousLog, thisLog)) { + LOG.info(message, params); + } + } + + } + + static { + ONE_MS = 1 << BIN_DIGITS; + LOG = LoggerFactory.getLogger(Timestamper.class); + MAX_LOG = Integer.getInteger("net.oschina.j2cache.hibernate5.util.log.max", 1) * 1000; + VALUE = new AtomicLong(); + LOGGED = new AtomicLong(); + } +} diff --git a/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/lang/VicariousThreadLocal.java b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/lang/VicariousThreadLocal.java new file mode 100644 index 0000000000000000000000000000000000000000..d15eaa86b3b4bf3ead4feda92f55f27ebe21a460 --- /dev/null +++ b/modules/hibernate5/src/net/oschina/j2cache/hibernate5/util/lang/VicariousThreadLocal.java @@ -0,0 +1,118 @@ +package net.oschina.j2cache.hibernate5.util.lang; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +public class VicariousThreadLocal extends ThreadLocal { + + private static final ThreadLocal> weakThread = new ThreadLocal(); + private static final Object UNINITIALISED = new Object(); + private final ThreadLocal> local = new ThreadLocal(); + private volatile VicariousThreadLocal.Holder strongRefs; + private static final AtomicReferenceFieldUpdater strongRefsUpdater = AtomicReferenceFieldUpdater.newUpdater(VicariousThreadLocal.class, VicariousThreadLocal.Holder.class, "strongRefs"); + private final ReferenceQueue queue = new ReferenceQueue(); + + static WeakReference currentThreadRef() { + WeakReference ref = (WeakReference)weakThread.get(); + if (ref == null) { + ref = new WeakReference(Thread.currentThread()); + weakThread.set(ref); + } + + return ref; + } + + public VicariousThreadLocal() { + } + + public T get() { + WeakReference ref = (WeakReference)this.local.get(); + VicariousThreadLocal.Holder holder; + Object value; + if (ref != null) { + holder = (VicariousThreadLocal.Holder)ref.get(); + value = holder.value; + if (value != UNINITIALISED) { + return (T) value; + } + } else { + holder = this.createHolder(); + } + + value = this.initialValue(); + holder.value = value; + return (T) value; + } + + public void set(T value) { + WeakReference ref = (WeakReference)this.local.get(); + VicariousThreadLocal.Holder holder = ref != null ? (VicariousThreadLocal.Holder)ref.get() : this.createHolder(); + holder.value = value; + } + + private VicariousThreadLocal.Holder createHolder() { + this.poll(); + VicariousThreadLocal.Holder holder = new VicariousThreadLocal.Holder(this.queue); + WeakReference ref = new WeakReference(holder); + + VicariousThreadLocal.Holder old; + do { + old = this.strongRefs; + holder.next = old; + } while(!strongRefsUpdater.compareAndSet(this, old, holder)); + + this.local.set(ref); + return holder; + } + + public void remove() { + WeakReference ref = (WeakReference)this.local.get(); + if (ref != null) { + ((VicariousThreadLocal.Holder)ref.get()).value = UNINITIALISED; + } + + } + + public void poll() { + ReferenceQueue var1 = this.queue; + synchronized(this.queue) { + if (this.queue.poll() != null) { + while(this.queue.poll() != null) { + ; + } + + VicariousThreadLocal.Holder first = this.strongRefs; + if (first != null) { + VicariousThreadLocal.Holder link = first; + VicariousThreadLocal.Holder next = first.next; + + while(next != null) { + if (next.get() == null) { + next = next.next; + link.next = next; + } else { + link = next; + next = next.next; + } + } + + if (first.get() == null && !strongRefsUpdater.weakCompareAndSet(this, first, first.next)) { + first.value = null; + } + + } + } + } + } + + private static class Holder extends WeakReference { + VicariousThreadLocal.Holder next; + Object value; + + Holder(ReferenceQueue queue) { + super(VicariousThreadLocal.currentThreadRef(), queue); + this.value = VicariousThreadLocal.UNINITIALISED; + } + } +} diff --git a/modules/hibernate5/test/config/commons-logging.properties b/modules/hibernate5/test/config/commons-logging.properties new file mode 100644 index 0000000000000000000000000000000000000000..d539d7e175d9bdd549dffce8e02e7eb5f6497d80 --- /dev/null +++ b/modules/hibernate5/test/config/commons-logging.properties @@ -0,0 +1,3 @@ +#\u8be5\u6587\u4ef6WAS\u73af\u5883\u5fc5\u987b\u5b58\u5728,\u5426\u5219\u65e5\u5fd7\u4e0d\u4f1a\u8f93\u51fa +org.apache.cmmons.logging.LogFactory = org.apache.commons.logging.impl.LogFactoryImpl +org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger \ No newline at end of file diff --git a/modules/hibernate5/test/config/ehcache.xml b/modules/hibernate5/test/config/ehcache.xml new file mode 100644 index 0000000000000000000000000000000000000000..c9e9f210f9046c02f338c20438b5e6078ad68191 --- /dev/null +++ b/modules/hibernate5/test/config/ehcache.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/hibernate5/test/config/ehcache3.xml b/modules/hibernate5/test/config/ehcache3.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a6a496b51a28649b197531ff23cfc2ec13047a7 --- /dev/null +++ b/modules/hibernate5/test/config/ehcache3.xml @@ -0,0 +1,19 @@ + + + + + java.lang.String + java.io.Serializable + + 30 + + + 1000 + 100 + + + + \ No newline at end of file diff --git a/modules/hibernate5/test/config/j2cache.properties b/modules/hibernate5/test/config/j2cache.properties new file mode 100644 index 0000000000000000000000000000000000000000..1ecef9514d3ea0215b1c4c1946fe84cf1a7bda6e --- /dev/null +++ b/modules/hibernate5/test/config/j2cache.properties @@ -0,0 +1,169 @@ +#J2Cache configuration + + +######################################### +# Cache Broadcast Method +# values: +# jgroups -> use jgroups's multicast +# redis -> use redis publish/subscribe mechanism (using jedis) +# lettuce -> use redis publish/subscribe mechanism (using lettuce) +# rabbitmq -> use RabbitMQ publisher/consumer mechanism +# rocketmq -> use RocketMQ publisher/consumer mechanism +# none -> don't notify the other nodes in cluster +# xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy +######################################### + +j2cache.broadcast = redis + +# jgroups properties +jgroups.channel.name = j2cache +jgroups.configXml = /network.xml + +# RabbitMQ properties +rabbitmq.exchange = j2cache +rabbitmq.host = localhost +rabbitmq.port = 5672 +rabbitmq.username = guest +rabbitmq.password = guest + +# RocketMQ properties +rocketmq.name = j2cache +rocketmq.topic = j2cache +# use ; to split multi hosts +rocketmq.hosts = 127.0.0.1:9876 + +######################################### +# Level 1&2 provider +# values: +# none -> disable this level cache +# ehcache -> use ehcache2 as level 1 cache +# ehcache3 -> use ehcache3 as level 1 cache +# caffeine -> use caffeine as level 1 cache(only in memory) +# redis -> use redis as level 2 cache (using jedis) +# lettuce -> use redis as level 2 cache (using lettuce) +# readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available. +# memcached -> use memcached as level 2 cache (xmemcached), +# [classname] -> use custom provider +######################################### + +j2cache.L1.provider_class = ehcache3 +j2cache.L2.provider_class = redis + +# When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations +# j2cache.L2.config_section = redis + +# Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true) +# NOTICE: redis hash mode (redis.storage = hash) do not support this feature) +j2cache.sync_ttl_to_redis = true + +# Whether to cache null objects by default (default false) +j2cache.default_cache_null_object = true + +######################################### +# Cache Serialization Provider +# values: +# fst -> using fast-serialization (recommend) +# kyro -> using kyro serialization +# json -> using fst's json serialization (testing) +# fastjson -> using fastjson serialization (embed non-static class not support) +# java -> java standard +# [classname implements Serializer] +######################################### + +j2cache.serialization = json +#json.map.person = net.oschina.j2cache.demo.Person + +######################################### +# Ehcache configuration +######################################### + +# ehcache.configXml = /ehcache.xml + +# ehcache3.configXml = /ehcache3.xml +# ehcache3.defaultHeapSize = 1000 + +######################################### +# Caffeine configuration +# caffeine.region.[name] = size, xxxx[s|m|h|d] +# +######################################### +caffeine.properties = /caffeine.properties + +######################################### +# Redis connection configuration +######################################### + +######################################### +# Redis Cluster Mode +# +# single -> single redis server +# sentinel -> master-slaves servers +# cluster -> cluster servers (ݿЧʹ database = 0 +# sharded -> sharded servers (롢ݿ hosts ָӳЧ ; redis://user:password@127.0.0.1:6379/0 +# +######################################### + +redis.mode = single + +#redis storage mode (generic|hash) +redis.storage = generic + +## redis pub/sub channel name +redis.channel = j2cache +## redis pub/sub server (using redis.hosts when empty) +redis.channel.host = + +#cluster name just for sharded +redis.cluster_name = j2cache + +## redis cache namespace optional, default[empty] +redis.namespace = + +## connection +# Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379 + +redis.hosts = 127.0.0.1:6379 +redis.timeout = 2000 +redis.password = +redis.database = 0 + +## redis pool properties +redis.maxTotal = 100 +redis.maxIdle = 10 +redis.maxWaitMillis = 5000 +redis.minEvictableIdleTimeMillis = 60000 +redis.minIdle = 1 +redis.numTestsPerEvictionRun = 10 +redis.lifo = false +redis.softMinEvictableIdleTimeMillis = 10 +redis.testOnBorrow = true +redis.testOnReturn = false +redis.testWhileIdle = true +redis.timeBetweenEvictionRunsMillis = 300000 +redis.blockWhenExhausted = false +redis.jmxEnabled = false + +lettuce.namespace = +lettuce.storage = generic +lettuce.channel = j2cache +lettuce.scheme = redis +lettuce.hosts = 127.0.0.1:6379 +lettuce.password = +lettuce.database = 0 +lettuce.sentinelMasterId = + +######################################### +# memcached server configurations +# refer to https://gitee.com/mirrors/XMemcached +######################################### + +memcached.servers = 127.0.0.1:11211 +memcached.username = +memcached.password = +memcached.connectionPoolSize = 10 +memcached.connectTimeout = 1000 +memcached.failureMode = false +memcached.healSessionInterval = 1000 +memcached.maxQueuedNoReplyOperations = 100 +memcached.opTimeout = 100 +memcached.sanitizeKeys = false \ No newline at end of file diff --git a/modules/hibernate5/test/config/log4j.xml b/modules/hibernate5/test/config/log4j.xml new file mode 100644 index 0000000000000000000000000000000000000000..840473ac5843e53f1dc38b74643d67be389da1be --- /dev/null +++ b/modules/hibernate5/test/config/log4j.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/hibernate5/test/config/network.xml b/modules/hibernate5/test/config/network.xml new file mode 100644 index 0000000000000000000000000000000000000000..fedb76d867851c461ad5d56a6258428ba6ab5835 --- /dev/null +++ b/modules/hibernate5/test/config/network.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/hibernate5/test/config/props/jdbc.properties b/modules/hibernate5/test/config/props/jdbc.properties new file mode 100644 index 0000000000000000000000000000000000000000..0556a5d13ab3a3bc63af63116a5a7fbfdcf3126b --- /dev/null +++ b/modules/hibernate5/test/config/props/jdbc.properties @@ -0,0 +1,24 @@ +# jdbc config +jdbc.driver=com.mysql.jdbc.Driver +#jdbc.driver=oracle.jdbc.driver.OracleDriver +#\u5F00\u53D1\u914D\u7F6E + + +#oracle +#jdbc.driverUrl=jdbc:oracle:thin:@192.168.0.200:1521:ORCL +#jdbc.user=sgp +#jdbc.password=sgp +#jdbc.driverUrl=jdbc:mysql://sp50f83d0575d01.mysql.rds.aliyuncs.com:3306/itsm?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 + +#mysql +#jdbc.driverUrl=jdbc:mysql://192.168.1.200:3306/webapp?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 +jdbc.driverUrl=jdbc:mysql://localhost:3306/webapp?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 +jdbc.user=root +jdbc.password=123456 + +#\u7EBF\u4E0A\u914D\u7F6E +jdbc.houseKeepingSleepTime=90000 +jdbc.houseKeepingTestSql=select count(1) from sys_sequence +jdbc.prototypeCount=5 +jdbc.maximumConnectionCount=100 +jdbc.minimumConnectionCount=20 \ No newline at end of file diff --git a/modules/hibernate5/test/config/redis.properties b/modules/hibernate5/test/config/redis.properties new file mode 100644 index 0000000000000000000000000000000000000000..39da017d95a9a43aedf7d7b6d24fbb226a7a4143 --- /dev/null +++ b/modules/hibernate5/test/config/redis.properties @@ -0,0 +1,9 @@ +# Redis settings +redis.host=localhost +redis.port=6379 +#redis.pass=java2000_wl + +redis.maxIdle=300 +redis.maxActive=600 +redis.maxWait=1000 +redis.testOnBorrow=true \ No newline at end of file diff --git a/modules/hibernate5/test/config/spring/applicationContext.xml b/modules/hibernate5/test/config/spring/applicationContext.xml new file mode 100644 index 0000000000000000000000000000000000000000..0523d888266e90da0fd66f234a47ec50621925b4 --- /dev/null +++ b/modules/hibernate5/test/config/spring/applicationContext.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.MySQL5InnoDBDialect + true + true + false + 2 + true + false + true + true + update + org.springframework.orm.hibernate5.SpringSessionContext + true + true + net.oschina.j2cache.hibernate5.J2CacheRegionFactory + + true + true + + + + + net.oschina.j2cache.hibernate5 + + + + + + + + + + \ No newline at end of file diff --git a/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactoryTest.java b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..28aec2eee7a388dbc735acb44faa8ae5609bb6a1 --- /dev/null +++ b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/J2CacheRegionFactoryTest.java @@ -0,0 +1,152 @@ +package net.oschina.j2cache.hibernate5; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; + +import net.oschina.j2cache.hibernate5.service.IArticleService; +import org.hibernate.criterion.MatchMode; +import org.hibernate.criterion.Restrictions; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.oschina.j2cache.J2Cache; +import net.oschina.j2cache.hibernate5.bean.Article; +import net.oschina.j2cache.hibernate5.service.ArticleService; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { "classpath*:spring/applicationContext.xml" }) +public class J2CacheRegionFactoryTest { + + private final static Logger LOG = LoggerFactory.getLogger(J2CacheRegionFactoryTest.class); + + @Autowired + private IArticleService articleService; + + @Before + public void setUp() throws Exception { + this.tearDown(); + + Article article = new Article(); + article.setTitle("测试缓存"); + article.setSummary("测试数据摘要"); + this.articleService.save(article); + + Article article1 = new Article(); + article1.setTitle("测试缓存1"); + article1.setSummary("测试数据摘要1"); + this.articleService.save(article1); + } + + @After + public void tearDown() throws Exception { + for (Article art : this.articleService + .find(Restrictions.like("title", "测试缓存", MatchMode.START))) { + this.articleService.delete(art.getId()); + } + } + + @Test + public void findUnique() { + + // 查询单个对象 + Article article = this.articleService + .findUnique(Restrictions.like("title", "测试缓存1", MatchMode.START)); + LOG.debug("第一次查询,缓存查询结果:" + article); + + article = this.articleService + .findUnique(Restrictions.like("title", "测试缓存1", MatchMode.START)); + LOG.debug("第二次查询,从缓存中获取:" + article); + + // 直接从缓存中读取数据 + + Map narticle = + getCacheValue("net.oschina.j2cache.hibernate5.bean.Article", article.getId()); + LOG.debug("直接从缓存中读取数据:" + narticle); + + // 验证结果 + assert article.getTitle() + .equals(narticle.get("title")); + + // 修改数据后 + Article saveartice = new Article(); + saveartice.setId(article.getId()); + saveartice.setTitle("测试缓存1"); + saveartice.setSummary("修改数据摘要"); + articleService.save(saveartice); + + // 缓存数据会删除 + narticle = getCacheValue("net.oschina.j2cache.hibernate5.bean.Article", article.getId()); + LOG.debug("修改后直接从缓存中读取数据:" + narticle); + // 发现还是原来的值,因为hibernate的缓存是存在于三个位置的,第一个为查询sql及条件作为的key。第二个为缓存单个对象的过期时间。第三个才是缓存的对象 + + article = this.articleService + .findUnique(Restrictions.like("title", "测试缓存1", MatchMode.START)); + LOG.debug("再次查询,缓存查询结果:" + article);// 会重新缓存结果 + + narticle = getCacheValue("net.oschina.j2cache.hibernate5.bean.Article", article.getId()); + LOG.debug("再次直接从缓存中读取数据:" + narticle); + + // 验证结果 + assert article.getTitle() + .equals(narticle.get("title")); + } + + @Test + public void find() { + // 查询list + List
articleList = this.articleService.find(); + LOG.debug("第一次查询,缓存查询结果:" + articleList); + + articleList = this.articleService.find(); + LOG.debug("第二次查询,从缓存中获取:" + articleList); + + // 修改数据后 + Article saveartice = new Article(); + saveartice.setId(articleList.get(0) + .getId()); + saveartice.setTitle("测试缓存1"); + saveartice.setSummary("修改数据摘要"); + articleService.save(saveartice); + // 缓存数据会删除 + + articleList = this.articleService.find(); + LOG.debug("再次查询,缓存查询结果:" + articleList);// 会重新缓存结果 + + // 测试新增数据 + Article newartice = new Article(); + newartice.setTitle("测试缓存2"); + newartice.setSummary("修改数据摘要"); + articleService.save(newartice); + // 缓存数据会删除 + + articleList = this.articleService.find(); + LOG.debug("再次查询,缓存查询结果:" + articleList);// 会重新缓存结果 + assert articleList.size() == 3; + + } + + private Map getCacheValue(String region, String key) { + try { + Object item = J2Cache.getChannel() + .get(region, key) + .getValue(); + if (item != null) + return (Map) BeanUtils.getPropertyDescriptor(item.getClass(), "value") + .getReadMethod() + .invoke(item); + } catch (IllegalAccessException | InvocationTargetException e) { + LOG.error(e.getMessage(), e); + } + return null; + } +} diff --git a/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/bean/Article.java b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/bean/Article.java new file mode 100644 index 0000000000000000000000000000000000000000..c657ee052eb9226303d39fa35091a8cc49ede9b6 --- /dev/null +++ b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/bean/Article.java @@ -0,0 +1,133 @@ +package net.oschina.j2cache.hibernate5.bean; + + +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.GenericGenerator; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@Entity +@Table(name = "TEST_CACHE_ARTICLE") +@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +public class Article implements Serializable { + + @Id + @Column(name = "ID", nullable = false, insertable = true, updatable = true) + @GenericGenerator(name="systemUUID",strategy="uuid") + @GeneratedValue(generator="systemUUID") + private String id; + /** + * 文章标题 + */ + @Column(name = "TITLE") + private String title; + /** + * 摘要 + */ + @Column(name = "SUMMARY") + private String summary; + /** + * 发布标识 + */ + @Column(name = "ISSUE") + private Boolean issue = false; + + /** + * 创建人 + */ + @Column(name = "CREATOR", length = 20) + private String creator; + /** + * 创建时间 + */ + @Temporal(TemporalType.TIMESTAMP) + @Column(updatable = false, name = "CREATE_TIME") + private Date createTime; + /** + * 最后修改人 + */ + @Column(name = "MODIFIER", length = 20) + private String modifier; + /** + * 最后修改时间 + */ + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "MODIFY_TIME") + private Date modifyTime; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public Boolean getIssue() { + return issue; + } + + public void setIssue(Boolean issue) { + this.issue = issue; + } + + public String getCreator() { + return creator; + } + + public void setCreator(String creator) { + this.creator = creator; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getModifier() { + return modifier; + } + + public void setModifier(String modifier) { + this.modifier = modifier; + } + + public Date getModifyTime() { + return modifyTime; + } + + public void setModifyTime(Date modifyTime) { + this.modifyTime = modifyTime; + } + + @Override + public String toString() { + return "Article[hashCode="+this.hashCode()+"]{" + + "id='" + id + '\'' + + ", title='" + title + '\'' + + ", summary='" + summary + '\'' + + '}'; + } +} diff --git a/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/ArticleService.java b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/ArticleService.java new file mode 100644 index 0000000000000000000000000000000000000000..64d5ee665b191c1290d45cdf158eb2be06570571 --- /dev/null +++ b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/ArticleService.java @@ -0,0 +1,54 @@ +package net.oschina.j2cache.hibernate5.service; + +import net.oschina.j2cache.hibernate5.bean.Article; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Criterion; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.util.List; + +@Transactional +@Service +public class ArticleService implements IArticleService { + + @Resource + private SessionFactory sessionFactory; + + protected Session getSession() { + return this.sessionFactory.getCurrentSession(); + } + + public void save(Article article) { + getSession().saveOrUpdate(article); + } + + public List
find(Criterion... criterions) { + Criteria criteria = getSession().createCriteria(Article.class); + for (Criterion c : criterions) { + criteria.add(c); + } + criteria.setCacheable(true); + return criteria.list(); + } + + public void delete(String id) { + getSession().delete(getSession().get(Article.class, id)); + } + + public Article findUnique(Criterion... criterions) { + Criteria criteria = getSession().createCriteria(Article.class); + for (Criterion c : criterions) { + criteria.add(c); + } + criteria.setCacheable(true); + return (Article)criteria.uniqueResult(); + } + + public Article get(String id) { + return (Article)getSession().get(Article.class,id); + } +} diff --git a/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/IArticleService.java b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/IArticleService.java new file mode 100644 index 0000000000000000000000000000000000000000..1fb25000abfb89e5ebf7a1e2da50181cdee3aec3 --- /dev/null +++ b/modules/hibernate5/test/src/net/oschina/j2cache/hibernate5/service/IArticleService.java @@ -0,0 +1,19 @@ +package net.oschina.j2cache.hibernate5.service; + +import net.oschina.j2cache.hibernate5.bean.Article; +import org.hibernate.criterion.Criterion; + +import java.util.List; + +public interface IArticleService { + + public void save(Article article); + + public List
find(Criterion... criterions); + + public void delete(String id); + + public Article findUnique(Criterion... criterions); + + public Article get(String id); +} diff --git a/modules/mybatis/pom.xml b/modules/mybatis/pom.xml index cdcb70cad1c557d6b6e08ba082692e913ac84d4d..7b3dd57703c6c9b883664813ed2e4ca022ade261 100644 --- a/modules/mybatis/pom.xml +++ b/modules/mybatis/pom.xml @@ -5,7 +5,7 @@ j2cache net.oschina.j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml 4.0.0 @@ -16,8 +16,7 @@ net.oschina.j2cache j2cache-core - ${j2cache-version} - compile + provided org.mybatis @@ -37,4 +36,4 @@ src/main/java - \ No newline at end of file + diff --git a/modules/session-manager/Readme.md b/modules/session-manager/Readme.md index 7b7e5253eb434de87f6c4df7f023c0fbe7d82e9e..7a808b0388bb22acfb4b9c686495caab87b2e557 100644 --- a/modules/session-manager/Readme.md +++ b/modules/session-manager/Readme.md @@ -10,7 +10,7 @@ net.oschina.j2cache j2cache-session-manager - 1.0.0 + xxx ``` 2. 配置 web.xml @@ -39,7 +39,18 @@ cookie.domain + + + redis.mode single @@ -87,4 +98,7 @@ /* ``` + + 更详细配置请参考 j2cache.properties 说明。 + 3. 启动应用并检查日志看是否启动正常 diff --git a/modules/session-manager/pom.xml b/modules/session-manager/pom.xml index aa9bfdb41c0d9e0e2545dea7318f1d056813fdf5..cd112af06dcf74b49bf954de27f516f012e9b2fd 100644 --- a/modules/session-manager/pom.xml +++ b/modules/session-manager/pom.xml @@ -5,7 +5,7 @@ j2cache net.oschina.j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml @@ -32,6 +32,14 @@ commons-logging commons-logging 1.2 + provided + + + + org.apache.commons + commons-pool2 + 2.5.0 + provided diff --git a/modules/session-manager/src/main/java/net/oschina/j2cache/session/CacheFacade.java b/modules/session-manager/src/main/java/net/oschina/j2cache/session/CacheFacade.java index b2a32bde05006e7c3356e4093df67fb941e1a6cd..415f0bd34955a4529d0c48a0207da07fdcab9c8b 100644 --- a/modules/session-manager/src/main/java/net/oschina/j2cache/session/CacheFacade.java +++ b/modules/session-manager/src/main/java/net/oschina/j2cache/session/CacheFacade.java @@ -17,9 +17,7 @@ package net.oschina.j2cache.session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPoolConfig; -import redis.clients.jedis.JedisPubSub; +import redis.clients.jedis.*; import redis.clients.jedis.exceptions.JedisConnectionException; import java.io.Closeable; @@ -116,8 +114,15 @@ public class CacheFacade extends JedisPubSub implements Closeable, AutoCloseable */ public void publish(Command cmd) { try { - Jedis jedis = (Jedis)redisClient.get(); - jedis.publish(pubsub_channel, cmd.toString()); + BinaryJedisCommands redis = redisClient.get(); + if(redis instanceof Jedis) { + Jedis jedis = (Jedis) redis; + jedis.publish(pubsub_channel, cmd.toString()); + } + else if(redis instanceof JedisCluster) { + JedisCluster jedis = (JedisCluster) redis; + jedis.publish(pubsub_channel, cmd.toString()); + } } finally { redisClient.release(); } diff --git a/modules/spring-boot-starter/pom.xml b/modules/spring-boot-starter/pom.xml index fbfe51f8776e8b6e7e3235c3da917d68c3c032e1..fe9b994d4339d43e3972d155d377c21ff17d8468 100644 --- a/modules/spring-boot-starter/pom.xml +++ b/modules/spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ j2cache net.oschina.j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml 4.0.0 @@ -16,8 +16,7 @@ net.oschina.j2cache j2cache-core - ${j2cache-version} - compile + provided org.springframework.boot @@ -69,4 +68,4 @@ 1.5.8.RELEASE - \ No newline at end of file + diff --git a/modules/spring-boot-starter/readme.md b/modules/spring-boot-starter/readme.md index 70b300f2536ab9083deb43d9b32bbaa2b76187ec..4f1671aa75d001aa063b7ad55a5467583ffcf4f2 100644 --- a/modules/spring-boot-starter/readme.md +++ b/modules/spring-boot-starter/readme.md @@ -34,5 +34,8 @@ j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPol j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider j2cache.L2.config_section = redis ``` - +在application.properties中支持关闭二级缓存 +``` +j2cache.l2-cache-open=false(默认开启) +``` diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java index c41ecb23241c3290d02a526d3a5bb0eefb17af01..4f40ca11da4b43462d68f64b5ca34739be11f64e 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java @@ -24,7 +24,7 @@ import net.oschina.j2cache.cache.support.util.SpringUtil; @ConditionalOnClass(J2Cache.class) @EnableConfigurationProperties({J2CacheConfig.class}) @Configuration -@PropertySource(value = "${j2cache.config-location}") +@PropertySource(value = {"${j2cache.config-location}","file:${j2cache.config-location}"},ignoreResourceNotFound = true ) public class J2CacheAutoConfiguration { @Autowired diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java index 4e859dae3d82ee7b684a20cd9507e217329d62bf..490d68ed0a92d8a7bcfe0b3fddcdd18d2210874e 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java @@ -17,17 +17,34 @@ public class J2CacheConfig { /** * 缓存清除模式, - * active:主动清除,二级缓存过期主动通知各节点清除,优点在于所有节点可以同时收到缓存清除 - * passive:被动清除,一级缓存过期进行通知各节点清除一二级缓存, - * blend:两种模式一起运作,对于各个节点缓存准确以及及时性要求高的可以使用,正常用前两种模式中一个就可 + *
    + *
  • active:主动清除,二级缓存过期主动通知各节点清除,优点在于所有节点可以同时收到缓存清除
  • + *
  • passive:被动清除,一级缓存过期进行通知各节点清除一二级缓存,
  • + *
  • blend:两种模式一起运作,对于各个节点缓存准确以及及时性要求高的可以使用,正常用前两种模式中一个就可
  • + *
*/ private String cacheCleanMode = "passive"; /** - * 是否允许缓存空值,默认:true + * 是否允许缓存空值,默认:false */ - private boolean allowNullValues = true; + private boolean allowNullValues = false; + + /** + * 使用哪种redis客户端,默认:jedis + * + */ + private String redisClient = "jedis"; + + /** + * 是否开启二级缓存 + */ + private boolean l2CacheOpen = true; + public String getConfigLocation() { return configLocation; } @@ -59,4 +76,21 @@ public class J2CacheConfig { public void setAllowNullValues(boolean allowNullValues) { this.allowNullValues = allowNullValues; } + + public String getRedisClient() { + return redisClient; + } + + public void setRedisClient(String redisClient) { + this.redisClient = redisClient; + } + + public boolean getL2CacheOpen() { + return l2CacheOpen; + } + + public void setL2CacheOpen(boolean l2CacheOpen) { + this.l2CacheOpen = l2CacheOpen; + } + } diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java index 0b35e3ef760d0ff5dbaee39282a92c39b4c94e25..a7a5a5596fe292a329917ed6ecfd240ee0b38446 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java @@ -14,6 +14,7 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -40,6 +41,7 @@ import redis.clients.jedis.exceptions.JedisConnectionException; @Configuration @AutoConfigureAfter({ RedisAutoConfiguration.class }) @AutoConfigureBefore({ J2CacheAutoConfiguration.class }) +@ConditionalOnProperty(value = "j2cache.l2-cache-open", havingValue = "true", matchIfMissing = true) public class J2CacheSpringRedisAutoConfiguration { private final static int MAX_ATTEMPTS = 3; diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java index 0ec59bdab59ceef2d6e2b5fdf4d8cdb7eb5d0418..32016946be41ecc4bfe53be0f7beb57274d2bc7a 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java @@ -82,7 +82,7 @@ public class J2CacheCache extends AbstractValueAdaptingCache { @Override protected Object lookup(Object key) { - CacheObject cacheObject = cacheChannel.get(j2CacheName, String.valueOf(key), super.isAllowNullValues()); + CacheObject cacheObject = cacheChannel.get(j2CacheName, String.valueOf(key), false); if(cacheObject.rawValue() != null && cacheObject.rawValue().getClass().equals(NullObject.class) && super.isAllowNullValues()) { return NullValue.INSTANCE; } diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java index 6d232ae4f3b3d5d2b5178d3744d36279f8042eed..312e19e03430523e8904537548b7738415171f83 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java @@ -1,11 +1,7 @@ package net.oschina.j2cache.cache.support.redis; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; @@ -54,7 +50,7 @@ public class SpringRedisCache implements Level2Cache { @Override public void evict(String... keys) { for (String k : keys) { - if (!k.equals("null")) { + if (!Objects.equals(k, "null")) { redisTemplate.opsForHash().delete(region, k); } else { redisTemplate.delete(region); diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java index 842aff3de117fb07256fd1cd437e17d01bb927ef..2387915c32c709ae317834098cac52efe6ec2deb 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +45,7 @@ public class SpringRedisGenericCache implements Level2Cache { public void clear() { Collection keys = keys(); keys.stream().forEach(k -> { - redisTemplate.delete(k); + redisTemplate.delete(this.region + ":" + k); }); } @@ -66,12 +67,7 @@ public class SpringRedisGenericCache implements Level2Cache { @Override public Collection keys() { - Set list = redisTemplate.keys(this.region + ":*"); - List keys = new ArrayList<>(list.size()); - for (String s : list) { - keys.add(s); - } - return keys; + return redisTemplate.keys(this.region + ":*").stream().map(k->k.substring(this.region.length()+1)).collect(Collectors.toSet()); } @Override diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java index efaf1074e3987abb19016b3641185f748bb3b84b..ff7e780fbb7cd2aeaefa820280ed0031505b9f8c 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java @@ -17,6 +17,7 @@ import net.oschina.j2cache.util.SerializationUtils; public class SpringRedisMessageListener implements MessageListener{ private static Logger logger = LoggerFactory.getLogger(SpringRedisMessageListener.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 private ClusterPolicy clusterPolicy; @@ -26,7 +27,11 @@ public class SpringRedisMessageListener implements MessageListener{ this.clusterPolicy = clusterPolicy; this.channel = channel; } - + + private boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + @Override public void onMessage(Message message, byte[] pattern) { byte[] messageChannel = message.getChannel(); @@ -36,7 +41,7 @@ public class SpringRedisMessageListener implements MessageListener{ } try { Command cmd = Command.parse(String.valueOf(SerializationUtils.deserialize(messageBody))); - if (cmd == null || cmd.isLocal()) + if (cmd == null || isLocalCommand(cmd)) return; switch (cmd.getOperator()) { diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java index 10cb7e1d7c23ebb2ce4fd7118c7678a7d1270169..0ef416a1e9bf1905068a0fb1fbb8a5555edf4250 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java @@ -13,6 +13,7 @@ import net.oschina.j2cache.CacheChannel; import net.oschina.j2cache.CacheExpiredListener; import net.oschina.j2cache.CacheObject; import net.oschina.j2cache.CacheProvider; +import net.oschina.j2cache.NullCache; import net.oschina.j2cache.cache.support.util.SpringUtil; /** @@ -23,6 +24,8 @@ import net.oschina.j2cache.cache.support.util.SpringUtil; public class SpringRedisProvider implements CacheProvider { private RedisTemplate redisTemplate; + + private net.oschina.j2cache.autoconfigure.J2CacheConfig config; private String namespace; @@ -47,6 +50,9 @@ public class SpringRedisProvider implements CacheProvider { @Override public Cache buildCache(String region, CacheExpiredListener listener) { + if(config.getL2CacheOpen() == false) { + return new NullCache(); + } Cache cache = caches.get(region); if (cache == null) { synchronized (SpringRedisProvider.class) { @@ -74,6 +80,10 @@ public class SpringRedisProvider implements CacheProvider { public void start(Properties props) { this.namespace = props.getProperty("namespace"); this.storage = props.getProperty("storage"); + this.config = SpringUtil.getBean(net.oschina.j2cache.autoconfigure.J2CacheConfig.class); + if(config.getL2CacheOpen() == false) { + return; + } this.redisTemplate = SpringUtil.getBean("j2CacheRedisTemplate", RedisTemplate.class); } diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java index ec15571cd08183f7cfe802c47dd2b6714106e789..eca5aa70353dab4c70b0934dd8723913161bc366 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java @@ -9,10 +9,11 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import net.oschina.j2cache.cluster.ClusterPolicy; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import net.oschina.j2cache.J2CacheConfig; import net.oschina.j2cache.cache.support.util.SpringUtil; +import net.oschina.j2cache.cluster.ClusterPolicy; /** * 使用spring redis实现订阅功能 @@ -20,79 +21,100 @@ import net.oschina.j2cache.cache.support.util.SpringUtil; */ public class SpringRedisPubSubPolicy implements ClusterPolicy { + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 + private RedisTemplate redisTemplate; - + private net.oschina.j2cache.autoconfigure.J2CacheConfig config; - + + private CacheProviderHolder holder; + /** * 是否是主动模式 */ private static boolean isActive = false; - + private String channel = "j2cache_channel"; + @Override + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + @SuppressWarnings("unchecked") @Override - public void connect(Properties props) { + public void connect(Properties props, CacheProviderHolder holder) { + this.holder = holder; + this.config = SpringUtil.getBean(net.oschina.j2cache.autoconfigure.J2CacheConfig.class); + if(config.getL2CacheOpen() == false) { + return; + } J2CacheConfig j2config = SpringUtil.getBean(J2CacheConfig.class); - this.config = SpringUtil.getBean(net.oschina.j2cache.autoconfigure.J2CacheConfig.class); this.redisTemplate = SpringUtil.getBean("j2CacheRedisTemplate", RedisTemplate.class); - if ("active".equals(config.getCacheCleanMode())) { - isActive = true; - } String channel_name = j2config.getL2CacheProperties().getProperty("channel"); - if (channel_name != null && !channel_name.isEmpty()) { + if(channel_name != null && !channel_name.isEmpty()) { this.channel = channel_name; } - RedisMessageListenerContainer listenerContainer = SpringUtil.getBean("j2CacheRedisMessageListenerContainer", - RedisMessageListenerContainer.class); - - listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), - new PatternTopic(this.channel)); - if (isActive) { - // 设置键值回调 + RedisMessageListenerContainer listenerContainer = SpringUtil.getBean("j2CacheRedisMessageListenerContainer", RedisMessageListenerContainer.class); + String namespace = j2config.getL2CacheProperties().getProperty("namespace"); + String database = j2config.getL2CacheProperties().getProperty("database"); + String expired = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:expired"; + String del = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:del"; + List topics = new ArrayList<>(); + topics.add(new PatternTopic(expired)); + topics.add(new PatternTopic(del)); + + if("active".equals(config.getCacheCleanMode())) { + isActive = true; + //设置键值回调 需要redis支持键值回调 + ConfigureNotifyKeyspaceEventsAction action = new ConfigureNotifyKeyspaceEventsAction(); + action.config(listenerContainer.getConnectionFactory().getConnection()); + listenerContainer.addMessageListener(new SpringRedisActiveMessageListener(this, namespace), topics); + }else if("blend".equals(config.getCacheCleanMode())) { + //设置键值回调 需要redis支持键值回调 ConfigureNotifyKeyspaceEventsAction action = new ConfigureNotifyKeyspaceEventsAction(); action.config(listenerContainer.getConnectionFactory().getConnection()); - - String namespace = j2config.getL2CacheProperties().getProperty("namespace"); - String database = j2config.getL2CacheProperties().getProperty("database"); - String expired = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:expired"; - String del = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:del"; - List topics = new ArrayList<>(); - topics.add(new PatternTopic(expired)); - topics.add(new PatternTopic(del)); listenerContainer.addMessageListener(new SpringRedisActiveMessageListener(this, namespace), topics); + listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), new PatternTopic(this.channel)); + }else { + listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), new PatternTopic(this.channel)); } } - // @Override - // public void sendEvictCmd(String region, String... keys) { - // if(!isActive || "blend".equals(config.getCacheCleanMode())) { - // String com = new Command(Command.OPT_EVICT_KEY, region, keys).json(); - // redisTemplate.convertAndSend(this.channel, com); - // } - // - // } + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } - // @Override - // public void sendClearCmd(String region) { - // if(!isActive || "blend".equals(config.getCacheCleanMode())) { - // String com = new Command(Command.OPT_CLEAR_KEY, region, "").json(); - // redisTemplate.convertAndSend(this.channel, com); - // } - // } + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } @Override - public void publish(Command cmd) { - if (!isActive || "blend".equals(config.getCacheCleanMode())) { + public void publish(Command cmd) { + if(!isActive && config.getL2CacheOpen()) { + cmd.setSrc(LOCAL_COMMAND_ID); redisTemplate.convertAndSend(this.channel, cmd.json()); } - } + } @Override public void disconnect() { - redisTemplate.convertAndSend(this.channel, Command.quit().json()); + if(!isActive && config.getL2CacheOpen()) { + Command cmd = new Command(); + cmd.setSrc(LOCAL_COMMAND_ID); + cmd.setOperator(Command.OPT_QUIT); + redisTemplate.convertAndSend(this.channel, cmd.json()); + } } } diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/J2CacheSerializer.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/J2CacheSerializer.java index 906bddfb86779f083ad166c857ad79b6f7ca2156..5748838ced2ef4f566748dbb01d6457b00365e8d 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/J2CacheSerializer.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/J2CacheSerializer.java @@ -2,6 +2,7 @@ package net.oschina.j2cache.cache.support.util; import java.io.IOException; +import org.nustaq.serialization.util.FSTUtil; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; @@ -11,12 +12,12 @@ import net.oschina.j2cache.util.SerializationUtils; public class J2CacheSerializer implements RedisSerializer{ @Override - public byte[] serialize(Object t) throws SerializationException { + public byte[] serialize(Object t) throws SerializationException { try { return SerializationUtils.serialize(t); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); + FSTUtil.rethrow(e); } return null; } @@ -26,8 +27,8 @@ public class J2CacheSerializer implements RedisSerializer{ try { return SerializationUtils.deserialize(bytes); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); + FSTUtil.rethrow(e); } return null; } diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java index 867b9bf10fb0bd96fa748c52e96b3e7206dea08a..8a0e75ffcc19fbe147745a1d803fda9d974f2b94 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java @@ -1,14 +1,19 @@ package net.oschina.j2cache.cache.support.util; +import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.support.ResourcePropertySource; import net.oschina.j2cache.J2CacheConfig; +import java.util.Objects; + public class SpringJ2CacheConfigUtil { /** * 从spring环境变量中查找j2cache配置 + * @param environment configuration + * @return j2cache config instance */ public final static J2CacheConfig initFromConfig(StandardEnvironment environment){ J2CacheConfig config = new J2CacheConfig(); @@ -19,12 +24,11 @@ public class SpringJ2CacheConfigUtil { config.setSyncTtlToRedis(!"false".equalsIgnoreCase(environment.getProperty("j2cache.sync_ttl_to_redis"))); config.setDefaultCacheNullObject("true".equalsIgnoreCase(environment.getProperty("j2cache.default_cache_null_object"))); String l2_config_section = environment.getProperty("j2cache.L2.config_section"); - if (l2_config_section == null || l2_config_section.trim().equals("")) - l2_config_section = config.getL2CacheName(); + if (l2_config_section == null || Objects.equals(l2_config_section.trim(),"")) l2_config_section = config.getL2CacheName(); final String l2_section = l2_config_section; environment.getPropertySources().forEach(a -> { - if(a instanceof ResourcePropertySource) { - ResourcePropertySource c = (ResourcePropertySource) a; + if(a instanceof MapPropertySource) { + MapPropertySource c = (MapPropertySource) a; c.getSource().forEach((k,v) -> { String key = k; if (key.startsWith(config.getBroadcast() + ".")) { diff --git a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java index 6623cad6a5c7834f95f15ddd82360401d2cf6287..c0a92cc7cc21a1d7fdb74582c46de1b094b10ecc 100644 --- a/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java +++ b/modules/spring-boot-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java @@ -7,12 +7,16 @@ import org.springframework.context.ApplicationContextAware; /** * spring 工具类 * @author zhangsaizz - * */ public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; + /** + * setApplicationContext + * @param applicationContext application context + * @throws BeansException exception + */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringUtil.applicationContext == null) { @@ -22,28 +26,25 @@ public class SpringUtil implements ApplicationContextAware { /** * 获取applicationContext + * @return ApplicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** - * 通过name获取 Bean. + * 通过name获取 Bean. + * @param name cache name + * @return cache object */ public static Object getBean(String name) { return getApplicationContext().getBean(name); } - /** - * 通过class获取Bean. - */ public static T getBean(Class clazz) { return getApplicationContext().getBean(clazz); } - /** - * 通过name,以及Clazz返回指定的Bean - */ public static T getBean(String name, Class clazz) { return getApplicationContext().getBean(name, clazz); } diff --git a/modules/spring-boot2-starter/pom.xml b/modules/spring-boot2-starter/pom.xml index c55e25217124091e40daac7664b694d302942fa7..ac3a5d41a1123c373c17c21113aafb4a65767cbe 100644 --- a/modules/spring-boot2-starter/pom.xml +++ b/modules/spring-boot2-starter/pom.xml @@ -5,7 +5,7 @@ j2cache net.oschina.j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml 4.0.0 @@ -16,14 +16,13 @@ net.oschina.j2cache j2cache-core - ${j2cache-version} org.slf4j slf4j-simple - compile + provided org.springframework.boot @@ -73,6 +72,6 @@ - 2.0.1.RELEASE + 2.2.5.RELEASE - \ No newline at end of file + diff --git a/modules/spring-boot2-starter/readme.md b/modules/spring-boot2-starter/readme.md index cfe2047f1b7ff956c5df917ba6da0d47ebdb9528..da76adf418ccbcc3c7b8fe35147e4585d526c2ad 100644 --- a/modules/spring-boot2-starter/readme.md +++ b/modules/spring-boot2-starter/readme.md @@ -32,9 +32,16 @@ j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPol 在j2cache.properties中配置,使用springRedis替换二级缓存 ``` j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider -j2cache.L2.config_section = redis +j2cache.L2.config_section = redis (如果要使用lettuce客户端请配置为lettuce) +``` +在application.properties中支持redis客户端 +* jedis +* lettuce +``` +j2cache.redis-client=jedis +``` +在application.properties中支持关闭二级缓存 +``` +j2cache.l2-cache-open=false(默认开启) ``` - - - diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java index 1049c8c94907d3762ba5e3737137fb7da123d29a..71d4924a2fe74f932ee7e03d19a9c939b478dec7 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheAutoConfiguration.java @@ -24,19 +24,18 @@ import net.oschina.j2cache.cache.support.util.SpringUtil; @ConditionalOnClass(J2Cache.class) @EnableConfigurationProperties({J2CacheConfig.class}) @Configuration -@PropertySource(value = "${j2cache.config-location}") +@PropertySource(value = "${j2cache.config-location}", encoding = "UTF-8", ignoreResourceNotFound = true) public class J2CacheAutoConfiguration { - + @Autowired private StandardEnvironment standardEnvironment; @Bean public net.oschina.j2cache.J2CacheConfig j2CacheConfig() throws IOException{ - net.oschina.j2cache.J2CacheConfig cacheConfig = new net.oschina.j2cache.J2CacheConfig(); - cacheConfig = SpringJ2CacheConfigUtil.initFromConfig(standardEnvironment); + net.oschina.j2cache.J2CacheConfig cacheConfig = SpringJ2CacheConfigUtil.initFromConfig(standardEnvironment); return cacheConfig; } - + @Bean @DependsOn({"springUtil","j2CacheConfig"}) public CacheChannel cacheChannel(net.oschina.j2cache.J2CacheConfig j2CacheConfig) throws IOException { diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java index cb2b0e4ac32405f5dfd79351e198b21a4af7af9e..490d68ed0a92d8a7bcfe0b3fddcdd18d2210874e 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheConfig.java @@ -26,9 +26,9 @@ public class J2CacheConfig { private String cacheCleanMode = "passive"; /** - * 是否允许缓存空值,默认:true + * 是否允许缓存空值,默认:false */ - private boolean allowNullValues = true; + private boolean allowNullValues = false; /** * 使用哪种redis客户端,默认:jedis @@ -38,6 +38,11 @@ public class J2CacheConfig { * */ private String redisClient = "jedis"; + + /** + * 是否开启二级缓存 + */ + private boolean l2CacheOpen = true; public String getConfigLocation() { @@ -79,4 +84,13 @@ public class J2CacheConfig { public void setRedisClient(String redisClient) { this.redisClient = redisClient; } + + public boolean getL2CacheOpen() { + return l2CacheOpen; + } + + public void setL2CacheOpen(boolean l2CacheOpen) { + this.l2CacheOpen = l2CacheOpen; + } + } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java index e49f28082d803459fc36467804e5457b076dd2ee..9afd767ea699a9944e28f139030a2ba09a07c295 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/autoconfigure/J2CacheSpringRedisAutoConfiguration.java @@ -46,13 +46,14 @@ import redis.clients.jedis.exceptions.JedisConnectionException; /** * 对spring redis支持的配置入口 - * + * * @author zhangsaizz * */ @Configuration @AutoConfigureAfter({ RedisAutoConfiguration.class }) @AutoConfigureBefore({ J2CacheAutoConfiguration.class }) +@ConditionalOnProperty(value = "j2cache.l2-cache-open", havingValue = "true", matchIfMissing = true) public class J2CacheSpringRedisAutoConfiguration { private final static int MAX_ATTEMPTS = 3; @@ -68,7 +69,7 @@ public class J2CacheSpringRedisAutoConfiguration { public JedisConnectionFactory jedisConnectionFactory(net.oschina.j2cache.J2CacheConfig j2CacheConfig) { Properties l2CacheProperties = j2CacheConfig.getL2CacheProperties(); String hosts = l2CacheProperties.getProperty("hosts"); - String mode = l2CacheProperties.getProperty("mode"); + String mode = l2CacheProperties.getProperty("mode") == null ? "null" : l2CacheProperties.getProperty("mode"); String clusterName = l2CacheProperties.getProperty("cluster_name"); String password = l2CacheProperties.getProperty("password"); int database = l2CacheProperties.getProperty("database") == null ? 0 @@ -149,7 +150,7 @@ public class J2CacheSpringRedisAutoConfiguration { public LettuceConnectionFactory lettuceConnectionFactory(net.oschina.j2cache.J2CacheConfig j2CacheConfig) { Properties l2CacheProperties = j2CacheConfig.getL2CacheProperties(); String hosts = l2CacheProperties.getProperty("hosts"); - String mode = l2CacheProperties.getProperty("mode"); + String mode = l2CacheProperties.getProperty("mode") == null ? "null" : l2CacheProperties.getProperty("mode"); String clusterName = l2CacheProperties.getProperty("cluster_name"); String password = l2CacheProperties.getProperty("password"); int database = l2CacheProperties.getProperty("database") == null ? 0 @@ -207,6 +208,7 @@ public class J2CacheSpringRedisAutoConfiguration { log.warn("Redis mode [" + mode + "] not defined. Using 'single'."); break; } + connectionFactory.setValidateConnection(true); return connectionFactory; } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java index 0ec59bdab59ceef2d6e2b5fdf4d8cdb7eb5d0418..1d58ff90cdc257a8e1be20c92915d06994822fd6 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/J2CacheCache.java @@ -36,7 +36,7 @@ public class J2CacheCache extends AbstractValueAdaptingCache { return this.j2CacheName; } - public void setJ2CacheNmae(String name) { + public void setJ2CacheName(String name) { this.j2CacheName = name; } @@ -46,7 +46,12 @@ public class J2CacheCache extends AbstractValueAdaptingCache { } @Override - public T get(Object key, Callable valueLoader) { + public synchronized T get(Object key, Callable valueLoader) { + ValueWrapper valueWrapper = this.get(key); + if (valueWrapper != null) { + return (T) valueWrapper.get(); + } + T value; try { value = valueLoader.call(); @@ -82,7 +87,7 @@ public class J2CacheCache extends AbstractValueAdaptingCache { @Override protected Object lookup(Object key) { - CacheObject cacheObject = cacheChannel.get(j2CacheName, String.valueOf(key), super.isAllowNullValues()); + CacheObject cacheObject = cacheChannel.get(j2CacheName, String.valueOf(key), false); if(cacheObject.rawValue() != null && cacheObject.rawValue().getClass().equals(NullObject.class) && super.isAllowNullValues()) { return NullValue.INSTANCE; } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java index 6d232ae4f3b3d5d2b5178d3744d36279f8042eed..2538d00afb0722e3051d789073a2b8b8d85526bb 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisCache.java @@ -1,11 +1,7 @@ package net.oschina.j2cache.cache.support.redis; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; @@ -43,7 +39,7 @@ public class SpringRedisCache implements Level2Cache { @Override public void clear() { - redisTemplate.opsForHash().delete(region); + redisTemplate.delete(region); } @Override @@ -54,7 +50,7 @@ public class SpringRedisCache implements Level2Cache { @Override public void evict(String... keys) { for (String k : keys) { - if (!k.equals("null")) { + if (!Objects.equals(k, "null")) { redisTemplate.opsForHash().delete(region, k); } else { redisTemplate.delete(region); diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java index 66d1d32fe4fa0c5f961b5aaf65d2793eed293af7..49eb85b272c630538a6227c17fc8e97c9d3aaca7 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisGenericCache.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +45,7 @@ public class SpringRedisGenericCache implements Level2Cache { public void clear() { Collection keys = keys(); keys.stream().forEach(k -> { - redisTemplate.delete(k); + redisTemplate.delete(this.region + ":" + k); }); } @@ -66,12 +67,7 @@ public class SpringRedisGenericCache implements Level2Cache { @Override public Collection keys() { - Set list = redisTemplate.keys(this.region + ":*"); - List keys = new ArrayList<>(list.size()); - for (String s : list) { - keys.add(s); - } - return keys; + return redisTemplate.keys(this.region + ":*").stream().map(k->k.substring(this.region.length()+1)).collect(Collectors.toSet()); } @Override @@ -95,7 +91,7 @@ public class SpringRedisGenericCache implements Level2Cache { log.debug(String.format("Invalid timeToLiveInSeconds value : %d , skipped it.", timeToLiveInSeconds)); setBytes(key, bytes); } else { - redisTemplate.opsForValue().getOperations().execute((RedisCallback>) redis -> { + redisTemplate.execute((RedisCallback>) redis -> { redis.setEx(_key(key), (int) timeToLiveInSeconds, bytes); return null; }); diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java index efaf1074e3987abb19016b3641185f748bb3b84b..ff7e780fbb7cd2aeaefa820280ed0031505b9f8c 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisMessageListener.java @@ -17,6 +17,7 @@ import net.oschina.j2cache.util.SerializationUtils; public class SpringRedisMessageListener implements MessageListener{ private static Logger logger = LoggerFactory.getLogger(SpringRedisMessageListener.class); + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 private ClusterPolicy clusterPolicy; @@ -26,7 +27,11 @@ public class SpringRedisMessageListener implements MessageListener{ this.clusterPolicy = clusterPolicy; this.channel = channel; } - + + private boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + @Override public void onMessage(Message message, byte[] pattern) { byte[] messageChannel = message.getChannel(); @@ -36,7 +41,7 @@ public class SpringRedisMessageListener implements MessageListener{ } try { Command cmd = Command.parse(String.valueOf(SerializationUtils.deserialize(messageBody))); - if (cmd == null || cmd.isLocal()) + if (cmd == null || isLocalCommand(cmd)) return; switch (cmd.getOperator()) { diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java index 10cb7e1d7c23ebb2ce4fd7118c7678a7d1270169..0ef416a1e9bf1905068a0fb1fbb8a5555edf4250 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisProvider.java @@ -13,6 +13,7 @@ import net.oschina.j2cache.CacheChannel; import net.oschina.j2cache.CacheExpiredListener; import net.oschina.j2cache.CacheObject; import net.oschina.j2cache.CacheProvider; +import net.oschina.j2cache.NullCache; import net.oschina.j2cache.cache.support.util.SpringUtil; /** @@ -23,6 +24,8 @@ import net.oschina.j2cache.cache.support.util.SpringUtil; public class SpringRedisProvider implements CacheProvider { private RedisTemplate redisTemplate; + + private net.oschina.j2cache.autoconfigure.J2CacheConfig config; private String namespace; @@ -47,6 +50,9 @@ public class SpringRedisProvider implements CacheProvider { @Override public Cache buildCache(String region, CacheExpiredListener listener) { + if(config.getL2CacheOpen() == false) { + return new NullCache(); + } Cache cache = caches.get(region); if (cache == null) { synchronized (SpringRedisProvider.class) { @@ -74,6 +80,10 @@ public class SpringRedisProvider implements CacheProvider { public void start(Properties props) { this.namespace = props.getProperty("namespace"); this.storage = props.getProperty("storage"); + this.config = SpringUtil.getBean(net.oschina.j2cache.autoconfigure.J2CacheConfig.class); + if(config.getL2CacheOpen() == false) { + return; + } this.redisTemplate = SpringUtil.getBean("j2CacheRedisTemplate", RedisTemplate.class); } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java index 62247ad16fb501a073968268aecbd69d83de4eb1..eca5aa70353dab4c70b0934dd8723913161bc366 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/redis/SpringRedisPubSubPolicy.java @@ -9,89 +9,112 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import net.oschina.j2cache.cluster.ClusterPolicy; +import net.oschina.j2cache.CacheProviderHolder; import net.oschina.j2cache.Command; import net.oschina.j2cache.J2CacheConfig; import net.oschina.j2cache.cache.support.util.SpringUtil; +import net.oschina.j2cache.cluster.ClusterPolicy; /** * 使用spring redis实现订阅功能 * @author zhangsaizz */ public class SpringRedisPubSubPolicy implements ClusterPolicy { + + private int LOCAL_COMMAND_ID = Command.genRandomSrc(); //命令源标识,随机生成,每个节点都有唯一标识 private RedisTemplate redisTemplate; private net.oschina.j2cache.autoconfigure.J2CacheConfig config; + private CacheProviderHolder holder; + /** * 是否是主动模式 */ private static boolean isActive = false; private String channel = "j2cache_channel"; - + + @Override + public boolean isLocalCommand(Command cmd) { + return cmd.getSrc() == LOCAL_COMMAND_ID; + } + @SuppressWarnings("unchecked") @Override - public void connect(Properties props) { - J2CacheConfig j2config = SpringUtil.getBean(J2CacheConfig.class); + public void connect(Properties props, CacheProviderHolder holder) { + this.holder = holder; this.config = SpringUtil.getBean(net.oschina.j2cache.autoconfigure.J2CacheConfig.class); - this.redisTemplate = SpringUtil.getBean("j2CacheRedisTemplate", RedisTemplate.class); - if("active".equals(config.getCacheCleanMode())) { - isActive = true; + if(config.getL2CacheOpen() == false) { + return; } + J2CacheConfig j2config = SpringUtil.getBean(J2CacheConfig.class); + this.redisTemplate = SpringUtil.getBean("j2CacheRedisTemplate", RedisTemplate.class); String channel_name = j2config.getL2CacheProperties().getProperty("channel"); if(channel_name != null && !channel_name.isEmpty()) { this.channel = channel_name; } RedisMessageListenerContainer listenerContainer = SpringUtil.getBean("j2CacheRedisMessageListenerContainer", RedisMessageListenerContainer.class); + String namespace = j2config.getL2CacheProperties().getProperty("namespace"); + String database = j2config.getL2CacheProperties().getProperty("database"); + String expired = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:expired"; + String del = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:del"; + List topics = new ArrayList<>(); + topics.add(new PatternTopic(expired)); + topics.add(new PatternTopic(del)); - listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), new PatternTopic(this.channel)); - if(isActive || "blend".equals(config.getCacheCleanMode())) { - //设置键值回调 + if("active".equals(config.getCacheCleanMode())) { + isActive = true; + //设置键值回调 需要redis支持键值回调 + ConfigureNotifyKeyspaceEventsAction action = new ConfigureNotifyKeyspaceEventsAction(); + action.config(listenerContainer.getConnectionFactory().getConnection()); + listenerContainer.addMessageListener(new SpringRedisActiveMessageListener(this, namespace), topics); + }else if("blend".equals(config.getCacheCleanMode())) { + //设置键值回调 需要redis支持键值回调 ConfigureNotifyKeyspaceEventsAction action = new ConfigureNotifyKeyspaceEventsAction(); action.config(listenerContainer.getConnectionFactory().getConnection()); - - String namespace = j2config.getL2CacheProperties().getProperty("namespace"); - String database = j2config.getL2CacheProperties().getProperty("database"); - String expired = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:expired"; - String del = "__keyevent@" + (database == null || "".equals(database) ? "0" : database) + "__:del"; - List topics = new ArrayList<>(); - topics.add(new PatternTopic(expired)); - topics.add(new PatternTopic(del)); listenerContainer.addMessageListener(new SpringRedisActiveMessageListener(this, namespace), topics); + listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), new PatternTopic(this.channel)); + }else { + listenerContainer.addMessageListener(new SpringRedisMessageListener(this, this.channel), new PatternTopic(this.channel)); } } -// @Override -// public void sendEvictCmd(String region, String... keys) { -// if(!isActive || "blend".equals(config.getCacheCleanMode())) { -// String com = new Command(Command.OPT_EVICT_KEY, region, keys).json(); -// redisTemplate.convertAndSend(this.channel, com); -// } -// -// } -// @Override -// public void sendClearCmd(String region) { -// if(!isActive || "blend".equals(config.getCacheCleanMode())) { -// String com = new Command(Command.OPT_CLEAR_KEY, region, "").json(); -// redisTemplate.convertAndSend(this.channel, com); -// } -// } + /** + * 删除本地某个缓存条目 + * @param region 区域名称 + * @param keys 缓存键值 + */ + public void evict(String region, String... keys) { + holder.getLevel1Cache(region).evict(keys); + } + + /** + * 清除本地整个缓存区域 + * @param region 区域名称 + */ + public void clear(String region) { + holder.getLevel1Cache(region).clear(); + } @Override public void publish(Command cmd) { - if(!isActive || "blend".equals(config.getCacheCleanMode())) { + if(!isActive && config.getL2CacheOpen()) { + cmd.setSrc(LOCAL_COMMAND_ID); redisTemplate.convertAndSend(this.channel, cmd.json()); } } - @Override public void disconnect() { - redisTemplate.convertAndSend(this.channel, Command.quit().json()); + if(!isActive && config.getL2CacheOpen()) { + Command cmd = new Command(); + cmd.setSrc(LOCAL_COMMAND_ID); + cmd.setOperator(Command.OPT_QUIT); + redisTemplate.convertAndSend(this.channel, cmd.json()); + } } - } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java index 867b9bf10fb0bd96fa748c52e96b3e7206dea08a..e3cf870e0f5dad5beae517316e0bec0d92a84c24 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringJ2CacheConfigUtil.java @@ -1,14 +1,19 @@ package net.oschina.j2cache.cache.support.util; +import net.oschina.j2cache.J2CacheConfig; +import org.springframework.core.env.CompositePropertySource; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.StandardEnvironment; -import org.springframework.core.io.support.ResourcePropertySource; -import net.oschina.j2cache.J2CacheConfig; +import java.util.Objects; public class SpringJ2CacheConfigUtil { /** * 从spring环境变量中查找j2cache配置 + * @param environment configuration + * @return j2cache configuration */ public final static J2CacheConfig initFromConfig(StandardEnvironment environment){ J2CacheConfig config = new J2CacheConfig(); @@ -19,18 +24,18 @@ public class SpringJ2CacheConfigUtil { config.setSyncTtlToRedis(!"false".equalsIgnoreCase(environment.getProperty("j2cache.sync_ttl_to_redis"))); config.setDefaultCacheNullObject("true".equalsIgnoreCase(environment.getProperty("j2cache.default_cache_null_object"))); String l2_config_section = environment.getProperty("j2cache.L2.config_section"); - if (l2_config_section == null || l2_config_section.trim().equals("")) + if (l2_config_section == null || Objects.equals(l2_config_section.trim(),"")) l2_config_section = config.getL2CacheName(); final String l2_section = l2_config_section; environment.getPropertySources().forEach(a -> { - if(a instanceof ResourcePropertySource) { - ResourcePropertySource c = (ResourcePropertySource) a; + if(a instanceof MapPropertySource) { + MapPropertySource c = (MapPropertySource) a; c.getSource().forEach((k,v) -> { String key = k; if (key.startsWith(config.getBroadcast() + ".")) { config.getBroadcastProperties().setProperty(key.substring((config.getBroadcast() + ".").length()), environment.getProperty(key)); - } + } if (key.startsWith(config.getL1CacheName() + ".")) { config.getL1CacheProperties().setProperty(key.substring((config.getL1CacheName() + ".").length()), environment.getProperty(key)); @@ -42,6 +47,35 @@ public class SpringJ2CacheConfigUtil { }); } }); + //配置在 nacos 中时,上面那段代码无法获取配置 + if (config.getL1CacheProperties().isEmpty() || config.getL2CacheProperties().isEmpty() || config.getBroadcastProperties().isEmpty()) { + environment.getPropertySources().forEach(a -> { + String[] propertyNames = new String[0]; + if (a instanceof CompositePropertySource) { + CompositePropertySource c = (CompositePropertySource) a; + propertyNames = c.getPropertyNames(); + } else if (a instanceof EnumerablePropertySource){ + EnumerablePropertySource c = (EnumerablePropertySource) a; + propertyNames = c.getPropertyNames(); + } + if (propertyNames.length > 0){ + for (String key : propertyNames) { + if (key.startsWith(config.getBroadcast() + ".")) { + config.getBroadcastProperties().setProperty(key.substring((config.getBroadcast() + ".").length()), + environment.getProperty(key)); + } + if (key.startsWith(config.getL1CacheName() + ".")) { + config.getL1CacheProperties().setProperty(key.substring((config.getL1CacheName() + ".").length()), + environment.getProperty(key)); + } + if (key.startsWith(l2_section + ".")) { + config.getL2CacheProperties().setProperty(key.substring((l2_section + ".").length()), + environment.getProperty(key)); + } + } + } + }); + } return config; } } diff --git a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java index 6623cad6a5c7834f95f15ddd82360401d2cf6287..7cdbcf495daec19c1fa92f3265f3ad0b8fc5935e 100644 --- a/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java +++ b/modules/spring-boot2-starter/src/net/oschina/j2cache/cache/support/util/SpringUtil.java @@ -20,30 +20,18 @@ public class SpringUtil implements ApplicationContextAware { } } - /** - * 获取applicationContext - */ public static ApplicationContext getApplicationContext() { return applicationContext; } - /** - * 通过name获取 Bean. - */ public static Object getBean(String name) { return getApplicationContext().getBean(name); } - /** - * 通过class获取Bean. - */ public static T getBean(Class clazz) { return getApplicationContext().getBean(clazz); } - /** - * 通过name,以及Clazz返回指定的Bean - */ public static T getBean(String name, Class clazz) { return getApplicationContext().getBean(name, clazz); } diff --git a/modules/spring-boot2-starter/test/src/com/test/ApplicationTests.java b/modules/spring-boot2-starter/test/src/com/test/ApplicationTests.java index 8911a753e512670ca047c19f720047e22cf7acd3..7f9fd66e6adb96453a21f80581f2bc525db562bf 100644 --- a/modules/spring-boot2-starter/test/src/com/test/ApplicationTests.java +++ b/modules/spring-boot2-starter/test/src/com/test/ApplicationTests.java @@ -1,5 +1,8 @@ package com.test; +import java.io.IOException; +import java.util.Random; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -17,27 +20,60 @@ import net.oschina.j2cache.autoconfigure.J2CacheSpringCacheAutoConfiguration; import net.oschina.j2cache.autoconfigure.J2CacheSpringRedisAutoConfiguration; @RunWith(SpringRunner.class) -@SpringBootTest(classes = { TestService.class, J2CacheAutoConfiguration.class, - J2CacheSpringCacheAutoConfiguration.class, J2CacheSpringRedisAutoConfiguration.class }, properties = { - "j2cache.config-location=classpath:/com/test/j2cache-test.properties", "spring.cache.type=GENERIC", - "j2cache.open-spring-cache=true", "j2cache.j2CacheConfig.serialization=json","j2cache.redis-client=jedis"}) +@SpringBootTest(classes = { + TestService.class, + J2CacheAutoConfiguration.class, + J2CacheSpringCacheAutoConfiguration.class, + J2CacheSpringRedisAutoConfiguration.class }, + properties = { + "j2cache.config-location=classpath:/com/test/j2cache-test.properties", + "spring.cache.type=GENERIC", + "j2cache.open-spring-cache=true", + "j2cache.j2CacheConfig.serialization=json", + "j2cache.redis-client=jedis", + "j2cache.cache-clean-mode=active", + "j2cache.allow-null-values=true", + "j2cache.l2-cache-open=true" + }) public class ApplicationTests { @Autowired private TestService testService; - + @Autowired private CacheChannel cacheChannel; @Test - public void testCache() { + public void testCache() throws IOException { testService.reset(); testService.evict(); testService.getNum(); - Integer n = testService.getNum(); - Assert.isTrue(n == 1, "缓存未生效!"); + testService.getNum(); +// testService.getNum(); +// testService.getNum(); +// Integer n = testService.getNum(); +// Assert.isTrue(n == 1, "缓存未生效!"); + for (int i = 1; i < 200; i++) { + new Thread(() -> { + for (int j = 1; j < 1000; j++) { + Integer n = testService.getNum(); + try { + Random r = new Random(); + Thread.sleep(r.nextInt(100)); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } +// if(n == null) { +// System.out.println(Thread.currentThread().getId() + ":出现缓存为null:" + j); +// } + } + }).start(); + } + System.in.read(); + } - + @Test public void clearCache() { testService.reset(); @@ -47,7 +83,7 @@ public class ApplicationTests { Integer a = testService.getNum(); Assert.isTrue(a == 1, "清除缓存未生效!"); } - + @Test public void beanCache() { testService.reset(); @@ -57,11 +93,18 @@ public class ApplicationTests { Integer a = b.getNum(); Assert.isTrue(a == 1, "对象缓存未生效!"); } - + @Test public void test() { cacheChannel.set("test", "123", "321"); CacheObject a = cacheChannel.get("test", "123"); Assert.isTrue(a.getValue().equals("321"), "失败!"); } + + @Test + public void test1() { +// cacheChannel.set("test", "123", "321"); + CacheObject a = cacheChannel.get("test", "1233"); + Assert.isTrue(a.getValue().equals("321"), "失败!"); + } } diff --git a/modules/springcache/pom.xml b/modules/springcache/pom.xml index 29eca3a315a466b762844972d1fac58108a31bea..b633342c51a96ca5e496d81ee39f6eb98a616465 100644 --- a/modules/springcache/pom.xml +++ b/modules/springcache/pom.xml @@ -5,7 +5,7 @@ j2cache net.oschina.j2cache - 2.7.0-release + 2.8.0-release ../../pom.xml 4.0.0 @@ -16,13 +16,12 @@ org.springframework spring-context-support - 4.3.6.RELEASE + 4.3.10.RELEASE net.oschina.j2cache j2cache-core - ${j2cache-version} junit @@ -34,4 +33,4 @@ test/src - \ No newline at end of file + diff --git a/modules/springcache/src/net/oschina/j2cache/springcache/J2CacheSpringCacheAdapter.java b/modules/springcache/src/net/oschina/j2cache/springcache/J2CacheSpringCacheAdapter.java index 10bf27be8024a4b7ec662a7aecf268dcaf23a9f8..9fc6fa24d0129b3ee94014a56dc5f1f60440c8ea 100644 --- a/modules/springcache/src/net/oschina/j2cache/springcache/J2CacheSpringCacheAdapter.java +++ b/modules/springcache/src/net/oschina/j2cache/springcache/J2CacheSpringCacheAdapter.java @@ -1,12 +1,16 @@ package net.oschina.j2cache.springcache; import net.oschina.j2cache.CacheChannel; +import net.oschina.j2cache.NullObject; import org.springframework.cache.CacheManager; import org.springframework.cache.support.AbstractValueAdaptingCache; +import org.springframework.cache.support.NullValue; import java.util.concurrent.Callable; /** + * Spring Cache Adapter + * * @author Chen */ public class J2CacheSpringCacheAdapter extends AbstractValueAdaptingCache { @@ -18,6 +22,8 @@ public class J2CacheSpringCacheAdapter extends AbstractValueAdaptingCache { * Create an {@code AbstractValueAdaptingCache} with the given setting. * * @param allowNullValues whether to allow for {@code null} values + * @param j2Cache j2cache instance + * @param name cache region name */ protected J2CacheSpringCacheAdapter(boolean allowNullValues, CacheChannel j2Cache, String name) { super(allowNullValues); @@ -39,7 +45,14 @@ public class J2CacheSpringCacheAdapter extends AbstractValueAdaptingCache { @Override protected Object lookup(Object key) { - return j2Cache.get(name, getKey(key)).getValue(); + Object value = j2Cache.get(name, getKey(key), false).rawValue(); + if (value == null || value.getClass().equals(Object.class)) { + return null; + } + if (value.getClass().equals(NullObject.class)) { + return NullValue.INSTANCE; + } + return value; } /** @@ -70,7 +83,7 @@ public class J2CacheSpringCacheAdapter extends AbstractValueAdaptingCache { * a {@link ValueRetrievalException} * * @param key the key whose associated value is to be returned - * @param valueLoader + * @param valueLoader value loader * @return the value to which this cache maps the specified key * @throws ValueRetrievalException if the {@code valueLoader} throws an exception * @since 4.3 @@ -79,6 +92,9 @@ public class J2CacheSpringCacheAdapter extends AbstractValueAdaptingCache { public T get(Object key, Callable valueLoader) throws ValueRetrievalException { ValueWrapper val = get(key); if (val != null) { + if (val.get() instanceof NullObject) { + return null; + } return (T) val.get(); } T t; diff --git a/pom.xml b/pom.xml index aa2f090c927158fa0c89acb508e4d78b02d74f27..e41aaa564c498782059e096228d16b765bf7a179 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,10 @@ 4.0.0 - + net.oschina.j2cache j2cache - 2.7.0-release + 2.8.0-release pom j2cache @@ -36,10 +36,9 @@ https://oss.sonatype.org/service/local/staging/deploy/maven2/ - + UTF-8 - 2.7.0-release @@ -89,6 +88,12 @@ sign + + + --pinentry-mode + loopback + + @@ -128,6 +133,7 @@ core modules/hibernate3 modules/hibernate4 + modules/hibernate5 modules/spring-boot-starter modules/spring-boot2-starter modules/mybatis @@ -135,6 +141,16 @@ modules/session-manager + + + + net.oschina.j2cache + j2cache-core + ${project.version} + + + + @@ -153,4 +169,4 @@ - \ No newline at end of file + diff --git a/runtest.bat b/runtest.bat new file mode 100644 index 0000000000000000000000000000000000000000..05f60327bec860c95a9b0b19c66066d480ae4adf --- /dev/null +++ b/runtest.bat @@ -0,0 +1,2 @@ +title J2Cache test +mvn exec:java -pl core \ No newline at end of file