今天老师重新详细讲解了hibernate 里的POVO.
最开始理解的POVO,感觉就是通过SAVE()方法,将OBJ 持久化到数据库.如果要UPDATE,只要将oBJ 里属性SET一个新值,然后执行下UPDATE就好(这是种错误的概念),因为那时还没怎么接触POVO,一开始看到这个已经感到很强大了,马上就在脑子中记住了POVO.
本以为在项目中可以得心应手的利用这个好处,结果错误的理解让我出了很多异常:
a different object with the same identifier value was already associated with the session;
上面就是其中一个,原因是对于POVO的理解错误,引起的,先看下面的一段代码:
Cat princess = new Cat();//新建一个Cat对象
princess.setId("402881830c2cf0f3010c2cf0f8b40001");//将对象set一个数据库中已存在的ID
princess.setName("Princess");
princess.setSex('F');
princess.setWeight(18.8f);
Cat princess2 = new Cat();//又新建一个Cat对象
princess2.setId("402881830c2cf0f3010c2cf0f8b40001");//同时将这个对象也set相同的ID
princess2.setName("Princess");
princess2.setSex('F');
princess2.setWeight(19.8f);
Session session = HibernateSessionFactory.currentSession();//好戏出场了,我们先current a Session
Transaction tx = session.beginTransaction();//开始事物(Transaction到底是什么也不太懂,我只知道它可以将缓存中数据写入数据库)
// Cat c = (Cat)session.load(Cat.class, "402881830c2cf0f3010c2cf0f8b40001");
// c.setWeight(20.3f);
session.saveOrUpdate(princess);//此时我们用session保存了princess,这之后的princess应该是持久化了,成了PO
session.saveOrUpdate(princess2);//如果按我一开始的理解,此时princess2应该也是可以持久化的(看上面兰色部分),因为princess2只是将princess更新了而已(这是致命的错误).
tx.commit();
HibernateSessionFactory.closeSession();
执行的结果总是那么讽刺, a different object with the same identifier value was already associated with the session
遇到了问题,总是最让人兴奋与无奈的时候.还是来看看为什么出错吧:
首先来讲讲POVO,PO又名persistence object,持久化对象,是指在对象通过save(),update(),load(),get();后,在session的Entity map实体容器里将持久话的对象add进去,也就是说,在我session.saveOrUpdate(princess);时,实体容器里已经将key和对象加入了.因为map是通过不同key来加OBJ的,而在hibernate里ID是唯一标识,使用ID来当做key是最好不过的了.因此Session 的实体容器只能加入一个id的对象.当session.saveOrUpdate(princess2);的时候,session准备把princess2也add到entityMap里时,由于相同的id,也就是key,它就报异常了a different object with the same identifier ..恭喜中标.
也就是说PO是在session 的实体容器里可引用的对象,当我要更新PO时,可以set一个属性值,然后只要tx.commit();动作,就可以更新了(让我个人感到非常惊讶的地方).
除了save();之外,同样通过load,update,get也可以获得PO.不过load和get有一少许区别(在使用的版本3.0中),get(id)就直接把DO获得(马上执行select操作),而load则不同,它会先对要load的ID做个标记,当要使用这个导出的对象时,它再执行.用上面的例子:
Cat c = (Cat)session.load(Cat.class, "402881830c2cf0f3010c2cf0f8b40001");//此时只是做标记
c.setWeight(20.3f);//这个时候才真正的执行了select 语句.