HHH-11186 - Add examples for all Hibernate annotations

Document @OnDelete annotation
This commit is contained in:
Vlad Mihalcea 2017-05-25 17:12:39 +03:00
parent a7f77e2687
commit baf194d422
5 changed files with 190 additions and 1 deletions

View File

@ -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`

View File

@ -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[]
----
====

View File

@ -0,0 +1,3 @@
delete from Person where id = ?
-- binding parameter [1] as [BIGINT] - [1]

View File

@ -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

View File

@ -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[]
}