Hibernate学习笔记 merge()方法--update对象

 背景:
    Account 和 Group 两个对象,设置了双向的many-to-many关系,lazy=true
    不使用open session in view 模式
    不使用hibernate二级缓存

测试逻辑:
    从数据库获取一个account对象(存在两个group: 1.administrators, 2.engineers)
    修改这个对象的group信息为:1.invalid, 2.any one
    然后调用DAO的update方法(这部分代码如下所示)
   

代码 v1 只使用merge()
getHibernateTemplate().merge(po); System.out.println("/tGet obj after update in dao start ..."); Account readAccount = (Account) getHibernateTemplate().get( Account.class, po.getId()); System.out.println("/tGet obj after update in dao end ..."); System.out.println("/tIs po==readAccount ? " + (po == readAccount)); System.out.println("/tShow detai of po: " + po.toDetailString()); System.out.println("/tShow detai of readAccount: " + readAccount.toDetailString());

 

输出结果:

Hibernate: select ... from SYS_ACCOUNTS where ID=? Hibernate: select T1.ACCOUNT_ID, T1.GROUP_ID, T2.ID, T2.NAME from TB_GROUP_MEMBER T1 left outer join TB_GROUPS T2 on T1.GROUP_ID=T2.ID where T1.ACCOUNT_ID=? Get obj after update in dao start ... Get obj after update in dao end ... Is po==readAccount ? false Show detai of po: Account[27.account_27, groups[1.invalid 2.any one ]] Show detai of readAccount: Account[27.account_27, groups[2.engineers 1.administrators ]]

注意:没有update/insert/delete语句出现


代码 v2 只使用update()

getHibernateTemplate().update(po); System.out.println("/tGet obj after added in dao start ..."); Group group = (Group) getHibernateTemplate().get(Group.class, new Long(1)); System.out.println("/tGroup detai:" + group.toString()); Account readAccount = (Account) getHibernateTemplate().get( Account.class, po.getId()); System.out.println("/tGet obj after added in dao end ..."); System.out.println("/tIs po==readAccount ? " + (po == readAccount)); System.out.println("/tShow detai of po: " + po.toDetailString()); System.out.println("/tShow detai of readAccount: " + readAccount.toDetailString());

输出结果:

Get obj after added in dao start ... Hibernate: select ... from SYS_GROUPS where ID=? Group detai:Group 1. administrators Get obj after added in dao end ... Is po==readAccount ? true Show detai of po: Account[27.account_27, groups[1.invalid 2.any one ]] Show detai of readAccount: Account[27.account_27, groups[1.invalid 2.any one ]] Hibernate: update SYS_ACCOUNTS ... where ID=? Hibernate: delete from SYS_GROUP_MEMBER where ACCOUNT_ID=? Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?) Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)

注意:出现了一句update, 一句delete,两句insert


代码 v3 先执行update(),再执行merge()
getHibernateTemplate().update(po); System.out.println("/tGet obj after added in dao start ..."); Group group = (Group) getHibernateTemplate().get(Group.class, new Long(1)); System.out.println("/tGroup detai:" + group.toString()); Account readAccount = (Account) getHibernateTemplate().get( Account.class, po.getId()); System.out.println("/tGet obj after added in dao end ..."); System.out.println("/tIs po==readAccount ? " + (po == readAccount)); System.out.println("/tShow detai of po: " + po.toDetailString()); System.out.println("/tShow detai of readAccount: " + readAccount.toDetailString()); getHibernateTemplate().merge(po); Account readAgain = (Account) getHibernateTemplate().get(Account.class, po.getId()); System.out.println("/tIs readAgain == po ? " + (readAgain == po)); System.out.println("/tIs readAgain == readAccount? " + (readAgain == readAccount)); System.out.println("/tShow detai again: " + readAgain.toDetailString());

输出结果:
Get obj after added in dao start ... Hibernate: select ... from SYS_GROUPS where ID=? Group detai:Group 1. administrators Get obj after added in dao end ... Is po==readAccount ? true Show detai of po: Account[27.account_27, groups[2.any one 1.invalid ]] Show detai of readAccount: Account[27.account_27, groups[2.any one 1.invalid ]] Hibernate: select ... from SYS_GROUPS where ID=? Is readAgain == po ? true Is readAgain == readAccount? true Show detai again: Account[27.account_27, groups[1.administrators 2.engineers ]] Hibernate: update SYS_ACCOUNTS ... where ID=? Hibernate: delete from SYS_GROUP_MEMBER where ACCOUNT_ID=? Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?) Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)

注意:
    1. update/delete/insert语句依然被执行
    2. 由于代码中添加了对group(id=1)的查找,出现了两句select来查找group表,而不是一句sql通过left outer join来完成
       如果把修改前后的accout都调整为有3个group,结果不确定:
           出现过两种情况:
               一条对group表的select,另外一句select还是会使用left outer join
               三条对group表的select语句
       在代码v1中也有同样的效果,同样的调整,测试结果都是一句select group,一句left outer join,但还不能认为是100%如此,猜测跟account是否已经被关联到session有关。

结论:
    1. merge()方法,会根据根据对象是否进行了实质性修改,来决定是否执行相应的update/delete/update语句,而upate()则不会进行比较,只用给定的对象信息覆盖原有信息

参考:
    Hibernate Session.merge() javadoc
    open session in view 模式

你可能感兴趣的:(开发手记)