hibernate04--三种状态之间的转换
public class StudentTest { Session session=null; Transaction transaction=null; //在执行测试方法之前 先执行before @Before public void before(){ /** * 01.读取核心的配置文件 在src的根目录下面! 底层规定位置! * 在实例化Configuration对象的时候通过configure() * 去src根目录下面,寻找hibernate.cfg.xml文件 */ Configuration configuration=new Configuration().configure(); //02.创建sessionFactory SessionFactory sessionFactory = configuration.buildSessionFactory(); //03.打开session session = sessionFactory.openSession(); //04.开启事务 transaction= session.beginTransaction(); } //在执行测试方法之后 @After public void after(){ //07.提交事务 sql语句 整体的执行! transaction.commit(); //08.关闭session session.close(); //sessionFactory.close(); 验证hbm2ddl中的create-drop } /** * hibernate对象的三种状态! * 01.瞬时状态(临时状态/自由状态) * 我们通过new关键字 创建出的一个实体对象!和hibernate没有半毛钱关系! * * 02.持久状态 * 对象正在被session管理,数据库中有对象 对应的数据! * 如果对象是持久状态! 那么对它的修改操作 不需要再使用其他的方法(update) * 在commit的时候,会执行flush(), * flush()的时候会进行缓存清理! * 缓存清理的时候会进行脏检查! * 如果对象的属性和之前的对象属性不一致! * 那么当前的对象就是脏对象! * 就会把脏对象同步到数据库! * * 03.游离状态(脱管状态) * 曾经被session管理过!和瞬时状态的区别就是 是否存在OID(主键标识符)! * */ @Test public void testSave1(){ //创建一个对象 Student stu=new Student(100, 50, "老白"); //瞬时状态 session.save(stu); //持久化状态 stu.setName("老白干"); /** 改变了对象的属性 这时候的stu就是脏对象 不需要执行update() commit的时候会产生两条sql语句! 01.insert 02.update */ } @Test public void testSave02(){ //创建一个对象 Student stu=new Student(666, 50, "老白"); //瞬时状态 stu.setName("老白干"); //瞬时状态 session.save(stu); //持久化状态 从这里开始 才被 session管理! } @Test public void testSave03(){ //创建一个对象 Student stu=new Student(555, 50, "老白"); //瞬时状态 stu.setName("老白干"); //瞬时状态 session.save(stu); //持久化状态 从这里开始 才被 session管理! stu.setName("老白干1"); stu.setName("老白干2"); stu.setName("老白干3"); /** * 还是两条sql语句 *commit的时候会产生两条sql语句! 01.insert 02.update */ } /** * 测试方法的前提环境三种情况 * 01.stu对象在数据库中没有对应的数据 * 02.stu对象在数据库中有对应的数据,但是我们没有修改属性 * 03.stu对象在数据库中有对应的数据,我们修改了属性 * 产生的结果都是一致的! * 根据id 产生update语句 */ @Test public void testUpdate(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.update(stu); } /** * 测试方法的前提环境 * stu对象在数据库中没有对应的数据 * 产生的结果: * 01.根据id 产生 select * 02.发现数据库中没有对应的数据 产生 insert */ @Test public void testSaveOrUpdate(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.saveOrUpdate(stu); } /** * 测试方法的前提环境 * 01.stu对象在数据库有对应的数据 * 02.没有改变stu对象的属性值 * 产生的结果: * 根据id 产生 select语句 */ @Test public void testSaveOrUpdate2(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.saveOrUpdate(stu); } /** * 测试方法的前提环境 * 01.stu对象在数据库有对应的数据 * 02.改变了stu对象的属性值 * 产生的结果: * 01.根据id 产生 select * 02.因为修改了对象的属性 所以 执行update */ @Test public void testSaveOrUpdate3(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 stu.setName("老白干"); session.saveOrUpdate(stu); } }
package cn.bdqn.test; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; import cn.bdqn.bean.Student; public class StudentTest { Session session=null; Transaction transaction=null; //在执行测试方法之前 先执行before @Before public void before(){ /** * 01.读取核心的配置文件 在src的根目录下面! 底层规定位置! * 在实例化Configuration对象的时候通过configure() * 去src根目录下面,寻找hibernate.cfg.xml文件 */ Configuration configuration=new Configuration().configure(); //02.创建sessionFactory SessionFactory sessionFactory = configuration.buildSessionFactory(); //03.打开session session = sessionFactory.openSession(); //04.开启事务 transaction= session.beginTransaction(); } //在执行测试方法之后 @After public void after(){ //07.提交事务 sql语句 整体的执行! transaction.commit(); //08.关闭session session.close(); //sessionFactory.close(); 验证hbm2ddl中的create-drop } /** * hibernate对象的三种状态! * 01.瞬时状态(临时状态/自由状态) * 我们通过new关键字 创建出的一个实体对象!和hibernate没有半毛钱关系! * * 02.持久状态 * 对象正在被session管理,数据库中有对象 对应的数据! * 如果对象是持久状态! 那么对它的修改操作 不需要再使用其他的方法(update) * 在commit的时候,会执行flush(), * flush()的时候会进行缓存清理! * 缓存清理的时候会进行脏检查! * 如果对象的属性和之前的对象属性不一致! * 那么当前的对象就是脏对象! * 就会把脏对象同步到数据库! * * 03.游离状态(脱管状态) * 曾经被session管理过!和瞬时状态的区别就是 是否存在OID(主键标识符)! * */ @Test public void testSave1(){ //创建一个对象 Student stu=new Student(100, 50, "老白"); //瞬时状态 session.save(stu); //持久化状态 stu.setName("老白干"); /** 改变了对象的属性 这时候的stu就是脏对象 不需要执行update() commit的时候会产生两条sql语句! 01.insert 02.update */ } @Test public void testSave02(){ //创建一个对象 Student stu=new Student(666, 50, "老白"); //瞬时状态 stu.setName("老白干"); //瞬时状态 session.save(stu); //持久化状态 从这里开始 才被 session管理! } @Test public void testSave03(){ //创建一个对象 Student stu=new Student(555, 50, "老白"); //瞬时状态 stu.setName("老白干"); //瞬时状态 session.save(stu); //持久化状态 从这里开始 才被 session管理! stu.setName("老白干1"); stu.setName("老白干2"); stu.setName("老白干3"); /** * 还是两条sql语句 *commit的时候会产生两条sql语句! 01.insert 02.update */ } /** * 测试方法的前提环境三种情况 * 01.stu对象在数据库中没有对应的数据 * 02.stu对象在数据库中有对应的数据,但是我们没有修改属性 * 03.stu对象在数据库中有对应的数据,我们修改了属性 * 产生的结果都是一致的! * 根据id 产生update语句 ! 只能是从游离变持久! */ @Test public void testUpdate(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.update(stu); } /** * 测试方法的前提环境 * stu对象在数据库中没有对应的数据 * 产生的结果: * 01.根据id 产生 select * 02.发现数据库中没有对应的数据 产生 insert */ @Test public void testSaveOrUpdate(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.saveOrUpdate(stu); } /** * 测试方法的前提环境 * 01.stu对象在数据库有对应的数据 * 02.没有改变stu对象的属性值 * 产生的结果: * 根据id 产生 select语句 */ @Test public void testSaveOrUpdate2(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 session.saveOrUpdate(stu); } /** * 测试方法的前提环境 * 01.stu对象在数据库有对应的数据 * 02.改变了stu对象的属性值 * 产生的结果: * 01.根据id 产生 select * 02.因为修改了对象的属性 所以 执行update */ @Test public void testSaveOrUpdate3(){ //创建一个对象 Student stu=new Student(1, 50, "老白"); //瞬时状态 stu.setName("老白干"); session.saveOrUpdate(stu); } /** * 测试方法的前提环境 * stu对象在数据库没有对应的数据 * 产生的结果: * 两条sql * 01.select 先去数据库中查询有没有id对应的数据 * 02.执行 insert */ @Test public void testMerge01(){ Student stu=new Student(1, 50, "老白"); //瞬时状态 session.merge(stu); } /** * 测试方法的前提环境 * stu对象在数据库有对应的数据 ,我们没有修改对象的属性 * 产生的结果: * 只有select语句 */ @Test public void testMerge02(){ Student stu=new Student(1, 50, "老白"); //瞬时状态 session.merge(stu); } /** * 测试方法的前提环境 * stu对象在数据库有对应的数据 ,我们修改了对象的属性 * 产生的结果: * 01.select * 02.update */ @Test public void testMerge03(){ Student stu=new Student(1, 50, "老白"); //瞬时状态 stu.setName("老白干"); session.merge(stu); } /** * 测试方法的前提环境 * stu对象在数据库有对应的数据 ,我们修改了对象的属性 * 产生的结果: * 报错 */ @Test public void testMerge04(){ Student stu=new Student(1, 50, "老白干"); //瞬时状态 session.merge(stu); //不会改变对象的状态 stu.setName("老白11111"); //瞬时状态 session.update(stu); //报错 } /** * save(): 把瞬时状态转换成 持久状态 * update():把游离状态转换成 持久状态 * saveOrUpdate(): * 会根据持久化对象的主键标识符来判断是执行save()还是update() * 如果没有oid,证明是瞬时状态,就执行save(); * 如果有oid,证明是游离状态,就执行update(); * merge: 虽然和saveOrUpdate()产生的sql结果一致! * 但是: * 01.merge不会改变对象的状态! * 02.当对象处于瞬时状态的时候,会将对象赋值一份到session的缓存中,执行save() ,产生insert语句! * 我们认为 产生了 insert语句,stu就变成了持久化对象!其实不是! * 只不过是session缓存中的对象发生了变化! */ }
/** * 第一步: *01.读取配置文件 hibernate.cfg.xml *02.创建会话工厂---》确保工厂是单例模式 *03.提供对外访问的接口 *第二步: * 在核心配置文件中 管理我们的currentSession */ public class HibernateSessionUtil { private static Configuration configuration; private static SessionFactory sessionFactory; private HibernateSessionUtil(){}//私有化构造 //在类被加载的时候 执行静态代码块 static{ configuration=new Configuration().configure(); sessionFactory=configuration.buildSessionFactory();//获取会话工厂 } //获取session的方法 public static Session getCurrentSession(){ return sessionFactory.getCurrentSession(); } }
hibernate.cfg.xml文件中新增
<!-- 配置我们的currentSession --> <property name="current_session_context_class">thread</property>
测试代码
public class SessionTest { public static void main(String[] args) { /**Configuration configuration=new Configuration().configure(); SessionFactory sessionFactory = configuration.buildSessionFactory(); Session session = sessionFactory.openSession(); //第一次 System.out.println(session.hashCode()); session = sessionFactory.openSession(); //第二次 System.out.println(session.hashCode()); hashCode不一致 */ //通过我们自己创建的回话工厂来创建currentSession Session session = HibernateSessionUtil.getCurrentSession(); //第一次 System.out.println(session.hashCode()); session = HibernateSessionUtil.getCurrentSession(); //第二次 System.out.println(session.hashCode()); //hashCode一致 } }
/** * flush和commit的区别! * * 相同点: * 两者都会同步到数据库! * * 不同点: * commit:永久保存! commit--->flush()-->缓存清理--->脏检查 * * flush: 不会永久保存! * 01.是执行缓存清理工作! * 02.会把缓存中的对象同步到数据库中!但是不会保存! * 03.确保缓存中的数据 和数据库中的数据一致! * * 缓存清理机制: * 在我们执行flush()的时候,会清理session中的数据! * 在清理缓存的的时候,会执行脏检查! * 脏检查: * 在对象被session管理的时候! * 01.session会在缓存中创建出 对象的快照保存现在对象的一个状态以及属性! (a对象) * 02.在清理缓存的时候会把现在对象的属性和(a对象)进行比对! * 03.发现现在的对象和(a对象不一致!那么现在的对象就称之为 脏对象! * 04.flush()会把这个脏对象 同步到 数据库! 但是不会保存!只是暂时的! * 05.之后commit的时候 才能永久保存数据! * */ @Test public void test01(){ //通过工具类获取session Session session = HibernateSessionUtil.getCurrentSession(); //获取事务 Transaction transaction = session.beginTransaction(); Student stu=(Student) session.get(Student.class, 1);//持久化对象 stu.setName("能改变吗?"); /** * 清理缓存 * 按照我们的理解,没有commit是不可能提交事务的!言外之意!数据库中的数据不会改变! */ System.out.println("*****************"); session.flush(); stu.setName("能改变吗2?"); System.out.println("*****************"); Student stu2=(Student) session.get(Student.class, 1); System.out.println(stu2.getName()); //已经改变了! } @Test public void test02(){ //通过工具类获取session Session session = HibernateSessionUtil.getCurrentSession(); //获取事务 Transaction transaction = session.beginTransaction(); Student stu=(Student) session.get(Student.class, 1);//持久化对象 stu.setName("能改变吗?"); System.out.println("*****************"); session.flush(); //执行 sql stu.setName("能改变吗2?"); //之后又改变了 值 System.out.println("*****************"); /** * 缓存中的OID是一致的! * get() * 01.查询session缓存 * 02.发现缓存中有数据 直接使用 * 03.所以说 stu2的name必须是 “ 能改变吗2?” */ Student stu2=(Student) session.get(Student.class, 1); System.out.println(stu2.getName()); //改变了第2次!! ! }