今天在测试hibernate的时候,发生了object references an unsaved transient instance - save the transient instance before flushing: com.aaa.bean.Tutor这样的错误。
一般来说,这样的错误还是挺常见的。但是问题恰恰出现在不常见的地方。先贴配置文件和测试代码:
@Test
public void addRecordTest2() throws ParseException {
Session session = HbSessionUtil.getSession();
Transaction transaction = session.beginTransaction();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = dateFormat.parse("2015-09-09");
Graduate graduate1 = new Graduate("aaaa", "男", date);
Graduate graduate2 = new Graduate("bbb", "男", date);
Tutor tutor1 = new Tutor("1111", "11", "1111");
tutor1.getGraduates().add(graduate1);
tutor1.getGraduates().add(graduate2);
//保存一的一方
session.save(tutor1);
transaction.commit();
session.close();
}
实际上我已经在配置文件中设置了cascade="save-update",还出错,这就有点郁闷了。
出现object references an unsaved transient instance - save the transient instance before flushing的错误就是因为在保存一个实体的时候,实体中存在对其他实体的引用,但是该引用的实体并没有存在于已有的数据库中和hibernate缓存中(更准确地讲,是出于游离态 ,这就是所谓的transient instance)。要解决这样的问题要么就手动保存出于游离态的那些实体,要么就设置cascade="all"或者="save-update",让hibernate保存一方的时候保存另一方。
从代码中可以看到我要保存的是tutor1,tutor有个set集合,集合中放的是graduate对象,我在配置文件中设置了cascade="save-update",就已经告诉了hibernate,在我保存tutor的时候要帮我保存set集合中的内容。理论上来说是没有问题的。
再仔细看看报错信息,save the transient instance before flushing: com.aaa.bean.Tutor。是在保存tutor的时候出错的,这就匪夷所思了。tutor是我手动保存的啊,怎么会有问题呢?! 哪里还存在出于游离态的tutor没有被我手动保存呢?经过仔细对比排查,发现,我居然是在Graduate的bean中new了一个tutor。
所以当hibernate自动帮我报graduate对象的时候,它发现里面还有一个游离态的tutor对象,就报错了。