2

I have two kinds of entities: Event and Schedule. I am trying to modify them avoiding transactions as much as possible not to lock the database for unnecessary time.

So instead of:

@Transactional
public void modify() {
    Event event = em.find(...);
    //... something that might take a long time
    event.addSchedule(schedule);
    em.flush();
}

I am trying rather to:

public void modify() {
    Event event = em.find(...);
    //... something that might take a long time
    event.addSchedule(schedule);
    repository.merge(event);
}

...
@Transactional
public void merge(Event event) {
    em.merge(event);
    em.flush();
}

The problem is that like this I am getting exceptions: An entity copy [Event#XXX] was already assigned to a different entity [Event#XXX]. I do not copy the entity, nor do anything unexpected with it.

Also, it is said that it is necessary to have properly implemented equals() and hashCode() methods. I have them, but as I've studied the stacktrace, it seems that the entities are compared not by equals, nor hashCode, they are compared with == as shown here: http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-core/4.1.3.Final/org/hibernate/event/internal/EventCache.java#62

They use IdentityHashMap, which specifically use ==.

So where can I look for problem? I've tried hibernate from 4.1.7 to current 4.3.4 and I am using hibernate.enable_lazy_load_no_trans to load entities without explicitly having session.

Vojtěch
  • 11,312
  • 31
  • 103
  • 173

2 Answers2

2

I have managed to solve this issue by changing the Cascade type from All to Persist on all the relationships of the issued Class.

Márcio
  • 21
  • 4
0

It seems there is a problem in the implementation of the equals/hashcode of Event:

An entity copy [Event#1000] was already assigned to a different entity [Event#1001]

An entity copy is a Java object in-memory which corresponds to an entity in the database. There could be several copies in-memory pointing to the same DB record.

The message says that there are two Event objects with different database identifiers (the @Id column),so from a point of view of database identity (obj1.getId().equals(obj2.getId())) are not the same.

But from a point of Java equivalence (obj1.equals(obj2)) they are considered the same. But two objects cannot be different in the database and the same in-memory, which causes the error.

The solution is to fix the equals/hashcode implementation, see this answer for further details on the problem and this page for details on implementing equals/hascode for Hibernate entities.

Community
  • 1
  • 1
Angular University
  • 42,341
  • 15
  • 74
  • 81