Couple of days back we are facing a performance issue while object creation. It is taking too long to create a object. While investigation we found that hibernate is deleting all entries and re-inserting them back in the join table of a many to many relation.
After spending couple of hours with generated SQL analysis, we found that if we use list in the many side of ORM relation hibernate behaves strange. While adding or removing an item from the list, hibernate issues a delete statement to delete all elements, and then issue insert statements to insert everything back with additional entry of newly added object or except the one removed. This seems to be inefficient and odd. Why not just delete or add the one item? Then if we change the collection type to a Set, only one delete or add statement is issued by itself.
The scenario described above occurs when mapping a many to many or a one to many relationship with a association table. The association table stores two attributes, each of which is a foreign key to another table. In addition, the many side object is mapped with a List, but no index column is used.
If table does not have an index column, and List is used as the property type, this property is mapped as a Hibernate bag. A bag does not retain its order when it is retrieved from the database, but it can be optionally sorted or ordered.

Hibernate's internals

If we are using List as a mapped attribute in hibernate without indexed column, hibernates treats it as a Bag. Since Hibernate handles List as a Bag (Unordered collection with non unique values. The best feature of a bag is that you can get the number of occurrences of an object through the API With a list, there is no way to do the same without iterating through the whole list.) as soon as we delete and add a element in this collection. Hibernate issues a SQL to delete all the elements first from join table which are no supposed to be deleted and then it re-insert all of them back from the Bag.

Final Thought

When using a list in hibernate an indexed column is necessary, if we want efficient manipulation of adding or deleting items. With an indexed column, when we code a remove(index), hibernate can relate that index to the column in the db or or add(element) will generate only one insert statement even if there are duplicates, it can distinguish and delete one row or add one row based on operation.
Expensive but better yet, if duplicates are not needed in the application, Set can be used. Set does not require index column and hibernate can easily distinguish one row because it know a set does not have duplicates.