簡述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();
- }
- }
我們創建了個新的Event對象并把它傳遞給Hibernate?,F在Hibernate負責與SQL打交道,并把INSERT命令傳給數據庫。在運行之前,讓我們看一下處理Session和Transaction的代碼。
一個Session就是個單一的工作單元。我們暫時讓事情簡單一些,并假設HibernateSession和數據庫事務是一一對應的。為了讓我們的代碼從底層的事務系統中脫離出來(此例中是JDBC,但也可能是JTA),我們使用Hibernate Session中的Transaction API。
sessionFactory.getCurrentSession()是干什么的呢?首先,只要你持有SessionFactory(幸虧我們有HibernateUtil,可以隨時獲得),大可在任何時候、任何地點調用這個方法。getCurrentSession()方法總會返回“當前的”工作單元。記得我們在hibernate.cfg.xml中把這一配置選項調整為"thread"了嗎?因此,因此,當前工作單元被綁定到當前執行我們應用程序的Java線程。但是,這并非是完全準確的,你還得考慮工作單元的生命周期范圍 (scope),它何時開始,又何時結束.
Session在第一次被使用的時候,即第一次調用getCurrentSession()的時候,其生命周期就開始。然后它被Hibernate綁定到當前線程。當事務結束的時候,不管是提交還是回滾,Hibernate會自動把Session從當前線程剝離,并且關閉它。假若你再次調用getCurrentSession(),你會得到一個新的Session,并且開始一個新的工作單元。這種線程綁定(thread-bound)的編程模型(model)是使用Hibernate的最廣泛的方式,因為它支持對你的代碼靈活分層(事務劃分可以和你的數據訪問代碼分離開來,在本教程的后面部分就會這么做)。
和工作單元的生命周期這個話題相關,Hibernate Session是否被應該用來執行多次數據庫操作?上面的例子對每一次操作使用了一個Session,這完全是巧合,這個例子不是很復雜,無法展示其他方式。Hibernate Session的生命周期可以很靈活,但是你絕不要把你的應用程序設計成為每一次數據庫操作都用一個新的Hibernate Session。因此就算下面的例子(它們都很簡單)中你可以看到這種用法,記住每次操作一個session是一個反模式。在本教程的后面會展示一個真正的(web)程序。
關于事務處理及事務邊界界定的詳細信息,請參看第 11 章 事務和并發。在上面的例子中,我們也忽略了所有的錯誤與回滾的處理。
為第一次運行我們的程序,我們得在Ant的build文件中增加一個可以調用得到的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參數(argument)的值是通過命令行調用這個target的時候設置的:
- C:\hibernateTutorial\>ant run -Daction=store
你應該會看到,編譯以后,Hibernate根據你的配置啟動,并產生一大堆的輸出日志。在日志最后你會看到下面這行:
- [java] Hibernate: insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)
這是Hibernate執行的INSERT命令,問號代表JDBC的綁定參數。如果想要看到綁定參數的值或者減少日志的長度,就要調整你在log4j.properties文件里的設置。
我們想要列出所有已經被存儲的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查詢語言)查詢語句來從數據庫中加載所有存在的Event對象。Hibernate會生成適當的SQL,把它發送到數據庫,并操作從查詢得到數據的Event對象。當然,你可以使用HQL來創建更加復雜的查詢。
現在,根據以下步驟來執行并測試以上各項:
◆運行ant run -Daction=store來保存一些內容到數據庫。當然,先得用hbm2ddl來生成數據庫schema。
◆現在把hibernate.cfg.xml文件中hbm2ddl屬性注釋掉,這樣我們就取消了在啟動時用hbm2ddl來生成數據庫schema。通常只有在不斷重復進行單元測試的時候才需要打開它,但再次運行hbm2ddl會把你保存的一切都刪掉(drop)——create配置的真實含義是:“在創建SessionFactory的時候,從schema 中drop 掉所有的表,再重新創建它們”。
◆如果你現在使用命令行參數-Daction=list運行Ant,你會看到那些至今為止我們所儲存的events。當然,你也可以多調用幾次store以保存更多的envents。
注意:
很多Hibernate新手在這一步會失敗,我們不時看到關于Table not found錯誤信息的提問。但是,只要你根據上面描述的步驟來執行,就不會有這個問題,因為hbm2ddl會在第一次運行的時候創建數據庫schema,后繼的應用程序重起后還能繼續使用這個schema。假若你修改了映射,或者修改了數據庫schema,你必須把hbm2ddl重新打開一次。
看過本文我想大家對Hibernate加載并存儲對象應該有了更深入的了解,以后就可以靈活運用了。
【編輯推薦】