簡述Hibernate中加載并存儲對象
本文主要向大家介紹Hibernate加載并存儲對象,下面我們用一個例子來加以說明。讓你更輕松的了解Hibernate中加載并存儲對象的好處。
首先要編寫一個帶有main()方法的EventManager類:
- package events;
- import org.hibernate.Session;
- import java.util.Date;
- import util.HibernateUtil;
- public class EventManager {
- public static void main(String[] args) {
- EventManager mgr = new EventManager();
- if (args[0].equals("store")) {
- mgr.createAndStoreEvent("My Event", new Date());
- }
- HibernateUtil.getSessionFactory().close();
- }
- private void createAndStoreEvent(String title, Date theDate) {
- Session session = HibernateUtil.getSessionFactory().getCurrentSession();
- session.beginTransaction();
- Event theEvent = new Event();
- theEvent.setTitle(title);
- theEvent.setDate(theDate);
- session.save(theEvent);
- session.getTransaction().commit();
- }
- }
我們創(chuàng)建了個新的Event對象并把它傳遞給Hibernate?,F(xiàn)在Hibernate負責(zé)與SQL打交道,并把INSERT命令傳給數(shù)據(jù)庫。在運行之前,讓我們看一下處理Session和Transaction的代碼。
一個Session就是個單一的工作單元。我們暫時讓事情簡單一些,并假設(shè)HibernateSession和數(shù)據(jù)庫事務(wù)是一一對應(yīng)的。為了讓我們的代碼從底層的事務(wù)系統(tǒng)中脫離出來(此例中是JDBC,但也可能是JTA),我們使用Hibernate Session中的Transaction API。
sessionFactory.getCurrentSession()是干什么的呢?首先,只要你持有SessionFactory(幸虧我們有HibernateUtil,可以隨時獲得),大可在任何時候、任何地點調(diào)用這個方法。getCurrentSession()方法總會返回“當(dāng)前的”工作單元。記得我們在hibernate.cfg.xml中把這一配置選項調(diào)整為"thread"了嗎?因此,因此,當(dāng)前工作單元被綁定到當(dāng)前執(zhí)行我們應(yīng)用程序的Java線程。但是,這并非是完全準(zhǔn)確的,你還得考慮工作單元的生命周期范圍 (scope),它何時開始,又何時結(jié)束.
Session在第一次被使用的時候,即第一次調(diào)用getCurrentSession()的時候,其生命周期就開始。然后它被Hibernate綁定到當(dāng)前線程。當(dāng)事務(wù)結(jié)束的時候,不管是提交還是回滾,Hibernate會自動把Session從當(dāng)前線程剝離,并且關(guān)閉它。假若你再次調(diào)用getCurrentSession(),你會得到一個新的Session,并且開始一個新的工作單元。這種線程綁定(thread-bound)的編程模型(model)是使用Hibernate的最廣泛的方式,因為它支持對你的代碼靈活分層(事務(wù)劃分可以和你的數(shù)據(jù)訪問代碼分離開來,在本教程的后面部分就會這么做)。
和工作單元的生命周期這個話題相關(guān),Hibernate Session是否被應(yīng)該用來執(zhí)行多次數(shù)據(jù)庫操作?上面的例子對每一次操作使用了一個Session,這完全是巧合,這個例子不是很復(fù)雜,無法展示其他方式。Hibernate Session的生命周期可以很靈活,但是你絕不要把你的應(yīng)用程序設(shè)計成為每一次數(shù)據(jù)庫操作都用一個新的Hibernate Session。因此就算下面的例子(它們都很簡單)中你可以看到這種用法,記住每次操作一個session是一個反模式。在本教程的后面會展示一個真正的(web)程序。
關(guān)于事務(wù)處理及事務(wù)邊界界定的詳細信息,請參看第 11 章 事務(wù)和并發(fā)。在上面的例子中,我們也忽略了所有的錯誤與回滾的處理。
為第一次運行我們的程序,我們得在Ant的build文件中增加一個可以調(diào)用得到的target。
- <target name="run" depends="compile">
- <java fork="true" classname="events.EventManager" classpathref="libraries">
- <classpath path="${targetdir}"/>
- <arg value="${action}"/>
- < SPAN>java>
- < SPAN>target>
action參數(shù)(argument)的值是通過命令行調(diào)用這個target的時候設(shè)置的:
- C:\hibernateTutorial\>ant run -Daction=store
你應(yīng)該會看到,編譯以后,Hibernate根據(jù)你的配置啟動,并產(chǎn)生一大堆的輸出日志。在日志最后你會看到下面這行:
- [java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
這是Hibernate執(zhí)行的INSERT命令,問號代表JDBC的綁定參數(shù)。如果想要看到綁定參數(shù)的值或者減少日志的長度,就要調(diào)整你在log4j.properties文件里的設(shè)置。
我們想要列出所有已經(jīng)被存儲的events,就要增加一個條件分支選項到main方法中去。
- if (args[0].equals("store")) {
- mgr.createAndStoreEvent("My Event", new Date());
- }
- else if (args[0].equals("list")) {
- List events = mgr.listEvents();
- for (int i = 0; i < events.size(); i++) {
- Event theEvent = (Event) events.get(i);
- System.out.println("Event: " + theEvent.getTitle() +
- " Time: " + theEvent.getDate());
- }
- }
我們也增加一個新的listEvents()方法:
- private List listEvents() {
- Session session = HibernateUtil.getSessionFactory().getCurrentSession();
- session.beginTransaction();
- List result = session.createQuery("from Event").list();
- session.getTransaction().commit();
- return result;
- }
我們在這里是用一個HQL(Hibernate Query Language-Hibernate查詢語言)查詢語句來從數(shù)據(jù)庫中加載所有存在的Event對象。Hibernate會生成適當(dāng)?shù)腟QL,把它發(fā)送到數(shù)據(jù)庫,并操作從查詢得到數(shù)據(jù)的Event對象。當(dāng)然,你可以使用HQL來創(chuàng)建更加復(fù)雜的查詢。
現(xiàn)在,根據(jù)以下步驟來執(zhí)行并測試以上各項:
◆運行ant run -Daction=store來保存一些內(nèi)容到數(shù)據(jù)庫。當(dāng)然,先得用hbm2ddl來生成數(shù)據(jù)庫schema。
◆現(xiàn)在把hibernate.cfg.xml文件中hbm2ddl屬性注釋掉,這樣我們就取消了在啟動時用hbm2ddl來生成數(shù)據(jù)庫schema。通常只有在不斷重復(fù)進行單元測試的時候才需要打開它,但再次運行hbm2ddl會把你保存的一切都刪掉(drop)——create配置的真實含義是:“在創(chuàng)建SessionFactory的時候,從schema 中drop 掉所有的表,再重新創(chuàng)建它們”。
◆如果你現(xiàn)在使用命令行參數(shù)-Daction=list運行Ant,你會看到那些至今為止我們所儲存的events。當(dāng)然,你也可以多調(diào)用幾次store以保存更多的envents。
注意:
很多Hibernate新手在這一步會失敗,我們不時看到關(guān)于Table not found錯誤信息的提問。但是,只要你根據(jù)上面描述的步驟來執(zhí)行,就不會有這個問題,因為hbm2ddl會在第一次運行的時候創(chuàng)建數(shù)據(jù)庫schema,后繼的應(yīng)用程序重起后還能繼續(xù)使用這個schema。假若你修改了映射,或者修改了數(shù)據(jù)庫schema,你必須把hbm2ddl重新打開一次。
看過本文我想大家對Hibernate加載并存儲對象應(yīng)該有了更深入的了解,以后就可以靈活運用了。
【編輯推薦】