临时状态的测试
Student student = new Student("张三", "男", 22, new Date());
以上student就是一个Transient(临时状态),此时student并没有被session进行托管,即在session的缓存中还不存在student这个对象,当执行完save方法后,此时student被session托管,且数据库中也存在了该对象,student就变成了一个Persistent(持久化对象)
session.save(student); //save方法就是往数据库插入一条记录
结论
此时我们知道hibernate会发出一条insert的语句,执行完save方法后,该student对象就变成了持久化的对象了
持久状态的测试1
Student student = new Student("张三", "男", 22, new Date());
以上student就是Transient(瞬时状态),表示没有被session管理并且数据库中没有执行save之后,被session所管理,而且,数据库中已经存在,此时就是Persistent状态。
session.save(student);
此时student是持久化状态,已经被session所管理,当在commit()提交时,会把session中的对象和目前的对象进行比较如果两个对象中的值不一致就会继续发出相应的sql语句。
student.setSex("女");
此时会发出2条sql,一条用户做插入,一条用来做更新。
结论
在调用了save方法后,此时student已经是持久化对象了,被保存在了session缓存当中,这时student又重新修改了属性值,那么在提交事务时,此时hibernate对象就会拿当前这个student对象和保存在session缓存中的student对象进行比较,如果两个对象相同,则不会发送update语句,否则,如果两个对象不同,则会发出update语句。
注意
在调用save方法后,student此时已经是持久化对象了,记住一点:如果一个对象已经是持久化状态了,那么此时对该对象进行各种修改,或者调用多次update、save方法时,hibernate都不会发送sql语句,只有当事物提交的时候,此时hibernate才会拿当前这个对象与之前保存在session中的持久化对象进行比较,如果不相同就发送一条update的sql语句,否则就不会发送update语句。
持久状态的测试2
Student student = session.load(Student.class, 1); // 取出id等于1的学生记录
//上面的student是持久状态的对象
student.setAge(77); //修改了属性,让session提交commit事务的时候,student这个对象和session中的对象不一致,所以会发出sql完成更新
结论
当session调用load、get方法时,此时如果数据库中有该对象,则从数据库取出该对象也变成了一个持久化对象,被session所托管。因此,这个时候如果对对象进行操作,在提交事务时同样会去与session中的持久化对象进行比较,因此这里会发送两条sql语句。
持久状态的测试3
Student student = session.load(Student.class, 1);
// load方法的作用:取出id等于1的学生记录
// 上面的student是取出后就是持久状态的对象
student.setAge(67);
// 修改了属性,让session提交commit事务的时候,student这个对象和session中的对象不一致,所以会发出sql完成更新
//但是提交事务之前, 清空session里的缓存
session.clear();
游离状态测试1
Student student = new Student();
student.setId(2);
student.setName("李四");
//程序执行到这里,student就是一个游离对象的状态, 因为数据库中存在id=2的记录, 且这个student对象,又没被session托管,是离线状态的,所以它是游离状态
session.save(student);
//执行save, hibernate会以自己的规则,重新insert一条记录
结论
修改游离状态的对象的ID值不会报错,也没有任何效果,要把游离状态的对象转持久不能用save方法,要用update方法。
游离状态测试2
Student student = new Student();
student.setId(2);
student.setName("李四");
//程序执行到这里,student就是一个游离对象的状态, 因为数据库中存在id=2的记录, 并且这个student对象,又没被session托管,是离线状态的,所以它是游离状态
session.update(student);
// 执行update方法时,这个student对象,就从游离状态转变为了持久的状态了
student.setId(77); //报错, 不准修改
结论
持久状态的对象的ID值是不准修改的。
游离状态测试3
Student student = new Student();
student.setId(2);
//程序执行到这里,student就是一个游离对象的状态, 因为数据库中存在id=2的记录, 并且这个student对象,又没被session托管,是离线状态的,所以它是游离状态
session.delete(student);
// 执行delete方法,作用是讲对象的游离或持久状态删除,同时删除数据库中对应的记录。
结论
这个时候的student对象已经不再是session托管的了,缓存中也不存在了,变成临时状态的对象了, 这时没有后续的操作,它会被垃圾回收机制从内存中处理掉。
游离状态测试4
Student student = new Student();
student.setId(2);
//程序执行到这里,student就是一个游离对象的状态, 因为数据库中存在id=2的记录, 并且这个student对象,又没被session托管,是离线状态的,所以它是游离状态
session.saveOrUpdate(student);
// saveOrUpdate这个方法,是个偷懒的方法,当对象的状态是游离的,Hibernate就会去调用update方法,如果对象是临时状态的话,就调用save方法,这个方法不常用!
结论
有student.setId(2)这条语句,这个对象就会被假设是游离的,执行update方法,没有这条语句, 它会被Hivernate认为是临时状态,就执行save方法。
游离状态测试5
Student student = session.load(Student.class, 1);
// load方法的作用:取出id等于1的学生记录
// 上面的student是取出后就是持久状态的对象
Student student2 = new Student();
//这时候的stutent2是临时的状态
student2.setId(1);
// 修改里student2的ID值,它就转游离的状态了
session.saveOrUpdate(student2);
//执行更新操作,它的状态会从游离转持久,我们的对象是用ID值来辨别身份的,所以在session的缓存中就存在了两份同样的对象,在session中不能存在两份拷贝, 所以报错
结论
Hibernate的session的缓存中不许用出现两个或两个以上有相同ID值的对象。
最后总结一下
①.对于刚创建的一个对象,如果session中和数据库中都不存在该对象,那么该对象就是瞬时对象(Transient)
②.瞬时对象调用save方法,或者离线对象调用update方法可以使该对象变成持久化对象,如果对象是持久化对象时,那么对该对象的任何修改,都会在提交事务时才会与之进行比较,如果不同,则发送一条update语句,否则就不会发送语句
③.离线对象就是,数据库存在该对象,但是该对象又没有被session所托管