Java Hibernate 无法删除带有外键的实体。外键设置为空
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40353605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HIbernate Can't delete Entity with foreign key. Foreign key gets set to null
提问by Freddie
This question has been asked in many forms here but none of the solutions seem to work for me. I'm trying to delete the parent entity and I want all of the child entities to also be deleted.
这里已经以多种形式提出了这个问题,但似乎没有一个解决方案对我有用。我正在尝试删除父实体,并且我希望也删除所有子实体。
My entities:
我的实体:
@Entity
@Table(name = "item", catalog = "myshchema")
public class Item implements java.io.Serializable {
@JoinColumn(name = "item_id", insertable = false, updatable = false, nullable = false)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<ItemCategory> categories;
/* Getters and Setters and other fields*/
}
Table for Item:
项目表:
CREATE TABLE `item` (
`item_id` int(11) NOT NULL AUTO_INCREMENT,
`store_id` int(11) NOT NULL,
PRIMARY KEY (`item_id`),
UNIQUE KEY `item_id_UNIQUE` (`item_id`),
KEY `FK_ITEM_STORE_ID_idx` (`store_id`),
CONSTRAINT `FK_ITEM_STORE_ID` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8;
And my other entity
还有我的另一个实体
@Entity
@Table(name = "item_category", catalog = "myschema")
@IdClass(ItemCategoryIndex.class)
public class ItemCategory implements java.io.Serializable {
@Id
@Column(name = "category_id", unique = true, nullable = false, insertable = false, updatable = false)
private Integer categoryId;
@Id
private Store store;
@Id
private Item item;
@Id
private String categoryName;
/* Getters and Setters */
}
Table for ItemCategory:
ItemCategory 表:
CREATE TABLE `item_category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`store_id` int(11) NOT NULL,
`item_id` int(11) NOT NULL,
`category_name` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`),
UNIQUE KEY `category_id_UNIQUE` (`category_id`),
UNIQUE KEY `IDX_UNIQUE_STORE_CATEGORY` (`store_id`,`item_id`,`category_name`) USING BTREE,
KEY `FK_CATEGORY_STORE_ID_idx` (`store_id`),
KEY `FK_ITEM_CATEGORY_ID_idx` (`item_id`),
CONSTRAINT `FK_CATEGORY_STORE_ID` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_ITEM_CATEGORY_ID` FOREIGN KEY (`item_id`) REFERENCES `item` (`item_id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=162 DEFAULT CHARSET=utf8;
I try to delete the item like this:
我尝试删除这样的项目:
Item item = entityManager.find(Item.class, idList.get(i));
entityManager.remove(item);
My logs show that Hibernate is trying to set the primary key for ItemCategory to null:
我的日志显示 Hibernate 正在尝试将 ItemCategory 的主键设置为 null:
Hibernate: update myschema.item_category set item_id=null where item_id=?
ERROR o.h.e.jdbc.spi.SqlExceptionHelper.logExceptions 146 - Column 'item_id' cannot be null
I even tried looping through the child records and deleting them manually, but Hibernate still issues this update to null query. What am I doing wrong?
我什至尝试遍历子记录并手动删除它们,但 Hibernate 仍然将此更新发布到空查询。我究竟做错了什么?
采纳答案by Minjun Yu
I have to break your problem down to two parts
我必须把你的问题分成两部分
First - let's talk about your database schema design.
首先 - 让我们谈谈您的数据库架构设计。
According to your schema, item
and item_category
has a one-to-manyrelationship meaning an item can have/be-assigned-todifferent categories but different items cannot have/be-assigned-tothe same category.
根据您的架构,item
并且item_category
具有一对多关系,这意味着一个项目可以具有/被分配到不同的类别,但不同的项目不能具有/被分配到同一类别。
That is totally fine if it is indeed your business requirement, I mention it because it does not make sense to me and this circumstance rarely happens.
这是完全正常,如果它确实是你的业务需求,我提到它,因为它没有任何意义,我和这种情况很少发生。
If what you want is that a category can have multiple items and vice versa, item
and item_category
must be a many-to-manyrelationship. There should be a join tableadditionally.
如果您想要的是一个类别可以有多个项目,反之亦然,item
并且item_category
必须是多对多关系。另外应该有一个连接表。
Second - let's say the schema don't change
第二 - 假设架构没有改变
ItemCategory
is the owner of the relationship because it has a foreign key item_id
refering to item
table. So the ItemCategoy should look roughlylike this:
ItemCategory
是关系的所有者,因为它有一个item_id
引用item
表的外键。所以 ItemCategoy 应该大致如下所示:
@Entity
@Table(name = "item_category")
public class ItemCategory {
@Id
private Integer categoryId;
private Store store;
@ManyToOne
@JoinColumn(name="item_id", /*cascade = ...*/)
private Item item;
private String categoryName;
/* Getters and Setters */
}
Your Item
entity will be roughlylike this:
您的Item
实体大致如下:
@Entity
@Table(name = "item", catalog = "myshchema")
public class Item implements java.io.Serializable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, mappedBy="item")
private Set<ItemCategory> categories; //`mappedBy`used here because this entity is not the owner of the relationship according to what mentioned above
/* Getters and Setters and other fields*/
}
To remove all the child entities(ItemCategory
) from Item
, simply
要从 中删除所有子实体(ItemCategory
)Item
,只需
em.remove(item);
em.remove(item);
The orphanRemoval
is true
, deleting the parent, the children will be deleted as well.
该orphanRemoval
是true
,删除父,孩子们将被删除。
回答by Khuzi
In Hibernate, you need to decide who is owning the relationship. If you have the parent side (ItemCategory) owning the relationship, you will find insertion/deletion of Item+ ItemCategory will involve update of item_id in ItemCategory table (which is what I observed from your exception). In most case it is not preferable. We usually let the children own the relationship. This is done by using mappedBy
在 Hibernate 中,您需要决定谁拥有该关系。如果您拥有拥有该关系的父端(ItemCategory),您会发现 Item+ ItemCategory 的插入/删除将涉及 ItemCategory 表中 item_id 的更新(这是我从您的异常中观察到的)。在大多数情况下,这不是可取的。我们通常让孩子拥有这种关系。这是通过使用mappedBy来完成的
(pseudo-code)
(伪代码)
class Item {
//...
@OneToMany(mappedBy = "item", cascade=ALL, orphanRemoval=true)
private Set<ItemCategory> categories;
}
class ItemCategory {
//...
@ManyToOne
@JoinColumn(name="item_id")
Item item;
}
The trick here is mappedBy
这里的技巧是mappedBy