@@ -43,39 +43,29 @@ Wikipedia says:
43
43
** Programmatic Example**
44
44
45
45
Let's first look at the data layer of our application. The interesting classes are ` UserAccount `
46
- which is a simple Java object containing the user account details, and ` DbManager ` which handles
47
- reading and writing of these objects to/from MongoDB database.
46
+ which is a simple Java object containing the user account details, and ` DbManager ` interface which handles
47
+ reading and writing of these objects to/from database.
48
48
49
49
``` java
50
- @Setter
51
- @Getter
50
+ @Data
52
51
@AllArgsConstructor
53
52
@ToString
53
+ @EqualsAndHashCode
54
54
public class UserAccount {
55
55
private String userId;
56
56
private String userName;
57
57
private String additionalInfo;
58
58
}
59
59
60
- @Slf4j
61
- public final class DbManager {
62
-
63
- private static MongoClient mongoClient;
64
- private static MongoDatabase db;
65
-
66
- private DbManager () { /* ...*/ }
67
-
68
- public static void createVirtualDb () { /* ...*/ }
69
-
70
- public static void connect () throws ParseException { /* ...*/ }
71
-
72
- public static UserAccount readFromDb (String userId ) { /* ...*/ }
60
+ public interface DbManager {
73
61
74
- public static void writeToDb (UserAccount userAccount ) { /* ...*/ }
75
-
76
- public static void updateDb (UserAccount userAccount ) { /* ...*/ }
77
-
78
- public static void upsertDb (UserAccount userAccount ) { /* ...*/ }
62
+ void connect ();
63
+ void disconnect ();
64
+
65
+ UserAccount readFromDb (String userId );
66
+ UserAccount writeToDb (UserAccount userAccount );
67
+ UserAccount updateDb (UserAccount userAccount );
68
+ UserAccount upsertDb (UserAccount userAccount );
79
69
}
80
70
```
81
71
@@ -171,30 +161,43 @@ strategies.
171
161
@Slf4j
172
162
public class CacheStore {
173
163
164
+ private static final int CAPACITY = 3 ;
174
165
private static LruCache cache;
166
+ private final DbManager dbManager;
175
167
176
168
/* ... details omitted ... */
177
169
178
- public static UserAccount readThrough (String userId ) {
170
+ public UserAccount readThrough (final String userId ) {
179
171
if (cache. contains(userId)) {
180
- LOGGER . info(" # Cache Hit !" );
172
+ LOGGER . info(" # Found in Cache !" );
181
173
return cache. get(userId);
182
174
}
183
- LOGGER . info(" # Cache Miss !" );
184
- UserAccount userAccount = DbManager . readFromDb(userId);
175
+ LOGGER . info(" # Not found in cache! Go to DB! !" );
176
+ UserAccount userAccount = dbManager . readFromDb(userId);
185
177
cache. set(userId, userAccount);
186
178
return userAccount;
187
179
}
188
180
189
- public static void writeThrough (UserAccount userAccount ) {
181
+ public void writeThrough (final UserAccount userAccount ) {
190
182
if (cache. contains(userAccount. getUserId())) {
191
- DbManager . updateDb(userAccount);
183
+ dbManager . updateDb(userAccount);
192
184
} else {
193
- DbManager . writeToDb(userAccount);
185
+ dbManager . writeToDb(userAccount);
194
186
}
195
187
cache. set(userAccount. getUserId(), userAccount);
196
188
}
197
189
190
+ public void writeAround (final UserAccount userAccount ) {
191
+ if (cache. contains(userAccount. getUserId())) {
192
+ dbManager. updateDb(userAccount);
193
+ // Cache data has been updated -- remove older
194
+ cache. invalidate(userAccount. getUserId());
195
+ // version from cache.
196
+ } else {
197
+ dbManager. writeToDb(userAccount);
198
+ }
199
+ }
200
+
198
201
public static void clearCache () {
199
202
if (cache != null ) {
200
203
cache. clear();
@@ -225,34 +228,39 @@ class.
225
228
public final class AppManager {
226
229
227
230
private static CachingPolicy cachingPolicy;
231
+ private final DbManager dbManager;
232
+ private final CacheStore cacheStore;
228
233
229
234
private AppManager () {
230
235
}
231
236
232
- public static void initDb (boolean useMongoDb ) { /* ... */ }
237
+ public void initDb () { /* ... */ }
233
238
234
239
public static void initCachingPolicy (CachingPolicy policy ) { /* ... */ }
235
240
236
241
public static void initCacheCapacity (int capacity ) { /* ... */ }
237
242
238
- public static UserAccount find (String userId ) {
239
- if (cachingPolicy == CachingPolicy . THROUGH || cachingPolicy == CachingPolicy . AROUND ) {
240
- return CacheStore . readThrough(userId);
243
+ public UserAccount find (final String userId ) {
244
+ LOGGER . info(" Trying to find {} in cache" , userId);
245
+ if (cachingPolicy == CachingPolicy . THROUGH
246
+ || cachingPolicy == CachingPolicy . AROUND ) {
247
+ return cacheStore. readThrough(userId);
241
248
} else if (cachingPolicy == CachingPolicy . BEHIND ) {
242
- return CacheStore . readThroughWithWriteBackPolicy(userId);
249
+ return cacheStore . readThroughWithWriteBackPolicy(userId);
243
250
} else if (cachingPolicy == CachingPolicy . ASIDE ) {
244
251
return findAside(userId);
245
252
}
246
253
return null ;
247
254
}
248
255
249
- public static void save (UserAccount userAccount ) {
256
+ public void save (final UserAccount userAccount ) {
257
+ LOGGER . info(" Save record!" );
250
258
if (cachingPolicy == CachingPolicy . THROUGH ) {
251
- CacheStore . writeThrough(userAccount);
259
+ cacheStore . writeThrough(userAccount);
252
260
} else if (cachingPolicy == CachingPolicy . AROUND ) {
253
- CacheStore . writeAround(userAccount);
261
+ cacheStore . writeAround(userAccount);
254
262
} else if (cachingPolicy == CachingPolicy . BEHIND ) {
255
- CacheStore . writeBehind(userAccount);
263
+ cacheStore . writeBehind(userAccount);
256
264
} else if (cachingPolicy == CachingPolicy . ASIDE ) {
257
265
saveAside(userAccount);
258
266
}
@@ -272,24 +280,35 @@ Here is what we do in the main class of the application.
272
280
@Slf4j
273
281
public class App {
274
282
275
- public static void main (String [] args ) {
276
- AppManager . initDb(false );
277
- AppManager . initCacheCapacity(3 );
278
- var app = new App ();
283
+ public static void main (final String [] args ) {
284
+ boolean isDbMongo = isDbMongo(args);
285
+ if (isDbMongo){
286
+ LOGGER . info(" Using the Mongo database engine to run the application." );
287
+ } else {
288
+ LOGGER . info(" Using the 'in Memory' database to run the application." );
289
+ }
290
+ App app = new App (isDbMongo);
279
291
app. useReadAndWriteThroughStrategy();
292
+ String splitLine = " ==============================================" ;
293
+ LOGGER . info(splitLine);
280
294
app. useReadThroughAndWriteAroundStrategy();
295
+ LOGGER . info(splitLine);
281
296
app. useReadThroughAndWriteBehindStrategy();
297
+ LOGGER . info(splitLine);
282
298
app. useCacheAsideStategy();
299
+ LOGGER . info(splitLine);
283
300
}
284
301
285
302
public void useReadAndWriteThroughStrategy () {
286
303
LOGGER . info(" # CachingPolicy.THROUGH" );
287
- AppManager . initCachingPolicy(CachingPolicy . THROUGH );
304
+ appManager. initCachingPolicy(CachingPolicy . THROUGH );
305
+
288
306
var userAccount1 = new UserAccount (" 001" , " John" , " He is a boy." );
289
- AppManager . save(userAccount1);
290
- LOGGER . info(AppManager . printCacheContent());
291
- AppManager . find(" 001" );
292
- AppManager . find(" 001" );
307
+
308
+ appManager. save(userAccount1);
309
+ LOGGER . info(appManager. printCacheContent());
310
+ appManager. find(" 001" );
311
+ appManager. find(" 001" );
293
312
}
294
313
295
314
public void useReadThroughAndWriteAroundStrategy () { /* ... */ }
@@ -300,16 +319,6 @@ public class App {
300
319
}
301
320
```
302
321
303
- Finally, here is some of the console output from the program.
304
-
305
- ```
306
- 12:32:53.845 [main] INFO com.iluwatar.caching.App - # CachingPolicy.THROUGH
307
- 12:32:53.900 [main] INFO com.iluwatar.caching.App -
308
- --CACHE CONTENT--
309
- UserAccount(userId=001, userName=John, additionalInfo=He is a boy.)
310
- ----
311
- ```
312
-
313
322
## Class diagram
314
323
315
324
![ alt text] ( ./etc/caching.png " Caching ")
0 commit comments