HHH-11186 - Add examples for all Hibernate annotations
Document @OnDelete annotation
This commit is contained in:
parent
a7f77e2687
commit
baf194d422
|
@ -1047,7 +1047,7 @@ The two possible strategies are defined by the https://docs.jboss.org/hibernate/
|
|||
CASCADE:: Use the database FOREIGN KEY cascade capabilities.
|
||||
NO_ACTION:: Take no action.
|
||||
|
||||
//TODO: Add example
|
||||
See the <<chapters/pc/PersistenceContext.adoc#pc-cascade-on-delete, `@OnDelete` cascade>> chapter for more info.
|
||||
|
||||
[[annotations-hibernate-optimisticlock]]
|
||||
==== `@OptimisticLock`
|
||||
|
|
|
@ -696,6 +696,7 @@ Even if just the `Person` parent entity was persisted, Hibernate has managed to
|
|||
|
||||
The `CascadeType.MERGE` allows us to merge a child entity along with the parent one.
|
||||
|
||||
[[pc-cascade-merge-example]]
|
||||
.`CascadeType.MERGE` example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
|
@ -755,6 +756,7 @@ Such a use case requires the use of the `PessimisticLockScope.EXTENDED` value of
|
|||
|
||||
However, `CascadeType.LOCK` allows us to reattach a parent entity along with its children to the currently running Persistence Context.
|
||||
|
||||
[[pc-cascade-lock-example]]
|
||||
.`CascadeType.LOCK` example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
|
@ -769,6 +771,7 @@ include::{sourcedir}/CascadeLockTest.java[tags=pc-cascade-lock-example]
|
|||
The `CascadeType.REFRESH` is used to propagate the refresh operation from a parent entity to a child.
|
||||
The refresh operation will discard the current entity state, and it will override it using the one loaded from the database.
|
||||
|
||||
[[pc-cascade-refresh-example]]
|
||||
.`CascadeType.REFRESH` example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
|
@ -790,6 +793,7 @@ In the aforementioned example, you can see that both the `Person` and `Phone` en
|
|||
The `CascadeType.REPLICATE` is to replicate both the parent and the child entities.
|
||||
The replicate operation allows you to synchronize entities coming from different sources of data.
|
||||
|
||||
[[pc-cascade-replicate-example]]
|
||||
.`CascadeType.REPLICATE` example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
|
@ -805,3 +809,42 @@ include::{extrasdir}/pc-cascade-replicate-example.sql[]
|
|||
|
||||
As illustrated by the SQL statements being generated, both the `Person` and `Phone` entities are replicated to the underlying database rows.
|
||||
|
||||
[[pc-cascade-on-delete]]
|
||||
==== `@OnDelete` cascade
|
||||
|
||||
While the previous cascade types propagate entity state transitions, the `@OnDelete` cascade is a DDL-level FK feature which allows you
|
||||
to remove a child record whenever the parent row is deleted.
|
||||
|
||||
So, when annotating the `@ManyToOne` association with `@OnDelete( action = OnDeleteAction.CASCADE )`,
|
||||
the automatic schema generator will apply the ON DELETE CASCADE SQL directive to the Foreign Key declaration,
|
||||
as illustrated by the following example.
|
||||
|
||||
[[pc-cascade-on-delete-mapping-example]]
|
||||
.`@OnDelete` mapping
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/CascadeOnDeleteTest.java[tags=pc-cascade-on-delete-mapping-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-cascade-on-delete-mapping-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Now, you can just remove the `Person` entity, and the associated `Phone` is going to be removed automatically.
|
||||
|
||||
[[pc-cascade-on-delete-example]]
|
||||
.`@OnDelete` example
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/CascadeOnDeleteTest.java[tags=pc-cascade-on-delete-example]
|
||||
----
|
||||
|
||||
[source, SQL, indent=0]
|
||||
----
|
||||
include::{extrasdir}/pc-cascade-on-delete-example.sql[]
|
||||
----
|
||||
====
|
|
@ -0,0 +1,3 @@
|
|||
delete from Person where id = ?
|
||||
|
||||
-- binding parameter [1] as [BIGINT] - [1]
|
|
@ -0,0 +1,18 @@
|
|||
create table Person (
|
||||
id bigint not null,
|
||||
name varchar(255),
|
||||
primary key (id)
|
||||
)
|
||||
|
||||
create table Phone (
|
||||
id bigint not null,
|
||||
"number" varchar(255),
|
||||
owner_id bigint,
|
||||
primary key (id)
|
||||
)
|
||||
|
||||
alter table Phone
|
||||
add constraint FK82m836qc1ss2niru7eogfndhl
|
||||
foreign key (owner_id)
|
||||
references Person
|
||||
on delete cascade
|
|
@ -0,0 +1,125 @@
|
|||
package org.hibernate.userguide.pc;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class CascadeOnDeleteTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Person.class,
|
||||
Phone.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
Person person = new Person();
|
||||
person.setId( 1L );
|
||||
person.setName( "John Doe" );
|
||||
entityManager.persist( person );
|
||||
|
||||
Phone phone = new Phone();
|
||||
phone.setId( 1L );
|
||||
phone.setNumber( "123-456-7890" );
|
||||
phone.setOwner( person );
|
||||
entityManager.persist( phone );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::pc-cascade-on-delete-example[]
|
||||
Person person = entityManager.find( Person.class, 1L );
|
||||
entityManager.remove( person );
|
||||
//end::pc-cascade-on-delete-example[]
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::pc-cascade-on-delete-mapping-example[]
|
||||
@Entity(name = "Person")
|
||||
public static class Person {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::pc-cascade-on-delete-mapping-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
//tag::pc-cascade-on-delete-mapping-example[]
|
||||
}
|
||||
|
||||
@Entity(name = "Phone")
|
||||
public static class Phone {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
@Column(name = "`number`")
|
||||
private String number;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@OnDelete( action = OnDeleteAction.CASCADE )
|
||||
private Person owner;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::pc-cascade-on-delete-mapping-example[]
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(String number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public Person getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(Person owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
//tag::pc-cascade-on-delete-mapping-example[]
|
||||
}
|
||||
//end::pc-cascade-on-delete-mapping-example[]
|
||||
}
|
Loading…
Reference in New Issue