Hibernate對多表關聯查詢

一、 Hibernate簡介Hibernate是一個JDO工具。它的工作原理是通過文件(一般有兩種:xml文件和properties文件)把值對象和數據庫表之間建立起一個映射關係。這樣,我們只需要通過操作這些值對象和Hibernate提供的一些基本類,就可以達到使用數據庫的目的。例如,使用Hibernate的查詢,可以直接返回包含某個值對象的列表(List),而不必向傳統的JDBC訪問方式一樣把結果集的數據逐個裝載到一個值對象中,爲編碼工作節約了大量的時間。Hibernate提供的HQL是一種類SQL語言,它和EJBQL一樣都是提供對象化的數據庫查詢方式,但HQL在功能和使用方式上都非常接近於標準的SQL.

 

    二、 Hibernate與JDBC的區別Hibernate與JDBC的主要區別如下:

    1、 Hibernate是JDBC的輕量級的對象封裝,它是一個獨立的對象持久層框架,和App Server,和EJB沒有什麼必然的聯繫。Hibernate可以用在任何JDBC可以使用的場合,從某種意義上來說,Hibernate在任何場合下取代JDBC. 

    2、 Hibernate是一個和JDBC密切關聯的框架,所以Hibernate的兼容性和JDBC驅動,和數據庫都有一定的關係,但是和使用它的Java程序,和App Server沒有任何關係,也不存在兼容性問題。

    3、 Hibernate是做爲JDBC的替代者出現的,不能用來直接和Entity Bean做對比。

    三、 Hibernate 進行多表關聯查詢Hibernate對多個表進行查詢時,查詢結果是多個表的笛卡爾積,或者稱爲“交叉”連接。 例如:from Student, Book from Student as stu, Book as boo from Student stu, Book boo注意:讓查詢中的Student和Book均是表student和book對應的類名,它的名字一定要和類的名字相同,包括字母的大小寫。別名應該服從首字母小寫的規則是一個好習慣,這和Java對局部變量的命名規範是一致的。

    下面列舉一個完整的例子來說明Hibernate對多個表進行關聯查詢(其中粗體是我們要特別注意的地方,相應表tBookInfo和BookSelection的結構和其對應的hbm.xml、class文件就不一一列舉了,有需要詳細瞭解的朋友,請聯繫我): dl.bitsCN.com網管軟件下載

String sTest = "from tBookInfo book, BookSelection sel where book.id = sel.bookId";

Collection result = new ArrayList();

Transaction tx = null;

try {

Session session = HibernateUtil.currentSession();

tx = session.beginTransaction();

Query query = session.createQuery(sql);

result = query.list();

tx.commit();

} catch (Exception e) {

throw e;

} finally {

HibernateUtil.closeSession();

}

ArrayList sList = (ArrayList) result;

Iterator iterator1 = sList.iterator();

while (iterator1.hasNext()) {

Object[] o = (Object[]) iterator1.next();

tBookInfo bookInfo = (tBookInfo) o[0];

BookSelection bookSelect = (BookSelection) o[1];

System.out.println("BookInfo-Title: " + bookInfo.getTitle());

System.out.println("BookSelection-BookSelectionId: " + bookSelect.getId());

}

1、到底在哪用cascade="..."?

cascade屬性並不是多對多關係一定要用的,有了它只是讓我們在 插入或刪除對像時更方便一些,只要在cascade的源頭上插入或是刪除,所有cascade的關係就會被自己動的插入或是刪除。便是爲了能正確的 cascade,unsaved-value是個很重要的屬性。Hibernate通過這個屬性來判斷一個對象應該save還是update,如果這個對 象的id是unsaved-value的話,那說明這個對象不是persistence object要save(insert);如果id是非unsaved-value的話,那說明這個對象是persistence object(數據庫中已存在),只要update就行了。saveOrUpdate方法用的也是這個機制。

2、到底在哪用inverse="ture"?

inverse屬性默認是false的,就是說關係的兩端都來維護關係。這個意思就是說,如有一個Student, Teacher和TeacherStudent表,Student和Teacher是多對多對多關係,這個關係由TeacherStudent這個表來表 現。那麼什麼時候插入或刪除TeacherStudent表中的記錄來維護關係呢?在用hibernate時,我們不會顯示的對 TeacherStudent表做操作。對TeacherStudent的操作是hibernate幫我們做的。hibernate就是看hbm文件中指 定的是"誰"維護關係,那個在插入或刪除"誰"時,就會處發對關係表的操作。前提是"誰"這個對象已經知道這個關係了,就是說關係另一頭的對象已經set 或是add到"誰"這個對象裏來了。前面說過inverse默認是false,就是關係的兩端都維護關係,對其中任一個操作都會處發對錶系表的操作。當在 關係的一頭,如Student中的bag或set中用了inverse="true"時,那就代表關係是由另一關維護的(Teacher)。就是說當這插 入Student時,不會操作TeacherStudent表,即使Student已經知道了關係。只有當Teacher插入或刪除時纔會處發對關係表的 操作。所以,當關系的兩頭都用inverse="true"是不對的,就會導致任何操作都不處發對關係表的操作。當兩端都是inverse= "false"或是default值是,在代碼對關係顯示的維護也是不對的,會導致在關係表中插入兩次關係。

在一對多關係中 inverse就更有意義了。在多對多中,在哪端inverse="true"效果差不多(在效率上)。但是在一對多中,如果要一方維護關係,就會使在插 入或是刪除"一"方時去update"多"方的每一個與這個"一"的對象有關係的對象。而如果讓"多"方面維護關係時就不會有update操作,因爲關係 就是在多方的對象中的,直指插入或是刪除多方對象就行了。當然這時也要遍歷"多"方的每一個對象顯示的操作修關係的變化體現到DB中。不管怎樣說,還是讓 "多"方維護關係更直觀一些。

3、cascade和inverse有什麼區別?

可以這樣理解,cascade定義的是關係兩端對象到對象的級聯關係;而inverse定義的是關係和對象的級聯關係。

4、 net.sf.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): 2, of class: Xxxxx

這個問題出現在要刪除關係的一頭時。如,要刪除一個已經和Student有關係的 Teacher。當tx.commit();時纔會拋出這個異常。這時一個在關係另一頭的Student對象中的Set或是List中把這個 Teacher對象顯示的remove掉,再session.delete(這個teacher);。這是爲了防止在Student端有cascade時 把這個Teacher對象再存回DB。所以,這個異常的只有在Student的關係定義中有cascade="...",而且沒有像上面說的顯示的解除關 系時纔會出現。所以防止出現這個異常的方法就是:1,在Student端不用cascade;2,或是用cascade的話,就顯示的刪除對像中的關係。 3,在Teacher端要用cascade

5、net.sf.hibernate.HibernateException: identifier of an instance of my.MyObject altered from N to N

這個異常其時不是多對多中常遇到的,但是這個異常的提示不make sense,所以提一下,是因爲id的java對象中的type和hbm文件中定義的不一樣,如:java中用long,而hbm中用type= "integer",並且generator用的是identity時就會出現
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章