Hibernate中的级联策略和object references an unsaved transient instance - save the transient instance before
来源:互联网 发布:拼图软件 编辑:程序博客网 时间:2024/06/03 22:43
本片博文整理关于Hibernate中级联策略cascade和它导致的异常:
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.mao.Address
关于这个异常应该是Hibernate初学者经常遇到的,导致该异常的原因就是:你的对象引用了一个未保存的瞬态实例,换句话讲就是:因为主表的记录不曾插入,所以参照该记录的从表记录也就无法插入
举个例子 咱们有两个表
表一 person_inf(从表)
结构:person_id(主键) person_name address_id(外键)
表二 address_inf(主表)
结构:address_id(主键) address_detail
如果从表的记录(address_detail)都没持久化,还处于瞬态,你在主表person_inf中就引用了从表信息,从表记录自然也不会插入,而且就会报该错。
下面是具体一个OneToOne实例
1:Person.java
import java.util.*;import javax.persistence.*;@Entity@Table(name="person_inf")public class Person{// 标识属性@Id @Column(name="person_id")@GeneratedValue(strategy=GenerationType.IDENTITY)private Integer id;private String name;private int age;// 定义该Person实体关联的Address实体@OneToOne(targetEntity=Address.class,cascade=CascadeType.ALL)// 映射名为address_id的外键列,参照关联实体对应表的addres_id主键列@JoinColumn(name="address_id", referencedColumnName="address_id" , unique=true)private Address address; //省略所有set get方法}
注意上面代码中@OneToOne(cascade=CascadeType.All)这条,它就代表着将所有的持久化操作都级联到关联体中,意思就是系统会自动级联插入主表记录(address_inf表),再插入从表记录(person_inf),而不用担心该关联体是否已经保存为持久化状态
2:关联体Address.java
import java.util.ArrayList;import java.util.List;import javax.persistence.*;@Entity@Table(name="address_inf")public class Address {@Id@Column(name="address_id")@GeneratedValue(strategy=GenerationType.IDENTITY)private int addressId;private String addressDetail;public Address() {}public Address(String addressDetail) {this.addressDetail = addressDetail;}//省略set get方法
3:主程序PersonManager.java 这里只贴出部分添加数据代码
Person person=new Person();person.setName("VipMao");person.setAge(24);//创建一个瞬态 的Adress对象Address address=new Address("山东曲阜");//设置Person和Adress之间的关联关系person.setAddress(address);//persist方法并不是立刻将标识符填入到实例化中 这是与save方法的区别session.persist(person);tx.commit();
代码可以看出,我们并没有将address对象保存为持久化就直接通过session.persist(person)映射到person_inf数据表中了,这是因为我们前面设置了@OneToOne(cascade=CascadeType.All),这就说明当程序执行到session.persist(person)的时候,会先执行插入address_inf表记录,再执行插入person_inf表记录,从打印的SQL语句也可以看出:
这里也建议大家在学习Hibernate时把show_sql 设置成true 这样你就会清楚的看见程序先执行了什么后干了什么。
这就是级联操作。如果将@OneToOne(cascade=CascadeType.All)去掉,就没法通过级联插入address表数据,就会报错:Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.mao.Address
另一种解决方式就是将程序改成如下
Person p = new Person();// 设置Person的name为crazyit字符串p.setName("VipMao");p.setAge(24);// 创建一个瞬态的Address对象Address a = new Address("山东曲阜");// 通过Person对象建立它自己与Address实体的关联关系p.setAddress(a);// 先持久化Address对象(对应为插入主表记录)session.persist(a);// 再持久化Person对象(对应为插入从表记录)session.save(p);tx.commit();
在将数据插入之前就将他持久化。
4:运行结果
可以发现无论通过cascade=CascadeType.All级联方式还是通过手动先保存持久化都可以实现
总结:
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.mao.Address
导致原因:
你的对象引用了一个未保存的瞬态实例,换句话讲就是:因为主表的记录不曾插入,所以参照该记录的从表记录也就无法插入
解决方案:
1:通过cascade=CascadeType.All将Hibernate的所有持久化操作都级联到关联实体
2:将你需要插入的数据先持久化,再映射到相应的表中。
- Hibernate中的级联策略和object references an unsaved transient instance - save the transient instance before
- net.sf.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before
- Hibernate 异常:object references an unsaved transient instance - save the transient instance before fl
- Hibernate 异常:object references an unsaved transient instance - save the transient instance before fl
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing异常
- object references an unsaved transient instance - save the transient instance before flushing(异常总结)
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing .
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing(异常总结)
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- object references an unsaved transient instance - save the transient instance before flushing
- 258. Add Digits [easy] (Python)
- Cocos2d-x 3.9 + VS2012 + BabeLua 如何搭建cocos2dx lua环境
- Stanford 机器学习 Anomaly Detection
- hihoCoder1301 筑地市场(统计符合条件数字,数位dp)
- 匈牙利算法模板及解释
- Hibernate中的级联策略和object references an unsaved transient instance - save the transient instance before
- windows命令行启动虚拟机(VirtualBox、VMware)
- HDU1068 二分图 最大独立集
- Android Studio报错,Error:SSL peer shut down incorrectly
- 图像处理之高斯金字塔
- vim查找替换
- 交换两个值函数swap()实现小结
- Java中的Set与hashCode
- 最大似然估计(MLE)和最大后验概率(MAP)