Reputation: 5648
The entities (using Set):
@Entity
class Product(
@Id
@GeneratedValue
val int: Int = 0,
val name : String,
@ManyToMany(cascade = [(CascadeType.PERSIST), (CascadeType.MERGE)])
val stores: MutableSet<Store> = mutableSetOf()
)
@Entity
class Store(
@Id
@GeneratedValue
val int: Int = 0,
val name : String = ""
)
...
val p = Product(name = "product")
em.persist(p)
val store = Store(name = "store");
p.stores += store
em.persist(store)
for (i in 1..5) {
val s = Store(name = i.toString())
p.stores += s
em.persist(s)
}
em.flush()
p.stores.remove(store)
em.flush()
The result:
Hibernate: insert into product (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: delete from product_stores where product_int=? and stores_int=?
But with this entity (using List):
@Entity
class Product(
@Id
@GeneratedValue
val int: Int = 0,
val name : String,
@ManyToMany(cascade = [(CascadeType.PERSIST), (CascadeType.MERGE)])
val stores: MutableList<Store> = mutableListOf()
)
The result:
Hibernate: insert into product (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into store (name, int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: delete from product_stores where product_int=?
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
Hibernate: insert into product_stores (product_int, stores_int) values (?, ?)
From Hibernate User Guide: http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#associations-many-to-many
When an entity is removed from the @ManyToMany collection, Hibernate simply deletes the joining record in the link table. Unfortunately, this operation requires removing all entries associated with a given parent and recreating the ones that are listed in the current running persistent context.
But I don't know the reason behind it, why can't we just do the same as in the Set case
Upvotes: 1
Views: 423
Reputation: 4542
The @ManyToMany annotation with a List is telling hibernate to expect a joinTable without index
List that don't use index column in one-to-many relation are treated implicitly as bags and this lead to
https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/performance-collections.html
Bags are the worst case. Since a bag permits duplicate element values and has no index column, no primary key may be defined. Hibernate has no way of distinguishing between duplicate rows. Hibernate resolves this problem by completely removing (in a single DELETE) and recreating the collection whenever it changes.
Upvotes: 1
Reputation: 16151
Here you got the explaination: http://assarconsulting.blogspot.com/2009/08/why-hibernate-does-delete-all-then-re.html
Upvotes: 1