09hibernate_session_flush

session flush测试:

 

session flush方法主要做了两件事:

    * 清理缓存

    * 执行sql

   

session在什么情况下执行flush

    * 默认在事务提交时

    * 显示的调用flush

    * 在执行查询前,如:iterate

   

hibernate按照save(insert),updatedelete顺序提交相关操作

 

 

uuid:create table t_user1 (user_id varchar(32) not null, name varchar(20) not null unique, password varchar(10) not null, create_time datetime, expire_time datetime, primary key (user_id))

 

native:create table t_user2 (user_id integer not null auto_increment, name varchar(20) not null unique, password varchar(10) not null, createtime datetime, expiretime datetime, primary key (user_id))

 

assigned:create table t_user3 (user_id varchar(32) not null, name varchar(255), password varchar(255), create_time datetime, expire_time datetime, primary key (user_id))

 

 

 

 

 

    /**

     * 测试uuid主键生成策略1完成save后不会发出insert语句,直到commitflush时才发insert语句

     */

    publicvoid testSave1() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User1 user = new User1();

           user.setName("李四3");

           user.setPassword("123");

           user.setCreateTime(new Date());

           user.setExpireTime(new Date());

          

           //因为user的主键生成侧路采用的是uuid,所以调用完成save,只是将user纳入到了session的管理

           //不会发出insert语句,但是id已经生成,sessionexistsInDatebase状态为false

           session.save(user);//save,不发Hibernate: insert into

          

           //调用flushhibernate会清理缓存,执行sql

           //如果数据库的隔离级别设置为:未提交读read uncommitted,那么我们可以看到flush过的数据

           //并且sessionexistsInDatebase状态为true

           session.flush();//Hibernate: insert into

          

           //提交事务

           //commit后数据是无法回滚的

           tx.commit();//默认情况下commit操作会先执行flush清理缓存,所以不用显示的调用flush

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }

session.flush();//flush后:发Hibernate: insert into

Hibernate: insert into t_user1 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

 

 

没有提交事务前:我们来看一下数据库中有没有记录:

 

mysql> select @@tx_isolation;

+-----------------+

| @@tx_isolation  |

+-----------------+

| REPEATABLE-READ |

+-----------------+

1 row in set (0.03 sec)

 

mysql> select * from t_user1;

Empty set (0.06 sec)

 

mysql> set  transaction isolation level read uncommitted;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select @@tx_isolation;

+------------------+

| @@tx_isolation   |

+------------------+

| READ-UNCOMMITTED |

+------------------+

1 row in set (0.00 sec)

 

mysql> select * from t_user1;

+----------------------------------+-------+----------+---------------------+---------------------+

| user_id                          | name  | password | create_time         | expire_time         |

+----------------------------------+-------+----------+---------------------+---------------------+

| 402881e738eb64e20138eb65f3990001 | 李四3 | 123      | 2012-08-03 15:31:55 | 2012-08-03 15:32:02 |

+----------------------------------+-------+----------+---------------------+---------------------+

1 row in set (0.00 sec)

 

/**

     * 测试native主键生成策略:完成save后马上发出insert语句

     */

    publicvoid testSave2() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User2 user = new User2();

           user.setName("猪八戒");

           user.setPassword("123");

           user.setCreateTime(new Date());

           user.setExpireTime(new Date());

          

           //因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id

           //纳入了session的管理,修改了sessionexistsInDatebase状态为true

           //如果数据库的隔离级别设置为:未提交读read uncommitted,那么我们可以看到save过的数据

           session.save(user);//save,马上发Hibernate: insert into

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }

 

 

save后,将执行insert语句,返回有数据库生成的id

           //纳入了session的管理,修改了sessionexistsInDatebase状态为true

 

 

 

mysql> select * from t_user2;

+---------+--------+----------+---------------------+---------------------+

| user_id | name   | password | createtime          | expiretime          |

+---------+--------+----------+---------------------+---------------------+

|       1 | 猪八戒 | 123      | 2012-08-03 16:09:44 | 2012-08-03 16:09:55 |

+---------+--------+----------+---------------------+---------------------+

1 row in set (0.00 sec)

 

/**

     * 测试uuid主键生成策略2:先saveevict抛出异常:org.hibernate.AssertionFailure: possible nonthreadsafe access to session

 

     */

    publicvoid testSave3() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User1 user = new User1();

           user.setName("王五");

           user.setPassword("123");

           user.setCreateTime(new Date());

           user.setExpireTime(new Date());

          

           //因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理

           //不会发出insert语句,但是id已经生成,sessionexistsInDatebase状态为false

           session.save(user);

          

           //user对象从session中逐出,即sessionEntityEntries属性中逐出

           session.evict(user);

          

           //无法成功提交,因为hibernate在清理缓存时,在sessioninsertions集合中取出user对象进行insert操作后

           //需要更新entityEntries属性中的existsInDatabasetrue,而我们采用evict已经将usersessionentityEntries

           //中逐出了,所以找不到相关数据,无法更新,抛出异常

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }

 

 

Save后:

 

 

 

Evict后:

 

 

org.hibernate.AssertionFailure: possible nonthreadsafe access to session

/**

     * 测试assigned主键生成策略:[注意使用的是每一张表t_user3]

     *

     */

    publicvoid testSave6() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User3 user = new User3();

           user.setId("001");

           user.setName("张三");

          

           session.save(user);[U1] 

          

           user.setName("王五");

           session.update[U2] (user);

          

           User3 user3 = new User3();

           user3.setId("002");

           user3.setName("李四");

           session.save[U3] (user3);

          

           //Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

           //Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

           //Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?

           //hibernate按照save(insert),updatedelete顺序提交相关操作

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }  

//注意:hibernate按照save(insert),updatedelete顺序提交相关操作

/**

     * 测试assigned主键生成策略:[注意使用的是每一张表t_user3] hibernate按照save(insert),updatedelete顺序提交相关操作

     *

     */

    publicvoid testSave6() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User3 user = new User3();

           user.setId("001");

           user.setName("张三");

          

           session.save(user);

          

           user.setName("王五");

           session.update(user);

          

           User3 user3 = new User3();

           user3.setId("002");

           user3.setName("李四");

           session.save(user3);

           //注意:hibernate按照save(insert),updatedelete顺序提交相关操作

           //Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

           //Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

           //Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?

          

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }  

Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?

 

mysql> select * from t_user3;

+---------+------+----------+-------------+-------------+

| user_id | name | password | create_time | expire_time |

+---------+------+----------+-------------+-------------+

| 001     | 王五 | NULL     | NULL        | NULL        |

| 002     | 李四 | NULL     | NULL        | NULL        |

+---------+------+----------+-------------+-------------+

2 rows in set (0.00 sec)

/**

     * 测试assigned主键生成策略:[注意使用的是每一张表t_user3]显示调用flush后,sql会按照我们的意愿执行

     *

     */

    publicvoid testSave7() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User3 user = new User3();

           user.setId("003");

           user.setName("张三");

          

           session.save(user);

          

           user.setName("王五");

           session.update(user);

           //因为我们在session.udpate(user)后执行了flush,所以在清理缓存时执行flush前的sql不会生成

           //sql会按照我们的意愿执行

           session.flush();

          

           User3 user3 = new User3();

           user3.setId("004");

           user3.setName("李四");

           session.save(user3);

          

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }     

}

//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

//Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?

//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

 

Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?

Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)

 

mysql> select * from t_user3;

+---------+------+----------+-------------+-------------+

| user_id | name | password | create_time | expire_time |

+---------+------+----------+-------------+-------------+

| 001     | 王五 | NULL     | NULL        | NULL        |

| 002     | 李四 | NULL     | NULL        | NULL        |

| 003     | 王五 | NULL     | NULL        | NULL        |

| 004     | 李四 | NULL     | NULL        | NULL        |

+---------+------+----------+-------------+-------------+

4 rows in set (0.00 sec)

 

不明白以下两个程序:

/**

     * 测试uuid主键生成策略3:saveflushevict[注意使用的是每一张表t_user1]

     */

    publicvoid testSave4() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User1 user = new User1();

           user.setName("王五");

           user.setPassword("123");

           user.setCreateTime(new Date());

           user.setExpireTime(new Date());

          

           //因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理

           //不会发出insert语句,但是id已经生成,sessionexistsInDatebase状态为false

           session.save(user);

          

           //flushhibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象

           //清除,并且设置sessionexistsInDatebase的状态为true

           session.flush();

          

           //user对象从session中逐出,即sessionEntityEntries属性中逐出

           session.evict(user);

          

           //可以成功提交,因为hibernate在清理缓存时,在sessioninsertions集合中无法找到user对象

           //所以就不会发出insert语句[U4] ,也不会更新session中的existsInDatabase的状态

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }

   

   

 

mysql> select * from t_user1;

+----------------------------------+---------+----------+---------------------+---------------------+

| user_id                          | name    | password | create_time         | expire_time         |

+----------------------------------+---------+----------+---------------------+---------------------+

| 402881e738ebdb9f0138ebdcab230001 | 王五    | 123      | 2012-08-03 17:41:34 | 2012-08-03 17:41:35 |

| 402881e738ebe0960138ebe098920001 | 王五1   | 123      | 2012-08-03 17:46:01 | 2012-08-03 17:46:01 |

| 402881e738ebe5dc0138ebe5ddc10001 | 王五11  | 123      | 2012-08-03 17:51:46 | 2012-08-03 17:51:46 |

| 402881e738ebe6d60138ebe6d7b10001 | 王五111 | 123      | 2012-08-03 17:52:50 | 2012-08-03 17:52:50 |

+----------------------------------+---------+----------+---------------------+---------------------+

5 rows in set (0.00 sec)

 

/**

     * 测试native主键生成策略2:[注意使用的是每一张表t_user2]

     */

    publicvoid testSave5() {

       Session session = null;

       Transaction tx = null;

       try {

           session = HibernateUtils.getSession();

           tx = session.beginTransaction();

 

           User2 user = new User2();

           user.setName("张三11");

           user.setPassword("123");

           user.setCreateTime(new Date());

           user.setExpireTime(new Date());

          

           //因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id

           //纳入了session的管理,修改了sessionexistsInDatebase状态为true

           //如果数据库的隔离级别设置为为提交读,那么我们可以看到save过的数据

           session.save(user);

          

           //user对象从session中逐出,即sessionEntityEntries属性中逐出

           session.evict(user);

          

           //可以成功提交,因为hibernate在清理缓存时,在sessioninsertions集合中无法找到user对象

           //所以就不会发出[U5] insert语句,也不会更新session中的existsInDatabase的状态

           tx.commit();

       }catch(Exception e) {

           e.printStackTrace();

           tx.rollback();

       }finally {

           HibernateUtils.closeSession(session);

       }

    }

 

mysql> select * from t_user2;

+---------+---------+----------+---------------------+---------------------+

| user_id | name    | password | createtime          | expiretime          |

+---------+---------+----------+---------------------+---------------------+

|       1 | 猪八戒  | 123      | 2012-08-03 16:09:44 | 2012-08-03 16:09:55 |

|       2 | 猪八戒2 | 123      | 2012-08-03 16:22:08 | 2012-08-03 16:22:08 |

|       3 | 张三11  | 123      | 2012-08-03 17:48:34 | 2012-08-03 17:48:35 |

|       4 | 张三111 | 123      | 2012-08-03 17:51:23 | 2012-08-03 17:51:23 |

|       5 | 张三1   | 123      | 2012-08-03 17:53:58 | 2012-08-03 17:53:58 |

+---------+---------+----------+---------------------+---------------------+

5 rows in set (0.00 sec)


 

 

原文地址:https://www.cnblogs.com/alamps/p/2622101.html