1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.cache.decorators;
17
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.apache.ibatis.cache.Cache;
24 import org.apache.ibatis.logging.Log;
25 import org.apache.ibatis.logging.LogFactory;
26
27
28
29
30
31
32
33
34
35
36
37
38 public class TransactionalCache implements Cache {
39
40 private static final Log log = LogFactory.getLog(TransactionalCache.class);
41
42 private final Cache delegate;
43 private boolean clearOnCommit;
44 private final Map<Object, Object> entriesToAddOnCommit;
45 private final Set<Object> entriesMissedInCache;
46
47 public TransactionalCache(Cache delegate) {
48 this.delegate = delegate;
49 this.clearOnCommit = false;
50 this.entriesToAddOnCommit = new HashMap<>();
51 this.entriesMissedInCache = new HashSet<>();
52 }
53
54 @Override
55 public String getId() {
56 return delegate.getId();
57 }
58
59 @Override
60 public int getSize() {
61 return delegate.getSize();
62 }
63
64 @Override
65 public Object getObject(Object key) {
66
67 Object object = delegate.getObject(key);
68 if (object == null) {
69 entriesMissedInCache.add(key);
70 }
71
72 if (clearOnCommit) {
73 return null;
74 } else {
75 return object;
76 }
77 }
78
79 @Override
80 public void putObject(Object key, Object object) {
81 entriesToAddOnCommit.put(key, object);
82 }
83
84 @Override
85 public Object removeObject(Object key) {
86 return null;
87 }
88
89 @Override
90 public void clear() {
91 clearOnCommit = true;
92 entriesToAddOnCommit.clear();
93 }
94
95 public void commit() {
96 if (clearOnCommit) {
97 delegate.clear();
98 }
99 flushPendingEntries();
100 reset();
101 }
102
103 public void rollback() {
104 unlockMissedEntries();
105 reset();
106 }
107
108 private void reset() {
109 clearOnCommit = false;
110 entriesToAddOnCommit.clear();
111 entriesMissedInCache.clear();
112 }
113
114 private void flushPendingEntries() {
115 for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
116 delegate.putObject(entry.getKey(), entry.getValue());
117 }
118 for (Object entry : entriesMissedInCache) {
119 if (!entriesToAddOnCommit.containsKey(entry)) {
120 delegate.putObject(entry, null);
121 }
122 }
123 }
124
125 private void unlockMissedEntries() {
126 for (Object entry : entriesMissedInCache) {
127 try {
128 delegate.removeObject(entry);
129 } catch (Exception e) {
130 log.warn("Unexpected exception while notifying a rollback to the cache adapter. "
131 + "Consider upgrading your cache adapter to the latest version. Cause: " + e);
132 }
133 }
134 }
135
136 }