今天在写后端接口的时候发现控制台报错。
这段英文的意思是 “对象指向了一个无法保存的瞬态实例”
这是什么意思呢?
举个例子
如上图所示,现在有两个实体类 Student, Address. Address 的外键关联Student 的主键。两者为一对一的关系
先看一下我们的实体类Student
@Data
@Entity
class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(mappedBy="student")
private Address address;
}
再看一下我们的Address
@Entity // 请注意一对一双向关联关系中不要在两个实体类上都添加@Data 注解,否则会出现循环引用,导致StackOverFlow 异常
class Address{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String street;
@OneToOne
private Student Student;
}
如果我们插入一条student 数据,在Jpa中我们可以这样
Student student = new Student();
Address address = new Address();
address.setStreet("莫邪路8号");
address.setStudent(student);//这一步是为了在数据库中给Address表添加外键,否则为外键为null
student.setName("小明");
student.setAddress(address);
studentRepository.create(student)
你要是这么写的话,就该报错啦,原因很简单。你要保存学生对象,程序会检测到你的学生对象里有一个address属性,address 属性指向的是address对象,而目前address 对象是一个瞬态对象,也就是说你要先把addess 对象保存到数据库当中,然后再保存student 对象到数据库中。否则就会报错: 对象(address属性)指向一个未保存的瞬态实例。
那么 我们应该怎么做呢?
有两种方法,
第一种方法:在Student 实体类中address 属性的@OneToOne注解上加上 "cascade = CascadeType.ALL"
@OneToOne(mappedBy="student", cascade = CascadeType.ALL)
private Address address;
cascade 的意思是级联操作。添加这个属性,程序运行后,就会先在Address 表中插入数据,再在Student 表中插入数据。
第二种方法:不要student 对象中添加address 属性。这样程序运行后就会插入一条student数据,这条数据Address 那一列的值null,同样的,这样也不会引发异常
Student student = new Student();
Address address = new Address();
student.setName("小明");
studentRepository.create(student)