首页 > 代码库 > Rhythmk 学习 Hibernate 02 - Hibernate 之 瞬时状态 离线状态 持久化状态 三状态

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=new  User();
        user.setCreateTime(new Date());
        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
@Test
public void test2()
{
     
    Session session = null;
    try {
        session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        User user=new  User();
        user.setCreateTime(new Date());
        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
    public void test3()
    {
 
        Session session = null;
        try {
            session = HibernateUtil.getSessionFactory().openSession();
            session.beginTransaction();
            User user = new User();
            user.setCreateTime(new Date());
            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
        public void test4() {
 
            Session session = null;
            try {
                session = HibernateUtil.getSessionFactory().openSession();
                session.beginTransaction();
                User user = new User();
                user.setCreateTime(new Date());
                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 = new User();
            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