session.merge ()方法
session.merge ()方法
?
该方法将修改表中记录,其所需要的实体状态为脱管状态,但是注意,它并不影响调用方法前后的状态,也即该实体依然是脱管状,见例6.4。
例6.4:session.merge ()方法对状态的变化
???? public void run() {
????????? //创建UserInfo实例
????????? UserInfo userInfo = new UserInfo();
????????? //使之成为脱管状态
????????? userInfo.setId(11112);
????????? userInfo.setName("RW3");
????????? userInfo.setSex("M");
????????? //创建UserInfo实例
????????? UserInfo userInfo2 = new UserInfo();
????????? //使之成为脱管状态
????????? userInfo2.setId(11112);
????????? userInfo2.setName("RW4");
????????? userInfo2.setSex("F");
????????? //启动Session
????????? Session session = HibernateSessionFactory.currentSession();
????????? //启动事务
????????? Transaction tx = session.beginTransaction();
????????? //调用merge方法,此时UserInfo实体状态并没有被持久化
????????? session.merge(userInfo);
????????? //调用merge方法后,此时UserInfo2实体状态并没有被持久化,但是数据库中的记录被更新了.
????????? ①session.merge(userInfo2);
????????? //merge方法与update方法的差别在于针对同样的操作update方法会报错
????????? //原因在于update方法使得实体状态成为了持久化状态,而Session中不允许两个持久化实体有同样的持久化标识
????????? ②//session.update(userInfo);
????????? //session.update(userInfo2);
???????? //以下两句不会发送SQL,因为userInfo2不是持久化状态的实体
???????? ③userInfo2.setName("RW5");
????????? userInfo2.setSex("M");
????????? //提交事务
????????? tx.commit();
????????? //关闭Hibernate Session
????????? HibernateSessionFactory.closeSession();
???? }
针对该段代码将执行如下SQL语句:
Hibernate:
/* ①session.merge(userInfo2)的动作 */
select
??????? userinfo0_.id as id0_0_,
??????? userinfo0_.NAME as NAME0_0_,
??????? userinfo0_.SEX as SEX0_0_,
??????? userinfo0_.roomid as roomid0_0_
??? from
??????? userinfo userinfo0_
??? where
??????? userinfo0_.id=?
Hibernate:
/* ①session.merge(userInfo2)的动作 */
update
??????????? userinfo
??????? set
??????????? NAME=?,
??????????? SEX=?,
??????????? roomid=?
??????? where
??????????? id=?
session.merge()方法会首先发送一句select语句,去数据库端获取UserInfo持久化标识所对应的表记录;然后自动生成一个持久化状态的UserInfo实体,与脱管状态的UserInfo实体做比较是否有所改变;一旦发生了改变,才会发送update语句执行更新。而按执行顺序,若两句session.merge()方法针对同一个脱管状态的UserInfo实体,那其结果只会执行最后一个session.merge()方法所发出的update语句。
即使执行了session.merge()方法,UserInfo实体依然是脱管状态,因此③userInfo2. setName("RW5")的语句不会同步数据库中的表。