1
votes

Server: JBoss Application Server 7.1.4

JPA implementation: Hibernate

External standalone Java application receives detached entities from EJBs via RMI. How to efficiently cache these objects in standalone Java application and preserve as much as possible on save/update operations?

Right now entities are cached in Map<Long, Object> cache. But because entities use common fields, we must clear whole cache on each save operation or we can get StaleObjectsException.

Lets look at the following example:

class Company {
  Long id;
  String name;
}

class User {
  Long id;
  String name;
  Company company;
}
// + getters & setters

Lets say Person 1 and Person 2 both have the same Company. External Java app requests these two objects and receives two Persons and one instance of Company. Both Persons reference the same Company. All good.

// put to cache
cache.put(person1.getId(), person1);
cache.put(person2.getId(), person2);
// change company name of person1
person1.getCompany().setName("newCompany");

// now send person1 to server EJB to be saved to database.

session.merge in EJB updates detached entity and returns completely new java object instance. We save new instance to cache: cache.put(returnedPerson1.getId(), returnedPerson1);

Problem: person2 in cache still have the old Company.

Simple solution:

cache.clear(); // on each save / update operation.

Can it be optimized to remove only changed objects or even update changed fields? Are there any libraries that solve this problem?

Edit: changed Address to Company to be more clear

1
Slightly off-topic, but if person1 updates their address, are you sure you want to change person2's address too? Would you not assume person1's just moved out? I'd think you should create a new Address object rather than updating the old one?hugh
Good point, but this was just an example. In reality I have 200 Entities with complex relationships.kikovi

1 Answers

0
votes

If it possible you can use second Map (cache) for Addresses and to keep separately. When you get new instance of a Person you can read Address and check it in AddressCache. It is more cheaper than clearing cache every time or checking all Persons in cache. Also you get rid of duplicates Addresses