Spring Boot Jpa之CascadeType
JPA允许您传播从父实体到子级的状态转换。为此,JPA javax.persistence.CascadeType定义了各种级联类型:
ALL
级联所有实体状态转换
PERSIST
级联实体持久化操作。
MERGE
级联实体合并操作。
REMOVE
级联实体删除操作。
REFRESH
级联实体刷新操作。
DETACH
级联实体分离操作。
此外,CascadeType.ALL将会传播任何Hibernate特定的操作,它由org.hibernate.annotations.CascadeType枚举定义:
以下示例将使用以下实体来解释上述一些级联操作:
@Entity
public class Person {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
private List<Phone> phones = new ArrayList<>();
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;
}
public List<Phone> getPhones() {
return phones;
}
public void addPhone(Phone phone) {
this.phones.add( phone );
phone.setOwner( this );
}
}
@Entity
public class Phone {
@Id
private Long id;
@Column(name = "`number`")
private String number;
@ManyToOne(fetch = FetchType.LAZY)
private Person owner;
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;
}
}
CascadeType.PERSIST示例
Person person = new Person();
person.setId( 1L );
person.setName( "John Doe" );
Phone phone = new Phone();
phone.setId( 1L );
phone.setNumber( "123-456-7890" );
person.addPhone( phone );
entityManager.persist( person );
当父实体Person被持久化时,会连同持久化子实体Phone。
对象会进入到持久化状态,对该对象的操作会自动同步到数据库。
指定
cascade = CascadeType.PERSIST
在实体类关联的实体字段上,那么保存该实体类时会级联保存该实体类关联的实体。
CascadeType.MERGE示例
Phone phone = entityManager.find( Phone.class, 1L );
Person person = phone.getOwner();
person.setName( "John Doe Jr." );
phone.setNumber( "987-654-3210" );
entityManager.clear();
entityManager.merge( person );
查询Phone实体的时候会执行语句:
SELECT
p.id as id1_0_1_,
p.name as name2_0_1_,
ph.owner_id as owner_id3_1_3_,
ph.id as id1_1_3_,
ph.id as id1_1_0_,
ph.number as number2_1_0_,
ph.owner_id as owner_id3_1_0_
FROM
Person p
LEFT OUTER JOIN
Phone ph
on p.id=ph.owner_id
WHERE
p.id = 1
在合并期间,获取子实体Phone时,会连同获取级联的父实体Person。这个级联只能合并数据库已存在的实体。
对象会进入到被管理状态,对该对象(可以是任何状态的对象)的操作会自动同步到数据库。
CascadeType.REMOVE示例
Person person = entityManager.find( Person.class, 1L );
entityManager.remove( person );
执行的SQL:
DELETE FROM Phone WHERE id = 1
DELETE FROM Person WHERE id = 1
该CascadeType.REMOVE使我们能够沿父实体一个删除级联的子实体。
CascadeType.DETACH
意思是,分离所有相关联的实体,该实体已在数据库中,对象将处于分离状态,对该对象的操作不会同步到数据库。
CascadeType.REFRESH
Person person = personDao.findOne(944397L);
Phone phone = person.getPhones().get(0);
person.setName( "John Doe Jr." );
phone.setNumber( "987-654-3210" );
personDao.save( person );
assertEquals( "John Doe", person.getName() );
assertEquals( "123-456-7890", phone.getNumber() );
当对父实体Person级联的对象进行操作并保存时,会关联保存子实体Phone到数据库。
以上。。。