View Javadoc
1   /*
2    *    Copyright 2015-2023 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.mybatis.caches.redis;
17  
18  import java.util.Map;
19  import java.util.concurrent.locks.ReadWriteLock;
20  
21  import org.apache.ibatis.cache.Cache;
22  
23  import redis.clients.jedis.Jedis;
24  import redis.clients.jedis.JedisPool;
25  
26  /**
27   * Cache adapter for Redis.
28   *
29   * @author Eduardo Macarron
30   */
31  public final class RedisCache implements Cache {
32  
33    private final ReadWriteLock readWriteLock = new DummyReadWriteLock();
34  
35    private String id;
36  
37    private static JedisPool pool;
38  
39    private final RedisConfig redisConfig;
40  
41    private Integer timeout;
42  
43    public RedisCache(final String id) {
44      if (id == null) {
45        throw new IllegalArgumentException("Cache instances require an ID");
46      }
47      this.id = id;
48      redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
49      pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getConnectionTimeout(),
50          redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName(),
51          redisConfig.isSsl(), redisConfig.getSslSocketFactory(), redisConfig.getSslParameters(),
52          redisConfig.getHostnameVerifier());
53    }
54  
55    // TODO Review this is UNUSED
56    private Object execute(RedisCallback callback) {
57      Jedis jedis = pool.getResource();
58      try {
59        return callback.doWithRedis(jedis);
60      } finally {
61        jedis.close();
62      }
63    }
64  
65    @Override
66    public String getId() {
67      return this.id;
68    }
69  
70    @Override
71    public int getSize() {
72      return (Integer) execute(jedis -> {
73        Map<byte[], byte[]> result = jedis.hgetAll(id.getBytes());
74        return result.size();
75      });
76    }
77  
78    @Override
79    public void putObject(final Object key, final Object value) {
80      execute(jedis -> {
81        final byte[] idBytes = id.getBytes();
82        jedis.hset(idBytes, key.toString().getBytes(), redisConfig.getSerializer().serialize(value));
83        if (timeout != null && jedis.ttl(idBytes) == -1) {
84          jedis.expire(idBytes, timeout);
85        }
86        return null;
87      });
88    }
89  
90    @Override
91    public Object getObject(final Object key) {
92      return execute(
93          jedis -> redisConfig.getSerializer().unserialize(jedis.hget(id.getBytes(), key.toString().getBytes())));
94    }
95  
96    @Override
97    public Object removeObject(final Object key) {
98      return execute(jedis -> jedis.hdel(id, key.toString()));
99    }
100 
101   @Override
102   public void clear() {
103     execute(jedis -> {
104       jedis.del(id);
105       return null;
106     });
107   }
108 
109   @Override
110   public ReadWriteLock getReadWriteLock() {
111     return readWriteLock;
112   }
113 
114   @Override
115   public String toString() {
116     return "Redis {" + id + "}";
117   }
118 
119   public void setTimeout(Integer timeout) {
120     this.timeout = timeout;
121   }
122 
123 }