• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / ibatis-2 / 730

28 Dec 2025 10:16PM UTC coverage: 65.615% (+0.5%) from 65.146%
730

push

github

web-flow
Update README.md

1602 of 2802 branches covered (57.17%)

5053 of 7701 relevant lines covered (65.61%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.32
/src/main/java/com/ibatis/sqlmap/engine/cache/CacheModel.java
1
/*
2
 * Copyright 2004-2025 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 com.ibatis.sqlmap.engine.cache;
17

18
import com.ibatis.common.logging.Log;
19
import com.ibatis.common.logging.LogFactory;
20
import com.ibatis.sqlmap.engine.mapping.statement.ExecuteListener;
21
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
22

23
import java.io.ByteArrayInputStream;
24
import java.io.ByteArrayOutputStream;
25
import java.io.IOException;
26
import java.io.ObjectInputStream;
27
import java.io.ObjectOutputStream;
28
import java.util.HashSet;
29
import java.util.Iterator;
30
import java.util.Properties;
31
import java.util.Set;
32

33
/**
34
 * Wrapper for Caches.
35
 */
36
public class CacheModel implements ExecuteListener {
37

38
  /** The Constant log. */
39
  private static final Log log = LogFactory.getLog(CacheModel.class);
1✔
40

41
  /** The Constant MAX_OBJECT_LOG_SIZE. */
42
  private static final int MAX_OBJECT_LOG_SIZE = 200;
43

44
  /**
45
   * This is used to represent null objects that are returned from the cache so that they can be cached, too.
46
   */
47
  public static final Object NULL_OBJECT = "SERIALIZABLE_NULL_OBJECT";
1✔
48

49
  /** The requests. */
50
  private int requests = 0;
1✔
51

52
  /** The hits. */
53
  private int hits = 0;
1✔
54

55
  /** Constant to turn off periodic cache flushes. */
56
  private static final long NO_FLUSH_INTERVAL = -99999;
57

58
  /** The id. */
59
  private String id;
60

61
  /** The read only. */
62
  private boolean readOnly;
63

64
  /** The serialize. */
65
  private boolean serialize;
66

67
  /** The last flush. */
68
  private long lastFlush;
69

70
  /** The flush interval. */
71
  private long flushInterval;
72

73
  /** The flush interval seconds. */
74
  private long flushIntervalSeconds;
75

76
  /** The flush trigger statements. */
77
  private Set flushTriggerStatements;
78

79
  /** The controller. */
80
  private CacheController controller;
81

82
  /** The resource. */
83
  private String resource;
84

85
  /**
86
   * Default constructor.
87
   */
88
  public CacheModel() {
1✔
89
    this.flushInterval = NO_FLUSH_INTERVAL;
1✔
90
    this.flushIntervalSeconds = NO_FLUSH_INTERVAL;
1✔
91
    this.lastFlush = System.currentTimeMillis();
1✔
92
    this.flushTriggerStatements = new HashSet<>();
1✔
93
  }
1✔
94

95
  /**
96
   * Getter for the cache model's id.
97
   *
98
   * @return the id
99
   */
100
  public String getId() {
101
    return id;
1✔
102
  }
103

104
  /**
105
   * Setter for the cache model's id.
106
   *
107
   * @param id
108
   *          - the new id
109
   */
110
  public void setId(String id) {
111
    this.id = id;
1✔
112
  }
1✔
113

114
  /**
115
   * Getter for read-only property.
116
   *
117
   * @return true if a read-only model
118
   */
119
  public boolean isReadOnly() {
120
    return readOnly;
1✔
121
  }
122

123
  /**
124
   * Setter for read-only property.
125
   *
126
   * @param readOnly
127
   *          - the new setting
128
   */
129
  public void setReadOnly(boolean readOnly) {
130
    this.readOnly = readOnly;
1✔
131
  }
1✔
132

133
  /**
134
   * Getter to tell if the cache serializes.
135
   *
136
   * @return true if the cache model serializes objects
137
   */
138
  public boolean isSerialize() {
139
    return serialize;
1✔
140
  }
141

142
  /**
143
   * Setter to tell the cache to serialize objects.
144
   *
145
   * @param serialize
146
   *          - if the cache model is to serialize objects
147
   */
148
  public void setSerialize(boolean serialize) {
149
    this.serialize = serialize;
1✔
150
  }
1✔
151

152
  /**
153
   * Getter for resource property.
154
   *
155
   * @return the value of the resource property
156
   */
157
  public String getResource() {
158
    return resource;
×
159
  }
160

161
  /**
162
   * Setter for resource property.
163
   *
164
   * @param resource
165
   *          - the new value
166
   */
167
  public void setResource(String resource) {
168
    this.resource = resource;
1✔
169
  }
1✔
170

171
  /**
172
   * Sets up the controller for the cache model.
173
   *
174
   * @param controller
175
   *          the new cache controller
176
   *
177
   * @throws ClassNotFoundException
178
   *           - if the class cannot be found
179
   * @throws InstantiationException
180
   *           - if the class cannot be instantiated
181
   * @throws IllegalAccessException
182
   *           - if the classes constructor is not accessible
183
   */
184
  public void setCacheController(CacheController controller)
185
      throws ClassNotFoundException, InstantiationException, IllegalAccessException {
186
    this.controller = controller;
1✔
187
  }
1✔
188

189
  /**
190
   * Getter for flushInterval property.
191
   *
192
   * @return The flushInterval (in milliseconds)
193
   */
194
  public long getFlushInterval() {
195
    return flushInterval;
×
196
  }
197

198
  /**
199
   * Getter for flushInterval property.
200
   *
201
   * @return The flushInterval (in milliseconds)
202
   */
203
  public long getFlushIntervalSeconds() {
204
    return flushIntervalSeconds;
×
205
  }
206

207
  /**
208
   * Setter for flushInterval property.
209
   *
210
   * @param flushInterval
211
   *          The new flushInterval (in milliseconds)
212
   */
213
  public void setFlushInterval(long flushInterval) {
214
    this.flushInterval = flushInterval;
1✔
215
    this.flushIntervalSeconds = flushInterval / 1000;
1✔
216
  }
1✔
217

218
  /**
219
   * Adds a flushTriggerStatment. When a flushTriggerStatment is executed, the cache is flushed (cleared).
220
   *
221
   * @param statementName
222
   *          The statement to add.
223
   */
224
  public void addFlushTriggerStatement(String statementName) {
225
    flushTriggerStatements.add(statementName);
1✔
226
  }
1✔
227

228
  /**
229
   * Gets an Iterator containing all flushTriggerStatment objects for this cache.
230
   *
231
   * @return The Iterator
232
   */
233
  public Iterator getFlushTriggerStatementNames() {
234
    return flushTriggerStatements.iterator();
1✔
235
  }
236

237
  /**
238
   * ExecuteListener event. This will be called by a MappedStatement for which this cache is registered as a
239
   * ExecuteListener. It will be called each time an executeXXXXXX method is called. In the case of the Cache class, it
240
   * is registered in order to flush the cache whenever a certain statement is executed. (i.e. the flushOnExecute cache
241
   * policy)
242
   *
243
   * @param statement
244
   *          The statement to execute
245
   */
246
  @Override
247
  public void onExecuteStatement(MappedStatement statement) {
248
    flush();
1✔
249
  }
1✔
250

251
  /**
252
   * Returns statistical information about the cache.
253
   *
254
   * @return the number of cache hits divided by the total requests
255
   */
256
  public double getHitRatio() {
257
    return (double) hits / (double) requests;
×
258
  }
259

260
  /**
261
   * Configures the cache.
262
   *
263
   * @param props
264
   *          the props
265
   */
266
  public void configure(Properties props) {
267
    controller.setProperties(props);
×
268
  }
×
269

270
  /**
271
   * Clears the cache.
272
   */
273
  public void flush() {
274
    synchronized (this) {
1✔
275
      controller.flush(this);
1✔
276
      lastFlush = System.currentTimeMillis();
1✔
277
      if (log.isDebugEnabled()) {
1!
278
        log("flushed", false, null);
×
279
      }
280
    }
1✔
281
  }
1✔
282

283
  /**
284
   * Get an object out of the cache. A side effect of this method is that is may clear the cache if it has not been
285
   * cleared in the flushInterval.
286
   *
287
   * @param key
288
   *          The key of the object to be returned
289
   *
290
   * @return The cached object (or null)
291
   */
292
  public Object getObject(CacheKey key) {
293
    Object value = null;
1✔
294
    synchronized (this) {
1✔
295
      if (flushInterval != NO_FLUSH_INTERVAL && System.currentTimeMillis() - lastFlush > flushInterval) {
1!
296
        flush();
×
297
      }
298

299
      value = controller.getObject(this, key);
1✔
300
      if (serialize && !readOnly && value != NULL_OBJECT && value != null) {
1!
301
        try {
302
          ByteArrayInputStream bis = new ByteArrayInputStream((byte[]) value);
1✔
303
          ObjectInputStream ois = new ObjectInputStream(bis);
1✔
304
          value = ois.readObject();
1✔
305
          ois.close();
1✔
306
        } catch (Exception e) {
×
307
          throw new RuntimeException("Error caching serializable object.  Be sure you're not attempting to use "
×
308
              + "a serialized cache for an object that may be taking advantage of lazy loading.  Cause: " + e, e);
309
        }
1✔
310
      }
311
      requests++;
1✔
312
      if (value != null) {
1✔
313
        hits++;
1✔
314
      }
315
      if (log.isDebugEnabled()) {
1!
316
        if (value != null) {
×
317
          log("retrieved object", true, value);
×
318
        } else {
319
          log("cache miss", false, null);
×
320
        }
321
      }
322
    }
1✔
323
    return value;
1✔
324
  }
325

326
  /**
327
   * Add an object to the cache.
328
   *
329
   * @param key
330
   *          The key of the object to be cached
331
   * @param value
332
   *          The object to be cached
333
   */
334
  public void putObject(CacheKey key, Object value) {
335
    if (null == value) {
1!
336
      value = NULL_OBJECT;
×
337
    }
338
    synchronized (this) {
1✔
339
      if (serialize && !readOnly && value != NULL_OBJECT) {
1!
340
        try {
341
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
1✔
342
          ObjectOutputStream oos = new ObjectOutputStream(bos);
1✔
343
          oos.writeObject(value);
1✔
344
          oos.flush();
1✔
345
          oos.close();
1✔
346
          value = bos.toByteArray();
1✔
347
        } catch (IOException e) {
×
348
          throw new RuntimeException("Error caching serializable object.  Cause: " + e, e);
×
349
        }
1✔
350
      }
351
      controller.putObject(this, key, value);
1✔
352
      if (log.isDebugEnabled()) {
1!
353
        log("stored object", true, value);
×
354
      }
355
    }
1✔
356
  }
1✔
357

358
  /**
359
   * Get the maximum size of an object in the log output.
360
   *
361
   * @return Maximum size of a logged object in the output
362
   */
363
  protected int getMaxObjectLogSize() {
364
    return MAX_OBJECT_LOG_SIZE;
×
365
  }
366

367
  /**
368
   * Log a cache action. Since this method is pretty heavy weight, it's best to enclose it with a log.isDebugEnabled()
369
   * when called.
370
   *
371
   * @param action
372
   *          String to output
373
   * @param addValue
374
   *          Add the value being cached to the log
375
   * @param cacheValue
376
   *          The value being logged
377
   */
378
  protected void log(String action, boolean addValue, Object cacheValue) {
379
    StringBuilder output = new StringBuilder("Cache '");
×
380
    output.append(getId());
×
381
    output.append("': ");
×
382
    output.append(action);
×
383
    if (addValue) {
×
384
      String cacheObjectStr = cacheValue == null ? "null" : cacheValue.toString();
×
385
      output.append(" '");
×
386
      if (cacheObjectStr.length() < getMaxObjectLogSize()) {
×
387
        output.append(cacheObjectStr);
×
388
      } else {
389
        output.append(cacheObjectStr.substring(1, getMaxObjectLogSize()));
×
390
        output.append("...");
×
391
      }
392
      output.append("'");
×
393
    }
394
    log.debug(output.toString());
×
395
  }
×
396

397
  /**
398
   * Sets the controller properties.
399
   *
400
   * @param cacheProps
401
   *          the new controller properties
402
   */
403
  public void setControllerProperties(Properties cacheProps) {
404
    controller.setProperties(cacheProps);
1✔
405
  }
1✔
406
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc