JPA object报错:references an unsaved transient instance - save the transient instance before flushing

今天在写后端接口的时候发现控制台报错。

这段英文的意思是 “对象指向了一个无法保存的瞬态实例”

这是什么意思呢?

举个例子

如上图所示,现在有两个实体类 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)

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值