1
@Entity
class Employee{
@Id
String name;
int age;
String gender;
}

I'm using the above entity object as key in Hashmap:

Employee e1 = new Employee("abc",23,"M")

Now if I create a new entity with same id and persist it:

@Autowired
EmployeeDao employeeDao;

e1.findByName("abc");

Map<Employee, Boolean> map = new HashMap<>();
map.put(e1, true);

Employee e2 = new Employee("abc",45,"F");
employeeDao.save(e2)

for(Employee ex:map.keySet()){
     map.get(ex);   //Returns null
}

I figure out my HashKey(e1) is also changed(to e2). Now since Hashmap uses "Entry" objects where Key would be an Employee Entity object(Which got changed), is it that JPA entities references objects stored in Entity manager? Is this why the Key changed?

Why did the Key(e1) change automatically?

user7171758
  • 292
  • 3
  • 10
  • Are you doing it inside of transaction? – Ihar Sadounikau Mar 25 '19 at 19:51
  • 2
    Entity Manager keeps the entity `cashed` until you detach it. And load entity by the `id` from the cache. So probably you are changing linked entity. Try to detach the entity after save – Ihar Sadounikau Mar 25 '19 at 19:52
  • What key exactly are you talking about? – Jens Schauder Mar 26 '19 at 06:33
  • @JensSchauder The key in HashMap obv – user7171758 Mar 26 '19 at 10:06
  • @IharSadounikau as soon as I do save, the HashMap key is modified. Seems like the Entry object in the Hashmap holds reference to the saved entity somehow. – user7171758 Mar 26 '19 at 10:09
  • There is nothing obvious about this question. If you create two instances `e1` and `e2` and save `e2`, `e1` will not change. You are doing either something different or your conclusion that `e1` is changed is faulty. Please show us the source code including: creation of both instances, adding the instance to a HashMap saving the other instance and determining that the instance used in the HashMap changed. – Jens Schauder Mar 26 '19 at 11:14
  • @JensSchauder Added more code for your reference. My question is why am I getting null? This is because the key in hashmap entry is getting changed. Now why did the key get changed? I hope that helps. – user7171758 Mar 26 '19 at 15:42

1 Answers1

1

Spring Data JPAs save does a merge under the hood. The merge looks for an entity with the same class and id in the 1st level cache. If it finds one it copies the state from the argument over to the instance in the cache. Dirty checking then ensures it gets flushed to the database. merge and in turn save also return the entity that was found in the 1st level cache.

Since you loaded e1 from the database in the same transaction it is in the 1st level cache and gets modified.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348