Hibernate中merge()方法解析
本文教你簡(jiǎn)單學(xué)會(huì)Hibernate merge() add操作,具體的實(shí)現(xiàn)過程如下:
背景:
◆Account 和 Group 兩個(gè)對(duì)象,設(shè)置了雙向的many-to-many關(guān)系,lazy=true
◆不使用open session in view 模式
◆不使用hibernate二級(jí)緩
◆考慮web應(yīng)用場(chǎng)景,設(shè)置account和group關(guān)聯(lián)時(shí),只需要group和account的id就夠了。
◆數(shù)據(jù)庫(kù)中存在兩個(gè)group: 1.administrators, 2.engineers而po對(duì)象中,group信息為:1.invalid, 2.any one
代碼A:
- Account account = (Account) getHibernateTemplate().merge(po);
- Long id = account.getId();
- System.out.println("\tGet obj after added in dao start ...");
- Account readAccount = (Account) getHibernateTemplate().get(
- Account.class, id);
- 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());
其中,為po設(shè)置了兩個(gè)group 輸出結(jié)果:
- Hibernate: select ... from SYS_GROUPS where ID=?
- Hibernate: select ... from SYS_GROUPS where ID=?
- Get obj after added in dao start ...
- Get obj after added in dao end ...
- Is po==readAccount ? false
- Show detai of po: Account[0.account_22, groups[2.any one 1.invalid ]]
- Show detai of readAccount: Account[22.account_22, groups[2.engineers 1.administrators ]]
- Hibernate: insert into SYS_ACCOUNTS (...) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)
- Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)
代碼B:
- Long id = (Long) getHibernateTemplate().save(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, id);
- 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(readAccount);
- Account readAgain = (Account) getHibernateTemplate().get(Account.class,
- id);
- System.out.println("\tIs po==readAgain ? " + (readAgain == po));
- System.out.println("\tIs readAgain== readAccount? "
- + (readAgain == readAccount));
- System.out.println("\tShow detai again: " + readAgain.toDetailString());
輸出結(jié)果:
- 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: select ... from SYS_GROUPS where ID=?
- Is po==readAgain ? true
- Is readAgain== readAccount? true
- Show detai again: Account[27.account_27, groups[1.administrators 2.engineers ]]
- Hibernate: insert into SYS_ACCOUNTS (...) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)
- Hibernate: insert into SYS_GROUP_MEMBER (ACCOUNT_ID, GROUP_ID) values (?, ?)
結(jié)論:
1. Hibernate merge()方法會(huì)導(dǎo)致執(zhí)行查詢group對(duì)象的select語(yǔ)句,在調(diào)用merge()命令時(shí)立即執(zhí)行(條件:目標(biāo)group對(duì)象沒有被緩存)
2. 無(wú)論Hibernate merge()或save()方法,insert語(yǔ)句都在***執(zhí)行,并非在調(diào)用相應(yīng)命令時(shí)立即執(zhí)行
3. 直接調(diào)用merge()方法時(shí),會(huì)返回一個(gè)新的instance,原po保持不變
4. save()之后,po中的group對(duì)象并沒有被關(guān)聯(lián)到session,因此查詢group(id=1)會(huì)觸發(fā)select語(yǔ)句
5. save()之后,po對(duì)象被關(guān)聯(lián)到session,再次查詢,不會(huì)觸發(fā)select語(yǔ)句,并且不會(huì)檢查group對(duì)象是否被關(guān)聯(lián)到session
6. save()之后再調(diào)用merge,返回的是同一個(gè)instance,但其關(guān)聯(lián)group對(duì)象會(huì)被更新
如果在add一個(gè)對(duì)象之后,如果存在關(guān)聯(lián)對(duì)象,并且需要再同一個(gè)hibernate session中進(jìn)行回顯,則建議使用Hibernate merge()方法。
參考:
Hibernate Session.merge() javadoc
open session in view 模式
【編輯推薦】