session flush测试:
session flush方法主要做了两件事:
* 清理缓存
* 执行sql
session在什么情况下执行flush
* 默认在事务提交时
* 显示的调用flush
* 在执行查询前,如:iterate
hibernate按照save(insert),update、delete顺序提交相关操作
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语句,直到commit时flush时才发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已经生成,session中existsInDatebase状态为false session.save(user);//save后,不发Hibernate: insert into
//调用flush,hibernate会清理缓存,执行sql //如果数据库的隔离级别设置为:未提交读read uncommitted,那么我们可以看到flush过的数据 //并且session中existsInDatebase状态为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的管理,修改了session中existsInDatebase状态为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的管理,修改了session中existsInDatebase状态为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:先save后evict:抛出异常: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已经生成,session中existsInDatebase状态为false session.save(user);
//将user对象从session中逐出,即session的EntityEntries属性中逐出 session.evict(user);
//无法成功提交,因为hibernate在清理缓存时,在session的insertions集合中取出user对象进行insert操作后 //需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session的entityEntries //中逐出了,所以找不到相关数据,无法更新,抛出异常 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("张三");
user.setName("王五");
User3 user3 = new User3(); user3.setId("002"); user3.setName("李四");
//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),update、delete顺序提交相关操作 tx.commit(); }catch(Exception e) { e.printStackTrace(); tx.rollback(); }finally { HibernateUtils.closeSession(session); } } |
//注意:hibernate按照save(insert),update、delete顺序提交相关操作
/** * 测试assigned主键生成策略:[注意使用的是每一张表t_user3] hibernate按照save(insert),update、delete顺序提交相关操作 * */ 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),update、delete顺序提交相关操作 //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:先save后flush再evict[注意使用的是每一张表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已经生成,session中existsInDatebase状态为false session.save(user);
//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象 //清除,并且设置session中existsInDatebase的状态为true session.flush();
//将user对象从session中逐出,即session的EntityEntries属性中逐出 session.evict(user);
//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到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的管理,修改了session中existsInDatebase状态为true //如果数据库的隔离级别设置为为提交读,那么我们可以看到save过的数据 session.save(user);
//将user对象从session中逐出,即session的EntityEntries属性中逐出 session.evict(user);
//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到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)