| Dear Hibernate Developers I have already talked to Vlad about this problem Hibernate triggers unnecessary update statements for all previous elements of a map if a new element is being added to this map. The problem only occures for maps with bidirectional bindings and HBM XML mappings. I was unable to reproduce the issue with annotation based mappings or unidirectional bindings. I built a simple demo projects containing two classes for illustration purposes. A person object referencing one or more task objects. Person.hbm.xml
<hibernate-mapping>
<class name="persistency.test.Person" table="person" lazy="true">
<id name="dbKey" type="long" access="field" column="dbkey">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" length="20" access="field" />
<map name="tasks" cascade="all-delete-orphan" inverse="true" access="field">
<key column="person_dbkey" />
<map-key type="string" column="name" />
<one-to-many class="persistency.test.Task" />
</map>
</class>
</hibernate-mapping>
Person.java
public class Person {
private String name;
private long dbKey;
private Map<String, Task> tasks = new HashMap<>();
public void addTask(Task task) {
task.setOwner(this);
this.tasks.put(task.getName(), task);
}
}
Task.hbm.xml
<hibernate-mapping>
<class name="persistency.test.Task" table="task" lazy="true">
<id name="dbKey" type="long" access="field" column="dbkey">
<generator class="native" />
</id>
<property name="name" type="java.lang.String" length="20" access="field" />
<property name="description" type="java.lang.String" length="100" access="field" />
<many-to-one name="owner" column="person_dbkey" class="persistency.test.Person" access="field" />
</class>
</hibernate-mapping>
Task.java
public class Task {
private String name;
private long dbKey;
private Person owner;
private String description;
public Task(String name, String description) {
this.name = name;
this.description = description;
}
public Task() { }
public String getName() {
return name;
}
public void setOwner(Person owner) {
this.owner = owner;
}
}
The table Task already contains three tasks:
If a new task is being added to the map containg already three tasks:
session.beginTransaction();
Person person = session.load(Person.class, 139000l);
person.addTask(new Task("Cleaning", "Floor, Roof"));
session.getTransaction().commit();
Hibernate then executes the following SQL statements:
select person0_.dbkey as dbkey1_0_0_, person0_.name as name2_0_0_ from XHM_2.person person0_ where person0_.dbkey=?
select tasks0_.person_dbkey as person_dbkey4_1_0_, tasks0_.dbkey as dbkey1_1_0_, tasks0_.name as name2_0_, tasks0_.dbkey as dbkey1_1_1_, tasks0_.name as name2_1_1_, tasks0_.description as description3_1_1_, tasks0_.person_dbkey as person_dbkey4_1_1_ from XHM_2.task tasks0_ where tasks0_.person_dbkey=?
select XHM_2.hibernate_sequence.nextval from dual
insert into XHM_2.task (name, description, person_dbkey, dbkey) values ('Cleaning', 'Floor, Roof', '139000', '224000')
update XHM_2.task set name='Eating' where dbkey='221000'
update XHM_2.task set name='Cooking' where dbkey='218000'
update XHM_2.task set name='Reading' where dbkey='225000'
update XHM_2.task set name='Cleaning' where dbkey='224000'
Hibernate triggers for update statements as shown above. I think there is no reason to update the previous three elements and the newly added element either. |