本片博文整理关于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:将你需要插入的数据先持久化,再映射到相应的表中。

帖子来源于:https://blog.csdn.net/VipMao/article/details/51378237

ERROR org.hibernate.internal.SessionImpl - HHH000346: Error during managed flush [object references an unsaved transient instance - save the transient instance before flushing: cn.itcast.domain.Custom的更多相关文章

  1. org.hibernate.AnnotationException: No identifier specified for entity: cn.itcast.domain.Counter

    因为我的hibernate映射表没有主键所以报这个错. 解决方案是: 1.创建一个主键 2.hibernate处理无主键的表的映射问题,其实很简单,就是把一条记录看成一个主键,即组合主键<com ...

  2. 三大框架常遇的错误:hibernate : object references an unsaved transient instance

    hibernate : object references an unsaved transient instance 该错误是操作顺序的问题,比如: save或update顺序问题---比方学生表和 ...

  3. Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved tran

    今天在使用一对多,多对一保存数据的时候出现了这个错误 Hibernate错误: Exception in thread "main" org.hibernate.Transient ...

  4. Hibernate的一个问题object references an unsaved transient instance - save the transi5

    1 我做了一对多和多对一的双向关联关系,在User这一方@ManyToOne已经设置了级联Cascade,这样在测试程序中保存User时,Group也应该自动保存,为什么会抛出以下的异常: (我是按着 ...

  5. hibernate 对象状态异常:object references an unsaved transient instance - save the transient instance before flushing

    我的问题出在,删除的对象对应的表中有一个外键,关联着另外一个表,可是另外一个表中没有数据,所以报了这个错误. 参考http://www.cnblogs.com/onlywujun/archive/20 ...

  6. hibernate : object references an unsaved transient instance 问题

    save顺序问题---比如学生表和班级表..学生表里有班级ID的外键.一对多的关系. 你save的时候应该先save班级,再save学生..否则学生的外键没有对应的值,引发异常

  7. 关于Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]错误

    控制台报错: 08:07:09.293 [http-bio-8080-exec-2] ERROR org.hibernate.internal.SessionImpl - HHH000346: Err ...

  8. ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - Data truncation: Incorrect datetime value: '' for column 'pubdate' at row 1

    之前的Connector/J版本是:mysql-connector-java-5.0.4-bin.jar 后来换成mysql-connector-java-5.1.45-bin.jar,问题解决 20 ...

  9. 报错HTTP Status 500 - HHH000142: Javassist Enhancement failed: cn.itcast.entity.Customer; nested exception is org.hibernate.HibernateException: HHH000142: Javassist Enhancement failed: cn.itcast.entity.

    报错 type Exception report message HHH000142: Javassist Enhancement failed: cn.itcast.entity.Customer; ...

随机推荐

  1. 获取数值型数组中大于60的元素个数,给数值型数组中不足60分的加20分。(数组,for循环,if条件判断语句)

    package com.Summer_0420.cn; /** * @author Summer * 获取数值型数组中大于60的元素个数 * 给数值型数组中不足60分的加20分 */ public c ...

  2. Java IO(三)——字节流

    一.流类 Java的流式输入/输出是建立在四个抽象类的基础上的:InputStream.OutputStream.Reader.Writer.它们用来创建具体的流式子类.尽管程序通过具体子类执行输入/ ...

  3. Linux进程管理 (1)进程的诞生

    专题:Linux进程管理专题 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 L ...

  4. Linux并发与同步专题 (4) Mutex互斥量

    关键词:mutex.MCS.OSQ. <Linux并发与同步专题 (1)原子操作和内存屏障> <Linux并发与同步专题 (2)spinlock> <Linux并发与同步 ...

  5. Linux IO性能分析blktrace/blk跟踪器

    关键词:blktrace.blk tracer.blkparse.block traceevents.BIO. 本章只做一个记录,关于优化Block层IO性能方法工具. 对Block层没有详细分析,对 ...

  6. docker容器中安装vi命令

    在使用docker容器时,有时候里边没有安装vim,敲vim命令时提示说:vim: command not found,这个时候就需要安装vim,可是当你敲apt-get install vim命令时 ...

  7. Python从菜鸟到高手(8):print函数、赋值与代码块

    1.神奇的print函数   print函数相信读者一定对它不陌生,因为在前面的章节,几乎每个例子都使用了print函数,这个函数的功能就是在控制台输出文本.不过print在输出文本时还可以进行一些设 ...

  8. [WPF]如何使用代码创建DataTemplate(或者ControlTemplate)

    1. 前言 上一篇文章([UWP]如何使用代码创建DataTemplate(或者ControlTemplate))介绍了在UWP上的情况,这篇文章再稍微介绍在WPF上如何实现. 2. 使用Framew ...

  9. XenServer 5.5 断电重启虚拟机磁盘丢失的修复

    1.现象 公司云平台使用的是XenServer 5.5,版本比较老了.最近几天因为机房改造,导致云环境断电,重启之后发现有2台机器无法ping到,所以再次重启,登录修复网卡,最后发现无法用XenCen ...

  10. Array Queries CodeForces - 797E

    题目链接 非常好的一道题目, 分析,如果用暴力的话,时间复杂度是O(q*n)稳稳的超时 如果用二维DP的话,需要O (n*n)的空间复杂度,会爆空间. 那么分析一下,如果k>sqrt(n)的话, ...