zoukankan      html  css  js  c++  java
  • 【Hibernate步步为营】--核心对象+持久对象全析(三)

           上篇文章讨论了Hibernate持久对象的生命周期,在整个生命周期中一个对象会经历三个状态,三种状态的转换过程在开发过程中是可控的。并且是通过用法来控制它们的转化过程。详细的转化过程今天就来着重讨论下。


    二、状态转化方法


           前面说到对象之间的转化过程是通过用法来实现的,这些方法是非常重要的。先看张图

         上面这张图在三篇文章中都实用到,它具体描写叙述了持久对象三种状态的转换过程及具体的转化方法。另外还有垃圾回收器,对象在瞬态和脱管状态下假设长时间不适用将会在某一时刻被Java回收器回收,消亡。


      1、对象直接进入Persistent状态         

        

         1.1 get方法

             从数据库中获取一行信息。并将该信息同步到创建的对象中,该方法返回一个Object对象,假设没有查询到内容则返回null。以下的实例通过採用Session的get方法来获取一个对象。并将对象转换为实例。

    public void testGet1(){
    	Session session=null;
    	Transaction tx = null;
    	try{
    		session=HibernateUtils.getSession();
    		//开启事务
    		tx= session.beginTransaction();
    		//get载入上来的对象为持久对象
    		//运行get会立即发出查询语句。假设不存在会返回null
    		User user=(User)session.get(User.class,"ff80808145bc28cc0145bc28ce020002");
    		System.out.println(user.getName());
    		
    		//persistent状态
    		//persistent状态的对象,当对象的属性发生改变的时候
    		//Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
    		user.setName("赵柳");
    		
    		session.getTransaction().commit();
    	}catch(Exception e){
    		e.printStackTrace();
    		if(tx != null){
    			tx.rollback();
    		}
    	}finally{
    		HibernateUtils.closeSession(session);
    	}	
    }
    

            设置断点。获取User对象。

                

                  


           获取到了该对象,通过强制转换后得到了一个user对象。程序中加入了setName方法,也就是说会更新数据库中的名称。运行完毕后检查数据库,例如以下图更新结果。                       

       1.2 load方法

         功能类似于get方法,也是从数据库中获取数据并同步到对象中,该方法支持lazy是一种懒汉操作,它返回的是一个持久化的Object对象或者一个代理,所以须要进行转化。

    public void testLoad1(){
    	Session session=null;
    	try{
    		session=HibernateUtils.getSession();
    		//不会立即查询语句,由于load支持lazy(延迟载入/懒载入)
    		//什么教lazy?仅仅有真正使用这个对象的时候。再创建,对于Hibernate来说
    		//才真正发出查询语句,主要为了提高性能,lazy是Hibernate中很重要的特性
    		//Hibernate的lazy是怎样实现的?採用代理对象实现。代理对象主要採用的是CGLIB库生成的
    		//而不是JDK的动态代理。由于JDK的动态代理仅仅能对实现了借口的类生成代理,CGLIB能够对类生成
    		//代理。它採用的是继承方式
    		User user=(User)session.load(User.class,"8a1b653745bcc7b50145bcc7b7140001");
    		System.out.println(user.getName());
    		
    		//persistent状态
    		//persistent状态的对象,当对象的属性发生改变的时候
    		//Hibernate在清理缓存(脏数据检查)的时候。会和数据库同步
    		user.setName("zhaoliu");
    		
    		session.getTransaction().commit();
    	}catch(Exception e){
    		e.printStackTrace();
    	}finally{
    		HibernateUtils.closeSession(session);
    	}	
    }
    

            查询获取该User对象例如以下图:

              
            分析上图,获取的User对象并不完整。或者说并没有常见一个User对象。更是一种代理,它使用了CGLIB来预载入对象,仅仅有在使用该对象时才真正创建。


        1.3 Get Vs load


           get和load方法非常重要。在面试Hibernate时常常会考到,以下对照下两者。


           同样点:(1)功能同样,将关系数据转化为对象;

                           (2)用法相同。相同须要制定两个參数
           不同点:(1)load方法支持lazy操作。预载入对象。在使用时才创建。get是直接将关系数据转化为对象;

                           (2)load载入对象假设不存在会抛出objectNotFoundException异常,get假设没有获取数据会返回null。


      2、手动构造detached对象

            想要获取对象还有第二种方法。它差别于get与load方法。是一种手动获取的方法,首先常见一个对象,然后通过制定id的方式获取该对象的数据。方法例如以下:

    public void testUer(){
    	Session session=null;
    	try{
    		
    		session=HibernateUtils.getSession();
    		session.beginTransaction();
    		
    		//手动构造detached对象
    		User user=new User();
    		user.setId("8a1b653745bcc7b50145bcc7b7140001");
    		
    		//persistent状态
    		//persistent状态的对象,当对象的属性发生改变的时候
    		//Hibernate在清理缓存(脏数据检查)的时候。会和数据库同步
    		session.getTransaction().commit();
    	}catch(Exception e){
    		e.printStackTrace();
    	}finally{
    		HibernateUtils.closeSession(session);
    	}	
    }
    

            查看获取的结果图:

             
                        
           分析结果图,代码中使用了setId方法为该对象制定了id号。在制定id号后就行对该对象进行操作,在事务提交后同步到数据库中,採用了手动指定,手动指定了对象的信息。


        2.1 Delete方法

           删除数据库中指定的对象,在删除前必须将对象转化到Persistent状态,能够使用get、load或者手动的方法指定对象,用法例如以下代码:

    session=HibernateUtils.getSession();
    session.beginTransaction();
    User user=(User)session.load(User.class,"8a1b653745bcc6d50145bcc6d67a0001");
    //建议採用此种方式删除,先载入再删除
    session.delete(user);
    

       2.2 Update

          更新数据。该方法会改动数据库中的数据。在使用的时候会出现量中情况。更新数据库某个字段值或者更新数据库的整行值

         2.2.1  更新某个字段值

          假设仅仅想要更新某个字段的值,在update前。须要使用load或者get方法使对象转化为persistent状态代码例如以下:

    //获取session对象
    session=HibernateUtils.getSession();
    //开启事务
    session.beginTransaction();
    //或者能够使用另外的方法开启
    //session.getTransaction().begin();
    
    //载入获取User对象
    //方法一:使用load方法
    //User user=(User)session.load(User.class, "8a1b653745bcc7b50145bcc7b7140001");
    //方法二:手动获取
    User user=new User();
    user.setId("8a1b653745bcc7b50145bcc7b7140001");
    
    //更新姓名
    user.setName("zhangsan");
    session.update(user);
    session.getTransaction().commit();
    

          2.2.2 更新整行                        

          想要更新整行的数据,能够採用手动将状态转换到detached状态。手动指定对象的id值,代码例如以下:

    //获取session对象
    session=HibernateUtils.getSession();
    //开启事务
    session.beginTransaction();
    //或者能够使用另外的方法开启
    //session.getTransaction().begin();
    
    //手动获取
    User user=new User();
    user.setId("8a1b653745bcc7b50145bcc7b7140001");
    
    //更新姓名
    user.setName("zhangsan");
    session.update(user);
    session.getTransaction().commit();
    

           查看更新结果:

           
          分析更新结果,它事实上更新了数据库的整行数据,这样的更新操作有太多的不确定因素,不建议使用。


       2.3 save方法


            插入数据。

    在运行save方法时会调用数据库的insert语句,向数据库中加入新的一行。save后的对象会转化为持久态,在此状态下的对象可以再次更新对象,在最后提交事务时会同更改更新到数据库。例如以下:

    public void testSave2(){
    	Session session=null;
    	Transaction tx = null;
    	try{
    		session=HibernateUtils.getSession();
    		//开启事务
    		tx= session.beginTransaction();
    		
    		//Transient状态
    		User user=new User();
    		user.setName("zhangsi");
    		user.setPassword("123");
    		user.setCreateTime(new Date());
    		user.setExpireTime(new Date());
    		
    		//persistent状态
    		//persistent状态的对象。当对象的属性发生改变的时候
    		//Hibernate在清理缓存(脏数据检查)的时候。会和数据库同步
    		session.save(user);
    		user.setName("lisi");
    		
    		tx.commit();
    		
    	}catch(Exception e){
    		e.printStackTrace();
    		if(tx != null){
    			tx.rollback();
    		}
    	}finally{
    		HibernateUtils.closeSession(session);
    	}
    	
    	//detached状态
    }
    

    查看上例执行结果视图:

       
            分析结果:session在提交事务的时候事实上做了两部的操作,结合代码中的更新过程,首先是新增了一个User对象,之后运行了save操作,它会调用insert语句。然后在代码中做了一个setName的操作,又一次改动了名称。但这时还没有同步到数据库中而是在内存中。这时就会有两种状态。我们称此时的数据位脏数据,最后提交事务的时候更新到数据库中。


    结语

           本文针对持久对象的转化方法展开了具体的讨论。一个对象在整个生命周期中有三种状态。文章讨论至此。核心对象和持久对象的讨论已经完毕。核心对象构成了Hibernate的内部执行机制,持久对象是关系模型和对象模型进行转化的核心。



  • 相关阅读:
    第四次作业:个人项目-小学四则运算 “软件”之初版
    随笔 | 阅读《构建之法》1-5章感想
    随笔 | 分布式版本控制系统Git的安装与使用
    随笔 | 对软件工程的一些感想
    为什么加载 JavaScript 使用 "src",CSS 使用 "href"?有其含义还是历史语法遗留?
    webstrom 添加一键open in browser
    sublime 代码段
    二.sublime配置 sublimecondeintel 分号后不要提示
    一.sublime配置 sublime 新建文档 默认html
    chrome使用
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6858098.html
Copyright © 2011-2022 走看看