JPA Hibernate - 在数据库和注释中级联删除 [英] JPA Hibernate - cascade delete in both database and annotation
问题描述
简介
我很想知道我应该怎么做,因为我已经阅读了许多试图理解这个问题的文章,其中包括许多SO问题。我已经读过的任何内容都与这篇文章相悖。
我想知道在使用级联规则和应用程序定义数据库时会发生什么因为这将决定我是否应采取以下方法或其他方式。
示例表
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,
主键(id),
外键( foo_id)在更新级联上引用foo(id)级联
)
示例类
@Entity
@Table(name =foo)
public class Foo {
private int id;
私人列表< Bar>酒吧;
@Id
@GeneratedValue
@Column(name =id)
public int getId(){
return id;
}
@OneToMany(mappedBy =foo,cascade = {CascadeType.ALL})
public List< Bar> getBars(){
返回酒吧;
}
public void setId(){
this.id = id;
}
public void setBars(List< Bar> bars){
this.bars = bars;
$ b @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;
}
}
问题
如果我现在调用一个删除操作(通过 EntityManagerFactory
或 SessionFactory
)在 Foo
对象上,会发生以下哪种情况?
-
hibernate操作将删除
bar
表中的所有记录,其中外键是Foo
的sfoo_id
,然后删除
Foo
记录。 -
hibernate操作将删除已加载到会话缓存中的所有相应的
Bar
记录(其中
可能或可能不全是bar
记录存在于实际数据库中)和
,然后删除Foo
记录(数据库级联规则将删除任何剩余的bar
记录)。
-
hibernate操作将尝试
删除<首先记录code> Foo ,如果数据库失败然后做
之前提到的步骤之一。
还有其他的事情发生在我没有考虑的地方,如果是的话?
考虑到以下这些困境,最好的方法是什么?
Dilemna
如果1为真,那么它会提示:a)仅在数据库中定义级联规则。一定要从应用程序中的对象中删除 bars
,这样它们不会从数据库中脱离(因为数据库将删除它们的记录),然后调用delete <$ c)c> foo 。
OR
应用程序,因为它会彻底地管理数据库的完整性。
不是
c)在这两个中定义级联规则,因为每一个都达到了理想的结果,使得另一个浪费处理。
如果2是真的,那么它会提示:
在数据库和应用程序中定义级联规则,以便Hibernate可以负责管理其实体,并且数据库可以在清除之后清除,因为应用程序不保证删除所有 bar
记录。
如果3是真的,那么它会提示:
在数据库和数据库中定义级联规则因为Hibernate似乎支持已经定义的级联规则d在数据库级别。
如果4是真的,那么它会提示:
这个问题甚至更多
编辑:添加我已阅读的文章...
相关文章
数据库,应用程序或两者的冲突视图:
SO-should-i-let-jpa-or-the-database-cascade-deletions
数据库或应用程序的冲突视图:
本文阐述了JPA提供者实施的内容(尽管应该指出的是,他们使用OpenJPA提供程序进行操作证明):
它指出:
删除和持久操作的级联也适用于尚未加载的那些
实体。它甚至将它们传递给
其他实体,可能遍历整个对象图。
它进入状态:
<刷新,合并和分离的级联仅通过已加载的
实体。
这意味着建议的过程2不成立。
如果您在数据库中声明级联,并且休眠数据库将始终先删除(如果它支持它),并且hibernate调用不会真的删除任何内容,但是仍然会运行。但是,由于您使用的是hibernate,因此它的主要优点是可以轻松转换到可能不支持数据库端级联功能的新数据库。因此,即使您的数据库支持级联,并且强调jdbc语句目前没有执行任何操作(它们可能会在未来执行某些操作),您仍然希望将它们留在那里。
Brief
I am wondering what I should do as I have read many articles trying to understand this, including many SO questions. Nothing I have read has quite hit the nail on the head with this one.
I want to know what happens when a database is defined with cascade rules as well as the application since this will define whether I should take the following approach or another.
Example tables
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
)
Example classes
@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;
}
}
Questions
If I now call a delete operation (be it through EntityManagerFactory
or SessionFactory
) on a Foo
object, which of the following will occur?
The hibernate operation will delete all records in the
bar
table whose foreign key is that ofFoo
'sfoo_id
and then delete theFoo
record.The hibernate operation will delete all corresponding
Bar
records that have been loaded into session cache (which may or may not be allbar
records that exist in the actual database) and then delete theFoo
record (the database cascade rule will then delete any remainingbar
records).The hibernate operation will attempt to delete the
Foo
record first and if database failure then do one of the aforementioned steps.Something else happens for which I have not considered, if so what?
Considering the following dilemna assumptions, what is the best approach?
Dilemna
If 1 is true then it would suggest:
A) Define cascade rule in database only. Be sure to remove bars
from the object in the application so they are not left detached from the database (as the database will delete their records) then make the call to delete foo
.
OR
B) Define cascade rule in application only since it will manage the database integrity thoroughly.
NOT
C) Define cascade rules in both, since each achieve the desired result making the other a waste of processing.
If 2 is true then it would suggest:
Define cascade rules in both database and application so that Hibernate can take care of managing its entities and the database can clean up after since the application is not guaranteed to remove all the bar
records.
If 3 is true then it would suggest:
Define cascade rules in both database and application since Hibernate appears to support the cascade rule already being defined at the database level.
If 4 is true then it would suggest:
This question is even more important as I have missed something fundamental!
Edit: Add articles I have read...
Related articles
Conflicting views for database, application or both:
SO - should-i-let-jpa-or-the-database-cascade-deletions
Conflicting views for database or application:
SO - cascading-deletes-updates-using-jpa-or-inside-of-database
This article sheds light on what JPA providers actually do (though it should be noted that they use OpenJPA provider for their proof of operations):
It states that:
The cascading of remove and persist operations applies also on those entities that have not been loaded yet. It even passes through them to other entities, potentially traversing through whole object graph.
It goes on to state:
The cascading of refresh, merge and detach passes only through entities that are already loaded.
This would mean that proposed process 2 is not true.
if you declare cascade in the database and hibernate the database will always delete first if it supports it and the hibernate calls will not really delete anything but run anyway. However, since you are using hibernate its main advantage is to allow easy transition to a new database which may not support database side cascade ability. Thus you would want to leave them in there even if your database supports cascade and the hiberate underlining jdbc statements are not currently doing anything (they may do something in the future)
这篇关于JPA Hibernate - 在数据库和注释中级联删除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!