zoukankan      html  css  js  c++  java
  • [Hibernate 2]session的三种状态

    一、Session的特点和获取

    特点:

    Session不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connection和Transaction之间。
     Session也称为持久化管理器,因为它是与持久化有关的操作接口。
     Session通过SessionFactory打开,在所有的工作完成后,需要关闭。
    它与Web层的HttpSession没有任何关系。

    获取:

    <span style="font-family:KaiTi_GB2312;font-size:18px;">//默认读取hibernate.cfg.xml文件
    Configuration cfg=new Configuration().configure();
    //建立SessionFactory
    SessionFactory factory=cfg.buildSessionFactory();
    //取得session
    Session session=null;
    session=factory.openSession();</span>

    二、Session的生命周期


    在session的生命周期里面,我们可以发现,session主要有三个状态:Transient(瞬时)、Persistent(持久化)、Detached(脱管)

    2.1,瞬时(Transient )

    使用new 操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。 

    2.2,持久化(Persist )

    持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。

    2.3,脱管(Detached )

    Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。


    三、实例解析session的三大状态

    <span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="white-space:pre">	</span>public void testSave2(){
    		Session session=null;
    		Transaction tx=null;
    		try {
    			session=HibernateUtils.getSession();
    			tx=session.beginTransaction();
    			
    			//Transient状态
    			User user=new User();
    			user.setName("张三");
    			user.setPassword("123");
    			user.setCreateTime(new Date());
    			user.setExpireTime(new Date());
    			
    			//以上user就是Transient(瞬时状态),表示没有被session管理并且数据库中没有
                //执行save之后,被session所管理,而且,数据库中已经存在,此时就是Persistent状态
    			session.save(user);
    			//此时user是持久化状态,已经被session所管理,当再次提交时,会把session中的对象和目前的对象进行比较
                //如果两个对象中的值不一致就会继续发出相应的sql语句
    			user.setName("王五");
    			
    			//可以显示的调用update方法,因为此时为持久状态,调用update没有什么意义,但是
    			session.update(user);
    			//此时会发出2条sql,一条用户做插入,一条用来做更新
    			tx.commit();
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    			if(tx!=null){
    				tx.rollback();
    			}
    		}finally{
    			HibernateUtils.closeSession(session);
    		}
    		//detached状态
    	}</span>
    控制台打印的sql语句:

    Hibernate: insert into User (name, password, createTime, expireTime, id) values (?, ?, ?, ?, ?)
    Hibernate: update User set name=?, password=?, createTime=?, expireTime=? where id=?

    <span style="font-family:KaiTi_GB2312;font-size:18px;">	public void testSave3(){
    		Session session=null;
    		Transaction tx=null;
    		User user=null;
    		try {
    			session=HibernateUtils.getSession();
    			tx=session.beginTransaction();
    			
    			//Transient状态
    			user=new User();
    			user.setName("Angel");
    			user.setPassword("123");
    			user.setCreateTime(new Date());
    			user.setExpireTime(new Date());
    			
    			//Persistent状态
    			session.save(user);
    			tx.commit();
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    			if(tx!=null){
    				tx.rollback();
    			}
    		}finally{
    			HibernateUtils.closeSession(session);
    		}
    		//detached状态
    		user.setName("soffe");
    		try {
    			session=HibernateUtils.getSession();
    			session.beginTransaction();
    			
    			//将detached状态的对象重新纳入session管理
    			//此时将变为persistent状态的对象
    			//persistent状态的对象,在清理缓存是会和数据库同步
    			session.update(user);
    			session.getTransaction().commit();
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    			session.getTransaction().rollback();
    		}finally{
    			HibernateUtils.closeSession(session);
    		}
    	}</span>

    要将一个脱管对象变为一个持久化对象,应该调用update方法,而不是save方法。如果调用save方法,那么Hibernate会根据其id生成策略执行insert语句,向数据库里插入一条数据。


    四、总结

    当一个对象处于持久化状态的时候,如果对该对象多次调用update、save方法,或者多次修改,hibernate都不会执行相应的sql语句。当事务提交时,hibernate会将当前对象与之前保存在session中的对象进行对比,如果不相同,就执行update语句,否则不执行。

    状态/存在位置 内存 缓存 数据库
    瞬时状态
    持久状态
    脱管状态


  • 相关阅读:
    Linkerd 2.10(Step by Step)—将 GitOps 与 Linkerd 和 Argo CD 结合使用
    Linkerd 2.10(Step by Step)—多集群通信
    Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置
    Linkerd 2.10(Step by Step)—控制平面调试端点
    Linkerd 2.10(Step by Step)—配置超时
    Linkerd 2.10(Step by Step)—配置重试
    Linkerd 2.10(Step by Step)—配置代理并发
    本地正常运行,线上环境诡异异常原因集合
    Need to invoke method 'xxx' declared on target class 'yyy', but not found in any interface(s) of the exposed proxy type
    alpine 安装常用命令
  • 原文地址:https://www.cnblogs.com/hhx626/p/6010321.html
Copyright © 2011-2022 走看看