Spring Boot Jpa之CascadeType

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到数据库。

以上。。。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,以下是 Spring Boot JPA 实现一对多增删改查的示例代码: 1. 创建实体类 ``` @Entity public class Parent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) private List<Child> children = new ArrayList<>(); // getters and setters } @Entity public class Child { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_id") private Parent parent; // getters and setters } ``` 2. 创建 Repository 接口 ``` public interface ParentRepository extends JpaRepository<Parent, Long> { } ``` 3. 创建 Service 类 ``` @Service public class ParentService { @Autowired private ParentRepository parentRepository; public Parent save(Parent parent) { return parentRepository.save(parent); } public void delete(Long id) { parentRepository.deleteById(id); } public Parent findById(Long id) { return parentRepository.findById(id).orElse(null); } public List<Parent> findAll() { return parentRepository.findAll(); } } ``` 4. 创建 Controller 类 ``` @RestController @RequestMapping("/parents") public class ParentController { @Autowired private ParentService parentService; @PostMapping public Parent create(@RequestBody Parent parent) { return parentService.save(parent); } @PutMapping("/{id}") public Parent update(@PathVariable Long id, @RequestBody Parent parent) { Parent existingParent = parentService.findById(id); if (existingParent == null) { throw new RuntimeException("Parent not found"); } existingParent.setName(parent.getName()); existingParent.setChildren(parent.getChildren()); return parentService.save(existingParent); } @DeleteMapping("/{id}") public void delete(@PathVariable Long id) { parentService.delete(id); } @GetMapping("/{id}") public Parent findById(@PathVariable Long id) { return parentService.findById(id); } @GetMapping public List<Parent> findAll() { return parentService.findAll(); } } ``` 以上就是 Spring Boot JPA 实现一对多增删改查的示例代码。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值