Rhythmk 学习 Hibernate 02 - Hibernate 之 瞬时状态 离线状态 持久化状态 三状态
by:rhythmk.cnblogs.com
1、Hibernate 三种状态:
1.1、三种定义(个人理解,不一定准确):
瞬时状态(transient): 不被session接管,且不存在数据库中的对象的状态,类似于新New一个对象
离线状态 (detached): 数据库中存在而不被session接管
持久化状态(persistent): 对象被session管理且数据库中存在此对象
1.2、 状态之间转换关系图

2 、状态转换以及Hibernate数据库执行过程详解:
2.1 瞬时状态 转换为 持久化对象
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /*      * 瞬时状态转换成序列化状态     * */        Session session = null;    try{        session = HibernateUtil.getSessionFactory().openSession();        session.beginTransaction();        User user=newUser();        user.setCreateTime(newDate());        user.setName("rhythmk");        user.setOpenId(10);        user.setType("admin");        // 此时User为瞬时对象        session.save(user);        //  通过save方法 user已经转变为持久化对象        session.getTransaction().commit();            } catch(Exception e) {        e.printStackTrace();    } finally{        if(session != null)            session.close();    }    } | 
当一个 瞬时对象被转成持久化对象后 ,只要此session会话没有关闭,该对象属性值再发生变化,session提交时候都会去对比该对象于保存时候是否被修改过。
如果被修改,则将该对象最终结果同步到数据库。
参考代码如下,进过在转变为持久化对象后进过多次调用update方法,最终生成的SQL语句依然只会有一个Insert与一条Update:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | @Testpublicvoidtest2(){        Session session = null;    try{        session = HibernateUtil.getSessionFactory().openSession();        session.beginTransaction();        User user=newUser();        user.setCreateTime(newDate());        user.setName("rhythmk");        user.setOpenId(10);        user.setType("admin");        // 此时User为瞬时对象        session.save(user);        //  通过save方法 user已经转变为持久化对象                user.setName("updatename");        session.update(user);                user.setName("updatename2");        session.update(user);                user.setName("updatename3");        session.update(user);                        session.getTransaction().commit();            } catch(Exception e) {        e.printStackTrace();    } finally{        if(session != null)            session.close();    }    } | 
输出:
Hibernate: insert into user (openId, type, name, createTime) values (?, ?, ?, ?)
Hibernate: update user set openId=?, type=?, name=?, createTime=? where userId=?
2.2 、当一个离线对象 通过session.delete方法转换成瞬时对象,此时瞬时对象的值发生变化将不生成同步SQL
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | @Test    publicvoidtest3()     {        Session session = null;        try{            session = HibernateUtil.getSessionFactory().openSession();            session.beginTransaction();            User user = newUser();            user.setCreateTime(newDate());            user.setName("rhythmk");            user.setOpenId(10);            user.setType("admin");            user.setUserId(12);            session.delete(user);//此时 user成为瞬时状态 以后其属性值的改变不会再生成SQL语句                        user.setName("updatename");                        user.setName("updatename3");                session.getTransaction().commit();        } catch(Exception e) {            e.printStackTrace();        } finally{            if(session != null)                session.close();        }    }                | 
输出:
Hibernate: delete from user where userId=?
当一个离线状态转换成瞬时状态时,改对象属性值发生变化尽管设定了改对象主键值,再调用session.save方法生成的Insert语句将不关注此主键ID
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @Test        publicvoidtest4() {            Session session = null;            try{                session = HibernateUtil.getSessionFactory().openSession();                session.beginTransaction();                User user = newUser();                user.setCreateTime(newDate());                user.setName("rhythmk");                user.setOpenId(9);                user.setType("admin");                user.setUserId(9);                session.delete(user);                user.setName("updatename");                session.save(user);                user.setName("updatename3");                session.update(user);                user.setName("updatename32");                session.update(user);                user.setName("updatename33");                session.update(user);                session.getTransaction().commit();            } catch(Exception e) {                e.printStackTrace();            } finally{                if(session != null)                    session.close();            }    } | 
输出:
Hibernate: delete from user where 
userId=?
Hibernate: insert 
into user (openId, type, name, createTime) values (?, ?, ?, ?)
Hibernate: update user set openId=?, type=?, 
name=?, createTime=? where userId=?
参考方法:
session.saveOrupdate(object)
根据object对象的主键ID判断如果,数据库存在记录则更新,否则添加
session.merge(object)
如果session回话中已经存在某主键ID的对象,如果此时再添加一个同主键的新对象进如回话状态,将出现异常 ,
此情况则可以调用merge方法对session回话中以存在对象进行覆盖:
如:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | session = HibernateUtil.openSession();            session.beginTransaction();            //u1已经是持久化状态            User u1 = (User)session.load(User.class, 3);            System.out.println(u1.getUsername());            //u2是离线状态            User u2 = newUser();            u2.setId(3);            u2.setPassword("123456789");            //此时u2将会变成持久化状态,在session的缓存中就存在了两份同样的对象,在session中不能存在两份拷贝,否则会抛出异常//            session.saveOrUpdate(u2);            //merge方法会判断session中是否已经存在同一个对象,如果存在就将两个对象合并            session.merge(u2);            //最佳实践:merge一般不用            session.getTransaction().commit(); | 
参考:
http://www.cnblogs.com/xiaoluo501395377/p/3380270.html
Rhythmk 学习 Hibernate 02 - Hibernate 之 瞬时状态 离线状态 持久化状态 三状态,码迷,mamicode.com
