方案如下,
我有3个名为Parent的对象(我简化名称),父母的子女和孩子的
父母的孩子是父母的集合,孩子的孩子是孩子的集合.
映射如下(相关部分)
亲
<set name="parentset"
table="pc-table"
lazy="false"
fetch="subselect"
cascade="all-delete-orphan"
inverse="true">
<key column=FK_ID_PC" on-delete="cascade"/>
<one-to-many class="parentchild,parentchild-ns"/>
</set>
Run Code Online (Sandbox Code Playgroud)
父母的孩子
<set name="childset"
table="cc-table"
lazy="false"
fetch="subselect"
cascade="all-delete-orphan"
inverse="true">
<key column="FK_ID_CC" on-delete="cascade"/>
<one-to-many class="childschild,childschild-ns"/>
</set>
Run Code Online (Sandbox Code Playgroud)
我想要实现的是,当我删除父级时,会有一个级联删除一直到孩子的孩子.但目前发生的是这个.
(这纯粹用于映射测试目的)获取父实体(工作正常)
IQuery query = session.CreateQuery("from Parent where ID =" + ID);
IParent doc = query.UniqueResult<Parent>();
Run Code Online (Sandbox Code Playgroud)
现在删除部分
session.Delete(doc);
transaction.Commit();
Run Code Online (Sandbox Code Playgroud)
在使用级联和反向解决了"无法插入空值"错误后,我希望现在可以使用此代码删除所有内容,但只删除父项.
我错过了可能错过的映射中的某些内容吗?任何正确方向的提示都非常受欢迎!
迭戈,谢谢你的回答.(和解释)
我去除了on-delete="cascade",这是因为我喜欢在代码中尽可能多地控制而不是在数据库中.
下面发布的代码是(工作)结果.
亲
<set name="parentset"
table="pc-table"
cascade="all-delete-orphan"
inverse="true"
batch-size="5">
<key column=FK_ID_PC"/>
<one-to-many class="parentchild,parentchild-ns"/>
</set>
Run Code Online (Sandbox Code Playgroud)
父母的孩子
<set name="childset"
table="cc-table"
cascade="all-delete-orphan"
batch-size="5"
inverse="true"> …Run Code Online (Sandbox Code Playgroud) 我想删除两个表中的行,这两个表通过一组可延迟的约束相互依赖.为了简化这篇文章,我模拟了一个简单的数据库模式.
我希望在SQL事务/数据库补丁中删除某些表中的条目'delete_from_me'.问题是,我想在松开链接本身之前根据第二个表'constraining_table'中的选择进行删除.
这是两个表的描述:
tab-quarantine=> \d delete_from_me
Table "public.delete_from_me"
Column | Type | Modifiers
-----------+-------------------+-----------
id | character varying | not null
extension | character varying | not null
Indexes:
"delete_from_me_pkey" PRIMARY KEY, btree (id)
tab-quarantine=> \d constraining_table
Table "public.constraining_table"
Column | Type | Modifiers
--------+-------------------+-----------
image | character varying | not null
type | character varying | not null
Foreign-key constraints:
"constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id)
ON UPDATE CASCADE
ON DELETE RESTRICT DEFERRABLE
Run Code Online (Sandbox Code Playgroud)
这是我刚刚在那里抨击的一些示例数据:
tab-quarantine=> SELECT * FROM delete_from_me; …Run Code Online (Sandbox Code Playgroud) 在我的MS SQL Server 2008数据库中,我有自引用的表,其中包含层次结构的类别(ID和ParentID).表具有自我外键约束和"而不是删除"触发器以执行删除其子节点的完整节点.
管理数据我正在使用实体框架(4.3),从具有自跟踪实体的DB生成的模型和ObjectContext(由VS模板生成).EDM还在"类别"实体上具有自引用关联.
尝试删除任何至少有一个子行的父行时,我遇到了问题.
我打电话后:
Entity.MarkAsDeleted();
Context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
在SQL Server Profiler中,我看到EF首先生成一个更新语句,将子行的ParentID设置为null,然后删除父行!当然,DB中的级联规则不起作用,子节点仍然保留在EF上下文和DB中.
我试图将关联规则"On delete"设置为"Cascade"和"None",但它没有意义......
如何在EF自引用表中执行级联删除,或者至少如何防止EF更新子行的父ID?
我在互联网上查了很多帖子,但都没有解决我的问题.如果有人能提供帮助,真的很感激!我有OneToMany父子关系.当其中一个子组合键是父组件(Level1)的外键时,Hibernate不会级联插入子级(Level2).我指定了cascade ="all",无论逆是true还是false,结果都是一样的.没有例外,它只是不插入.下面的打印显示Level1已成功插入,但Level2仅被选中,没有插入.
Hibernate:插入sst.level_1(STATUS,NAME)值(?,?)Hibernate:从sst.level_2 level2x_中选择level2x_.LEVEL_1_ID,level2x_.TIMESEGMENT,level2x_.CATEGORY为CATEGORY4_,其中level2x_.LEVEL_1_ID =?和level2x_.TIMESEGMENT =?
API是Hibernate 4.1.6/Spring 3.1.2.
这是mySQL的表定义:
Hibernate: insert into sst.level_1 (STATUS, NAME) values (?, ?)
Hibernate: select level2x_.LEVEL_1_ID, level2x_.TIMESEGMENT, level2x_.CATEGORY as CATEGORY4_ from sst.level_2 level2x_ where level2x_.LEVEL_1_ID=? and level2x_.TIMESEGMENT=?
Run Code Online (Sandbox Code Playgroud)
这是测试代码.
CREATE TABLE level_1
(
ID int NOT NULL PRIMARY KEY AUTO_INCREMENT,
STATUS int,
NAME varchar(255)
);
CREATE TABLE level_2
(
LEVEL_1_ID int,
TIMESEGMENT int,
CATEGORY varchar(2),
PRIMARY KEY (LEVEL_1_ID, TIMESEGMENT),
FOREIGN KEY (LEVEL_1_ID) REFERENCES level_1(ID) ON DELETE CASCADE
);
Run Code Online (Sandbox Code Playgroud)
Level1的映射:
public class Test {
public static …Run Code Online (Sandbox Code Playgroud) 在Tomcat Web应用程序上运行的Maven-Spring-Hibernate-MySql中,我正在使用hibernate ddl来生成MySQL5InnoDBDialect的数据库模式.
除了外键的级联选项之外,生成的模式很好.例如,我有这样的结构:
保存用户详细信息对象的用户对象,两者共享相同的密钥:
@Entity
@Table(name = "Users")
public class User implements Serializable {
private static final long serialVersionUID = -359364426541408141L;
/*--- Members ---*/
/**
* The unique generated ID of the entity.
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "User_Id")
protected long id;
@Getter
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "user", optional = true)
protected UserDetails userDetails;
...
}
Run Code Online (Sandbox Code Playgroud)
而用户详细信息:
@Entity
@Table(name = "UserDetails")
public class UserDetails implements Serializable {
private static final long serialVersionUID = …Run Code Online (Sandbox Code Playgroud) 我用FOREIGN KEY创建了表,不能插入任何东西.
CREATE TABLE menus (
id int(10),
parent_id int(10),
label varchar(255),
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES menus (id)
);
Run Code Online (Sandbox Code Playgroud)
删除父项时,我需要FOREIGN KEY自动删除子项.此表已成功创建,但我无法插入任何内容.
INSERT INTO `menus` (`parent_id`, `label`)
VALUES ('1', 'label1');
Run Code Online (Sandbox Code Playgroud)
要么
INSERT INTO `menus` (`label`)
VALUES ( 'label1');
#1452 - Cannot add or update a child row: a foreign key constraint fails
Run Code Online (Sandbox Code Playgroud)
我真的不想在PHP代码中寻找任何孩子所以我需要以某种方式创建具有3列的简单表并自动删除所有孩子和他们的孩子.
我有一对多关系:ProductCategory可以包含许多产品.这是代码:
@Entity
public class Product implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private String id;
@Column(name="ProductName")
private String name;
private BigDecimal price;
private String description;
@ManyToOne
@JoinColumn(name="UserId")
private User user;
@ManyToOne
@JoinColumn(name="Category")
private ProductCategory category;
private static final long serialVersionUID = 1L;
public Product() {
super();
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() …Run Code Online (Sandbox Code Playgroud) 我对Hibernate很陌生,一直试图确定它将为你做什么以及它需要你做什么.
一个重要的是处理具有数据库中尚不存在的依赖项的对象.例如,我有一个Project对象,其中包含一个Manufacturer字段,该字段接受Manufacturer对象作为其值.在数据库中,我有一个带有mfr_id列的产品表,该列是对manufacturer表的引用(一种相当典型的单向一对多关系).
如果分配给产品对象的制造商与已经存在于数据库中的制造商有关,则没有问题.但是,当我尝试保存或更新引用尚未持久化的制造商的对象时,操作将失败并出现异常.
线程"Application"中的异常org.hibernate.TransientObjectException:对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例
我当然可以手动检查产品制造商的状态,看看它的ID字段是否为空,如果是,则将其保存,但这似乎是一个麻烦的解决方案.如果尚未保留相关的依赖项,Hibernate是否支持自动持久的依赖项?如果是这样,我该如何启用该行为?我正在使用与Netbeans捆绑的Hibernate版本(我相信3.5)和用于指定映射行为的内联注释.以下是我的产品和制造商类,减少了处理依赖关系的部分.(产品扩展为Sellable,映射到可销售的表,使用JOINED作为继承策略.该表包含标识产品的主键)
@Entity
@Table (
name="products",
schema="sellable"
)
public abstract class Product extends Sellable {
private Manufacturer manufacturer;
@ManyToOne (fetch = FetchType.EAGER)
@JoinColumn (name = "mfr_id")
public Manufacturer getManufacturer () {
return this.manufacturer;
}
/**
*
* @param manufacturer
*/
public Product setManufacturer (Manufacturer manufacturer) {
this.manufacturer = manufacturer;
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
依赖制造商
@Entity
@Table (
name="manufacturers",
schema="sellable",
uniqueConstraints = @UniqueConstraint(columnNames="mfr_name")
)
public class Manufacturer implements Serializable {
private Integer mfrId = null;
private …Run Code Online (Sandbox Code Playgroud) 我有这样的场景:我有这些课程:
public class A
{
public int Id {get;set;}
public virtual ICollection<B> bCollection {get; set; }
}
public class B
{
public int Id {get;set;}
}
public class C1 : BaseClass1
{
public int Id{get;set;}
public virtual B B{get;set;}
}
public class C2 : BaseClass2
{
public int Id {get;set;}
public virtual B B {get;set;}
}
...
public class C100 : BaseClass100
{
public int Id {get;set;}
public virtual B B {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
A类具有B类的集合,Ci类具有一个B类和不同的基类.当在A类集合中只有B不能引用它时,我可以删除A类并且所有B集合也被删除(级联删除).但是当在A类集合中有B类时Ci引用它我不能删除A类实例...
我的预期行为:
A类将被删除,A类的所有B集合都被删除,如果Ci引用了集合中的某些B,它将在删除结束时为空.(类Ci的内容不会被删除!),我 …
我和Many-to-Many班级之间有关系.因为我想获得有关辅助表的其他信息,所以我必须创建一个帮助类,如下所述:使用JPA和Hibernate时,使用额外列映射多对多关联的最佳方法FooBarFooBar
我创建了一个Foo,并创建了一些条形图(保存到DB).当我然后使用其中一个条添加到foo
foo.addBar(bar); // adds it bidirectionally
barRepository.save(bar); // JpaRepository
Run Code Online (Sandbox Code Playgroud)
然后创建FooBar的DB条目 - 正如预期的那样.
但是,当我想再次从foo中删除相同的栏时,使用
foo.removeBar(bar); // removes it bidirectionally
barRepository.save(bar); // JpaRepository
Run Code Online (Sandbox Code Playgroud)
然后,不会从数据库中删除先前创建的FooBar条目.通过调试,我看到foo.removeBar(bar);确实删除了双向.没有异常被抛出.
难道我做错了什么?我很确定它与Cascading选项有关,因为我只保存吧.
我尝试过的:
添加orphanRemoval = true@OneToMany - 注释,但没有用.我认为这是正确的,因为我不删除 Foo和Bar,只删除他们的关系.
从@OneToMany注释中排除CascadeType.REMOVE,但与orphanRemoval相同我认为这不适用于这种情况.
编辑: 我怀疑在我的代码或模型中必须有一些东西与我的orphanRemoval混淆,因为现在已有2个答案说它有效(带orphanRemoval=true).
最初的问题已得到解答,但如果有人知道什么可能导致我的孤儿无法工作,我会非常感谢您的意见.谢谢
代码:Foo,Bar,FooBar
public class Foo {
private Collection<FooBar> fooBars = new HashSet<>();
// constructor omitted for brevity
@OneToMany(cascade = CascadeType.ALL, mappedBy = "foo", fetch = FetchType.EAGER)
public Collection<FooBar> getFooBars() …Run Code Online (Sandbox Code Playgroud) cascade ×10
hibernate ×4
c# ×2
foreign-keys ×2
java ×2
jpa ×2
mysql ×2
hbm2ddl ×1
nhibernate ×1
one-to-many ×1
orm ×1
parent-child ×1
persist ×1
postgresql ×1
sql ×1
transactions ×1