Hibernate 查詢結果的展現

來源:互聯網
上載者:User

我們使用hibernate(以下簡稱h)來管理資料庫表的關聯關係,基本的原理其實是很簡單的,就是將資料庫中表之間的關聯轉移到了實體bean的類之間,配置好了以後h就可以幫我們維持這種關聯關係了。這的確帶來了很大的方便,我們可以在我們的程式中以hql來物件導向的擷取或儲存資料了,例如以前我們要查詢一個班級裡面的學生的資訊,自己寫sql的話需要關聯2張表,而且還要自己手動的將查詢到的資料一個一個的取出來,然後封裝到我們的bean裡面去最後才能字啊jsp中顯示出來,這個過程是很繁瑣的,有了h,我們就可以不用在sql顯式的寫這種關聯關係了,我們選擇將這種關聯關係寫到h的對應檔中去,這樣一來h就幫我們維護這種關係了,我們需要查詢班級裡面的學生的資訊的時候,只要通過hql: from Class  as c  where c.id=:id;就可以得到具體的一個班級的實體物件(假設是c),接著Set<Student> students= c.getStudents();就可以得到該班級裡面的所有的學生了。整個過程沒有join等任何關聯操作,以為這個關聯已經由h幫我們維護了,所以我們就可以不管了。

通過上面我們知道,Hibernate是通過對象包含對象這樣的方式來維護關係的,那麼當我們需要查詢關聯對象的時候,先通過Hibernate得到主對象,再調用主對象的get×得到關聯對象,就可以擷取關聯資訊了,然後組裝資料到jsp上去顯示。 我們可以簡單的寫成:hql=“select new map(c.id as id ,c.name as name,c.students[0].name as  studentname) from Class as  c  where c.id=:id”; 這樣就同時完成了資料的查詢和組裝。將查詢到的資料群組裝到一個map中,as 後面的就是 map的key,map的值就是查詢出來的資料了。這種資料群組裝方式比:

while (it.hasNext()) { 
10 Object[] tuple = (Object[]) it.next(); 
11 Members members = (Members) tuple[ 0 ]; 
12 String className = (String) tuple[ 1 ]; 

要簡潔很多。

當然,我們也可以定義自己的實體類來容納查詢出的資料:

selectnew NewMembers(members, classInfo.className) " + 
3 " from Members members, ClassInfo classInfo " + 
4 " where members.level = classInfo.classCode " 

也可以 使用hibernateapi 函數 setResultTransformer 將查詢結果存放到我們自訂的bo對象中去:

String sql = "select u.userName as userName ,p.title as title ,p.addTime as addTime from user as u,post as p where u.id=p.userId"
Query q = factory.getCurrentSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(PostVO.class));


關於資料群組裝,有很多方法,不一而論。
我們下面要討論的是,h在涉及到3張或3張以上的表的複雜的查詢的時候,如何使用的問題。
我們知道2張或者一張表的情形使用我們上面介紹的方式就足夠了,但是對3張以上的表關聯的複雜查詢,我們則要比較2中方式的好壞了:

一種方式是仍然將表關係通過配置對應檔交給h來管理,這樣一來我們不僅僅要在設定檔裡配置多個關係,而且在對應的實體類裡面也要加入關聯屬性,在查詢的時候得到主實體物件以後還有多次調用其屬性來擷取關聯表的資訊,這樣不是不可以,但是是比較繁瑣的,稍微不注意就容易出現錯誤。

如果要查詢的表多於5張,最好的建議就是使用native sql來做,也就是通過直接執行sql語句來查詢,表間的關聯關係直接在sql語句裡面寫明,不要h來管理,這樣一來少了h的配置,二來不需要定義每個表對應的實體類,也算省了很多事情,在使用native sql的時候有一些需要注意的地方:

  Session s = sessionFactory.openSession();           String sql="select book.bookname,borr.borrowTime,borr.backTime,pub.pubname,bs.name  bookcasename,book.price from "+"(select * from tb_borrow where ifback=0) "+"as borr left join tb_bookinfo book on borr.bookid=book.id join tb_publishing pub "+"on book.isbn=pub.isbn join tb_bookcase bs "+" on book.bookcase=bs.id join tb_reader r on borr.readerid=r.id where r.barcode=?";  Query query=s.createSQLQuery(sql).addScalar("bookname", Hibernate.STRING) .addScalar("borrowTime", Hibernate.STRING).  addScalar("backTime", Hibernate.STRING).addScalar("pubname", Hibernate.STRING).  addScalar("bookcasename", Hibernate.STRING).addScalar("price", Hibernate.STRING);     query.setParameter(0, barCode);   List list=null;      try{    list=query.list();   s.close(); }  catch (Exception e)  {      e.printStackTrace();  }return list;


1.  Session session = sessionFactory.openSession();session.createSQLQuery(sql);通過這種方式獲得查詢對象query。
2.  
  list=query.list();得到的是一個數組列表(ArrayList),其中列表的每個元素都是object類型的數組,代表查詢結果的一條記錄,也就是說h會將sql查詢出來的其中的每個欄位都強制轉換成Object類型,然後組成一個數組方到list裡面去。
3.單純使用
s.createSQLQuery(sql)往往會報“找不到列”的錯誤,其實這是h對native sql支援的原因,因為Hibernate是通過使用ResultSetMetadata來判定返回的標量值的實際順序和類型的,假若某個指定的類型沒有被映射,或者不是你所預期的類型那麼就會出現上述錯誤了,所以通過addScalar()明確指出返回什麼列以及每個列的類型就可以避免上述錯誤了。
最好你根據實際的類型將得到的object轉換成實際的類型,就可以得到這些類型中儲存的資訊了。
  • 1
  • 2
  • 3
  • 4
  • 下一頁

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.