为什么Hibernate在使用List时需要在单向ManyToMany中重新创建其他条目

时间:2017-11-30 10:56:54

标签: java hibernate jpa spring-data-jpa

实体(使用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()

结果:

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=?

但是使用这个实体(使用List):

@Entity
class Product(
    @Id
    @GeneratedValue
    val int: Int = 0,
    val name : String,
    @ManyToMany(cascade = [(CascadeType.PERSIST), (CascadeType.MERGE)])
    val stores:  MutableList<Store> = mutableListOf()
)

结果:

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 (?, ?)

来自Hibernate用户指南: http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#associations-many-to-many

  

当从@ManyToMany集合中删除实体时,Hibernate只删除链接表中的连接记录。不幸的是,此操作需要删除与给定父级关联的所有条目,并重新创建当前运行的持久化上下文中列出的条目。

但我不知道其背后的原因,为什么我们不能像Set案例一样做

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

带有List的@ManyToMany注释告诉hibernate期望没有索引的joinTable

在一对多关系中不使用索引列的列表被隐式处理为包,这导致

https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/performance-collections.html

  袋子是最糟糕的情况。由于包允许重复的元素值并且没有索引列,因此不能定义主键。 Hibernate无法区分重复的行。 Hibernate通过完全删除(在单个DELETE中)并在每次更改时重新创建集合来解决此问题。