今天要寫的內容其實不多,本打算將hibernate對集合的操作的內容直接歸結為一篇的,但想一想,還是分開寫的比較好,畢竟前面的已經發布出去來了,廢話不多說,開始吧!
依舊新建一個StudentList.java實體類,其他的屬性不變,只是將hobby屬性由Set集合類型變為List集合類型,還是把代碼貼出來吧,希望不要嫌煩
package com.joe.entity; import java.util.List; public class StudentList { private int id; private String name; private int age; private List<String> hobby; /** * 無參構造函數 */ public StudentList(){ } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List<String> getHobby() { return hobby; } public void setHobby(List<String> hobby) { this.hobby = hobby; } }
接下來,大家都知道的,就是配置StudentList.hbm.xml對象關系映射文件了,先說說<list>標簽吧,<list>元素用來映射java.util.List類型的屬性,常用的屬性和子元素有:
- name屬性
- table屬性
- <key>子元素
- <list-index>子元素
- <element>子元素
照樣貼上代碼:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" > <hibernate-mapping> <!-- 一個class標簽對應一個實體類,name屬性指定實體類名稱,table屬性指定關聯的數據庫表 --> <class name="com.joe.entity.StudentList" table="stu_list_tab"> <!-- 主鍵 --> <id name="id" column="stu_id"> <!-- 提供ID自增的策略 native會根據數據庫自行判斷 --> <generator class="native"></generator> </id> <!-- 其他屬性,name對應實體類的屬性,column對應關系型數據庫表的列 --> <property name="name" column="stu_name"></property> <property name="age" column="stu_age"></property> <list name="hobby" table="hobby_list_tab"> <key column="student_id"></key> <list-index column="position"></list-index> <element type="string" column="hobby"></element> </list> </class> </hibernate-mapping>
來解讀一下list標簽吧,<key>子元素和<element>子元素就不多講了,主要是<list-index>子元素,我查了一下資料,也可以使用<index>,因List集合是個有序可重復的集合,所以要使用<index-index column="position"/></list-index>(或者使用<index column="position"></index>) 來標明其順序。(position為hobby_list_tab表中附加字段),因此在插入更新時便需要維護position字段,否則索引設置錯誤,取出的數據就會出現空值情況。
如果<list>標簽配置了inverse="true"屬性, 則list的index則不會主動賦值,index列會產生空值,如果index列數據庫設置可以為空,則可以正常保存數據. 而用hibernate再去查詢對象數據時,會拋出null index column for collection: 此類錯誤.也就是說配置inverse為true的list,需要手動維護index列.感覺還是挺復雜的,有點兒攪。
當然,還可以使用<bag>(結合了List與Set)標簽來配置list集合屬性,可以重復且沒有順序的一種集合,是Hibernate提供的。HIbernate使用jdk的List模擬Bag。其配置與Hibernate映射list時基本相同。這里就不再討論來,畢竟這是是沖着list來的。
依舊建立一個StudentListTest.java測試類,先寫一個創建表結構的方法:
@Test
public void createTable() {
Configuration cfg = new Configuration().configure();
SchemaExport se = new SchemaExport(cfg);
se.create(true, true);
}
執行該方法,看看hibernate的執行結果:
在創建hobby_list_tab表的時候,可以看到position字段配置來not null 屬性,這也體現來前面的list標簽的配置,更多的信息可以在其官方文檔了解,這里提供一個快捷通道:點擊這里
add()方法的測試:
/** * 添加的方法 */ @Test public void add(){ Transaction tx=null; Session session=null; try{ session=HibernateUtils.getSession(); tx=session.beginTransaction(); StudentList student=new StudentList(); student.setName("zhangsan"); student.setAge(20); List<String> list=new ArrayList<String>(); list.add("basketball"); list.add("swimming"); student.setHobby(list); session.save(student); tx.commit(); }catch(HibernateException he){ if(tx!=null){ tx.rollback(); } he.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
執行該方法,看看控制台的輸出信息:
只有一點需要說明的,就是我在程序中並沒有為position膚質,那position字段中是否有值,如果有,為何值?打開mysql數據庫,一看便知:
哎,有值,這是hibernate提供的一種機制,它自動維護,只要你配置正確。還有一個問題需要注意,就是為什么是從0開始的而不是其他的值開始的呢?這就和我們的List集合相關聯,List的底層是一個動態的數組,所以添加元素時,下標是從0開始的。
findAll()方法的測試:
@Test public void findAll(){ Transaction tx=null; Session session=null; try{ session=HibernateUtils.getSession(); tx=session.beginTransaction(); StudentList stu=(StudentList)session.get(StudentList.class, 1); System.out.println(stu.getId()+stu.getName()+stu.getAge()); tx.commit(); }catch(HibernateException he){ if(tx!=null){ tx.rollback(); } he.printStackTrace(); }finally{ HibernateUtils.closeSession(session); } }
和以前測試差不多,先只訪問基本屬性,我想hibernate的執行動作大家都知道了,只會有一條select語句,不會去訪問hobby_list_tab表的,還是貼上圖吧:
接下來,添加訪問hobby屬性的代碼:
//訪問hobby屬性 List<String> hobby=stu.getHobby(); for(String str:hobby){ System.out.println(str); }
相信結果大家還是知道的,依舊貼圖:
其實自我感覺這篇文章和上一篇文章有點重復,但是還不至於無聊致死,畢竟知識是一步一步學來的,接下來的一兩篇,節奏大概還是這樣的吧,各位看官,不要嫌我啰嗦喲。