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