title: Spring-data-jpa的级联增删改查
date: 2020-03-13 14:14:23
categories: springboot
tags:
概述
此文是为了研究jpa级联表之间的增删改查,对这一方面内容进行一个总结
为了方便描述,使用的数据结构比较简单,书店和书,双向一对多的关系,实体如下:
默认情况下:(即不设置cascade属性,不显式使用CascadeType)
Book实体
@Data
@Entity
@Table
public class Book implements Serializable {
/**
* 编号
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
/**
* 书名
*/
@Column(name="name")
private String name;
@ManyToOne
@JoinColumn(name="bookstore_id")
private BookStore bookStore;
}
BookStore实体
@Data
@Entity
@Table
public class BookStore implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="name")
private String name;
@OneToMany(mappedBy = "bookStore")
private List bookList;
}
初始数据库表:
book表
book_store表
save操作
只对book_store进行保存
测试代码
@Test
public void test1(){
Book b=new Book();
b.setName("book1");
BookStore bs=new BookStore();
bs.setName("store1");
bookStoreRepo.save(bs);
}
保存后数据库如下:
book表:
book_store表:
可以看到只有book_store中有数据(id为4是因为之前表里有数据,然后手动进行了删除,所以id从4开始,不要在意这些细节),book表仍为空,说明保存关系被维护端并不会保存对应的关系维护端
只对book进行保存
测试代码
public void test2(){
Book b=new Book();
b.setName("book2");
BookStore bs=new BookStore();
bs.setName("store2");
b.setBookStore(bs);
bookRepo.save(b);
}
出现错误
TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
错误原因为对b进行持久化(即保存)之前为对bs进行持久化
先保存bookstore在保存book
测试代码
public void test3(){
Book b=new Book();
b.setName("book3");
BookStore bs=new BookStore();
bs.setName("store3");
b.setBookStore(bs);
bookStoreRepo.save(bs);
bookRepo.save(b);
}
操作成功,查看数据库
book表
bookstore表
可以看到,数据,外键均保存成功
先保存book在保存bookstore
测试代码
public void test4(){
Book b=new Book();
b.setName("book4");
BookStore bs=new BookStore();
bs.setName("store4");
b.setBookStore(bs);
bookRepo.save(b);
bookStoreRepo.save(bs);
}
操作失败,错误原因与只保存book相同
总结:
默认情况下,保存关系维护端由于外键的存在,必须后于被维护端进行保存,否则报错;
保存需要注意顺序,但均需进行保存操作;不会出现只保存一端,另一端也得到保存的情况,即保存没有级联
delete操作
执行操作前数据库为:
book表:
bookstore表
对bookstore表进行删除
测试代码
public void test5(){
Integer id=2;
BookStore bs1= bookStoreRepo.findById(id.longValue()).get();
id=3;
BookStore bs2= bookStoreRepo.findById(id.longValue()).get();
id=4;
BookStore bs3= bookStoreRepo.findById(id.longValue()).get();
//操作1
bookStoreRepo.delete(bs1);
//操作2
// bookStoreRepo.delete(bs2);
//操纵3
// bookStoreRepo.delete(bs3);
}
测试代码中,本别对id为2,3,4的bookstore记录进行删除,这几个记录分别关联book表中的2个,1个,0个记录
其中,操作1,2均执行失败,原因为book表中有指向它们的外键,存在外键约束;操作3执行成功,原因为book表中不存在指向它们的外键,没有外键约束,执行后book表不变,bookstore表如下: