我想知道我应该怎么做,因为我读了很多文章试图理解这一点,包括很多问题。我读过的书中,没有一本是非常中肯的。
我想知道当使用级联规则以及应用程序定义数据库时会发生什么,因为这将定义我应该采用以下方法还是其他方法。
create table foo(
id int unsigned not null auto_increment,
primary key(id)
);
create table bar(
id int unsigned not null auto_increment,
foo_id int unsigned not null,
primary key(id),
foreign key(foo_id) references foo(id) on delete cascade on update cascade
)
@Entity
@Table(name = "foo")
public class Foo {
private int id;
private List<Bar> bars;
@Id
@GeneratedValue
@Column(name = "id")
public int getId() {
return id;
}
@OneToMany(mappedBy = "foo", cascade = {CascadeType.ALL})
public List<Bar> getBars() {
return bars;
}
public void setId() {
this.id = id;
}
public void setBars(List<Bar> bars) {
this.bars = bars;
}
}
@Entity
@Table(name = "bar")
public class Bar {
private int id;
private Foo foo;
@Id
@GeneratedValue
@Column(name = "id")
public int getId() {
return id;
}
@ManyToOne
@JoinColumn(name = "foo_id", nullable = false)
public getFoo() {
return foo;
}
public void setId(int id) {
this.id = id;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
}
如果我现在对Foo
对象调用删除操作(无论是通过EntityManagerFactory
还是SessionFactory
),会发生以下哪种情况?
>
hibernate操作将删除已加载到会话缓存中的所有相应条记录(可能是也可能不是实际数据库中存在的所有条记录),然后删除Foo记录(数据库级联规则将删除任何剩余的条记录)。
hibernate操作将首先尝试删除Foo记录,如果数据库出现故障,则执行上述步骤之一。
发生了我没有考虑过的其他事情,如果是什么?
考虑到以下dilemna假设,最佳方法是什么?
如果1为真,那么它会建议:
A) 仅在数据库中定义级联规则。确保从应用程序中的对象中删除条形图,这样它们就不会与数据库分离(因为数据库将删除它们的记录),然后调用delete(删除)。
或
B) 仅在应用程序中定义级联规则,因为它将彻底管理数据库完整性。
不
c)在两者中定义级联规则,因为每个都实现了所需的结果,使另一个成为处理的浪费。
如果2为真,则建议:
在数据库和应用程序中定义级联规则,以便Hibernate可以管理其实体,并且数据库可以在之后进行清理,因为应用程序不能保证删除所有的条形记录。
如果3为真,则表明:
在数据库和应用程序中定义级联规则,因为Hibernate似乎支持已经在数据库级别定义的级联规则。
如果4为真,那么它会建议:
这个问题更重要,因为我错过了一些基本的东西!
编辑:添加我读过的文章...
数据库、应用程序或两者的视图冲突:
SO-应该-我-让-jpa-或-数据库-级联删除
数据库或应用程序的冲突视图:
SO-级联使用jpa或数据库内部删除更新
本文阐明了JPA提供程序实际做什么(尽管应该注意的是,他们使用OpenJPA提供程序作为操作证明):
jpa教程
它指出:
移除和持久化操作的级联也适用于那些尚未加载的实体。它甚至将它们传递给其他实体,可能会遍历整个对象图。
它接着指出:
刷新、合并和分离的级联仅通过已加载的实体。
这意味着拟议的流程2不正确。
你为什么还要考虑呢?最好坚持使用hibernate级联选项。在另一侧,如果两侧都有cascade,则会运行cascade delete两次。一次来自hibernate,一次由数据库管理。
示例189。来自hibernate 5.2文档。生成以下sql。
@Entity(name = "Person")
public static class Person {
@ManyToMany(cascade = {CascadeType.DELETE})
private List<Address> addresses = new ArrayList<>();
...
}
Person person1 = entityManager.find( Person.class, personId );
entityManager.remove( person1 );
DELETE FROM Person_Address
WHERE Person_id = 1
DELETE FROM Person
WHERE id = 1
现在您可以看到hibernate在删除父实体之前删除子实体。数据库级联将在sql人删除上运行,但当以前删除子实体时,它现在没有什么要删除的。
如果在数据库中声明cascade并Hibernate,则数据库将始终首先删除(如果它支持),并且hibernate调用不会真正删除任何内容,而是运行。然而,由于您使用的是hibernate,它的主要优点是允许轻松过渡到可能不支持数据库端级联功能的新数据库。因此,即使您的数据库支持cascade,并且hiberate下划线的jdbc语句当前没有做任何事情(它们将来可能会做一些事情),您也希望将它们留在那里
在数据库中,将有一个列,并对的列具有外键约束。 对于在删除时级联的外键约束,可能执行的一些操作包括、和。这给出了以下方案组合。 a:在JPA中对父级进行级联删除调用,在删除父行时删除数据库中的子级。 b:在JPA中级联删除,在父删除时将子表中的外键列设置为null。在这种情况下,@joincolumn中的和中的可能需要为true/false。 C:在JPA中进行级联删除,在数据库中对外键删除不做任
我正在尝试创建具有一对一关系的域对象。A 是父母,B 是孩子。 我尝试了许多不同的方法来将删除从 A 级联到 B,但是当我查看数据库创建时,它没有设置 ON DELETE CASCADE。 有人能看到我做错了什么吗 答: 我知道CascadeType.ALL或孤儿移除应该有效果,但他们没有。 B: 有人能明白为什么它不级联删除吗?
嗨,我遇到这样的情况: 带有2个字段的实体标记,其中包含2组对象(Obj1、Obj2)。删除Obj1时,我想删除标记实体中设置的Obj1中包含的所有信息。你能告诉我怎么做吗? 检查点中没有对标记的引用。若我将Cascade设置为ManyToMany,那个么当我删除标记时,所有带有该标记的用户都会被删除。我想要的是在删除检查点时删除tag\u检查点表中的行。我应该自己做还是有好办法??
问题内容: 性能是关键:在数据库内部级联删除/更新还是让Hibernate / JPA处理它更好? 如果级联在DBMS内部,这会影响查询数据的能力吗? 如果这很重要,我正在使用HSQLDB。 问题答案: 对于级联更新,如果您在数据库中具有外键约束,则根本无法在应用程序空间中执行此操作。 示例:假设您有一个针对美国各州的查找表,主键为两个字母的缩写。然后,您有了一个表,用于引用该表的邮寄地址。有人告
问题内容: 假设我们有两个实体,A和B。B与A具有多对一关系,如下所示: 现在,我要删除对象,并将删除操作级联到其所有子项。有两种方法可以做到这一点: 添加到OneToMany批注中,让JPA删除所有子项,然后再从数据库中删除A对象。 保持类不变,只需让数据库级联删除操作即可。 使用后面的选项有什么问题吗?这会导致实体管理器保留对已删除对象的引用吗?我之所以选择选项2而不是选项1的原因是,选项1生
我制作了一个JTable,其中填充了数据库中的数据。它从textfields中获取数据并将其添加到表和数据库中。问题是我有一个删除按钮,我让它从表本身删除选定的行(使用defaultTableModel),但它不会从实际的数据库中删除该数据。当我再次运行该程序时,删除的行再次出现在JTable中。 这可能会变得混乱,但希望有人能找出我错过了什么。帮助将会很感激,但不要,我的时间很少,不能完全大修我