本次學習是在hibernate3環境下,沒有結合struts2和Spring,測試是直接用java類的main方法在控制檯輸出。java
oracle數據庫(其餘數據庫也能夠,都是類似的)、hibernate3.jar等架包。sql
a.建立工程,引入hibernate和驅動開發包數據庫
b.在src下添加hibernate.cfg.xml主配置服務器
c.根據數據表建立Entity實體類session
d.編寫實體類和數據表的映射文件xxx.hbm.xmloracle
e.利用Hibernate API實現增刪改查操做app
1、在src下添加hibernate.cfg.xml主配置,配置內容以下:函數
<!DOCTYPE hibernate-configuration PUBLIC 工具 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 性能 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration> <session-factory> <!-- 鏈接數據庫的驅動--> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <!-- 鏈接數據庫的地址--> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost :1521:orcl</property> <!-- 鏈接數據庫的用戶名--> <property name="hibernate.connection.username">hr</property> <!-- 鏈接數據庫的密碼--> <property name="hibernate.connection.password">orcl</property>
<property name="hibernate.connection.pool.size">20 </property> <property name="hibernate.show_sql">true </property> <property name="jdbc.fetch_size">50 </property> <property name="jdbc.batch_size">23 </property> <property name="jdbc.use_scrollable_resultset">false </property> <property name="Connection.useUnicode">true </property>
<!--hibernate.dialect 只是Hibernate使用的數據庫方言,就是要用Hibernate鏈接那種類型的數據庫服務器。--> <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect </property>
<!--指定映射文件--> <mapping resource="com/neusoft/test/entity/User.hbm.xml" /> </session-factory> </hibernate-configuration> |
2、根據數據表建立Entity實體類,com/neusoft/test/entity/User.java,代碼以下:
package com.neusoft.test.entity;
public class User { private int id; private String userName; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getuserName() { return userName; } public void setuserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } |
須要注意的是實體類定義的字段最好與數據庫(oracle不區分大小寫)中的字段一致,若是不一致會麻煩一些,且配置容易出錯。
3、編寫實體類和數據表的映射文件com/neusoft/test/entity/User.hbm.xml,該配置文件存放的位置不是固定的,可是要與hibernate.cfg.xml主配置中「指定映射文件」相對應,具體配置以下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.neusoft.test.entity"> <class name="User" table="demo_user_t"> <id name="id"> <column name="id"></column> <!--主鍵生成策略,sequence是oracle自增策略,別的數據庫要使用各自適用的 --> <generator /> </id> <property name="userName" column="userName"/> <property name="password" /> </class> </hibernate-mapping> |
name屬性對應的是實體類中的屬性字段,必須是一致的(區分大小寫),若是該字段與數據庫表中的字段是一致的,則不須要column;若是不一致,則須要column指明該字段是與數據庫中哪一個字段是對應的。
數據庫的表名爲demo_user_t,含有字段id、userName、password。
4、測試,進行增刪改查。新建一個test1.java。代碼以下:
package com.neusoft.test.action;
import java.util.List; import org.hibernate.*; import com.neusoft.test.entity.User; import com.neusoft.test.utils.HibernateUtil;
public class test1 { /** * main函數,選擇要執行的動做 */ public static void main(String args[]) { testFindAll(); }
/** * 測試添加操做 */ public static void testAdd() { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); User user = new User(); user.setId(1);// user.setId()要根據主鍵生成策略而定 user.setuserName("1"); user.setPassword("1"); session.save(user);// 保存 tx.commit();// 提交事務 session.close();// 關閉session }
/** * 測試更新操做 */ public static void testUpdate() { Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); // 按ID=1主鍵作條件查詢 User user = (User) session.load(User.class, 1); user.setuserName("11"); user.setPassword("11"); session.update(user); tx.commit(); session.close(); }
/** * 測試刪除操做 */ public static void testDelete() { Session session = HibernateUtil.getSession(); Transaction tx = session.beginTransaction(); User user = new User(); user.setId(1); // User user = (User)session.get(User.class, 1); session.delete(user);// 執行一個delete語句,按ID作條件刪除 tx.commit(); session.close(); }
/** * 測試查詢操做 */ @SuppressWarnings("unchecked") public static void testFindAll() { Session session = HibernateUtil.getSession(); // 利用Query執行一個HQL查詢語句 Query query = session.createQuery("from User"); List<User> list = query.list(); for (User u : list) { System.out.println(u.getId() + " " + u.getuserName() + " " + u.getPassword()); } session.close(); }
public static void testFindById() { Session session = HibernateUtil.getSession(); // 利用Query執行一個HQL查詢語句 User user = (User) session.get(User.class, 1); System.out.println(user.getId() + " " + user.getuserName() + " " + user.getPassword()); session.close(); }
@SuppressWarnings("unchecked") public static void testFindByName() { Session session = HibernateUtil.getSession(); // 利用Query執行一個HQL查詢語句 Query query = session.createQuery("from User where userName='1'"); List<User> list = query.list(); for (User u : list) { System.out.println(u.getId() + " " + u.getuserName() + " " + u.getPassword()); } session.close(); } } |
須要一個自定義的hibernate工具類HibernateUtil,代碼以下:
package com.neusoft.test.utils;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration;
public class HibernateUtil { // static SessionFactory sessionFactory= new Configuration().configure().buildSessionFactory(); static SessionFactory sessionFactory = new Configuration().configure( "hibernate.cfg.xml").buildSessionFactory(); static Session session = sessionFactory.openSession();
public static Session getSession() { return session; }
public static void closeSession() { // TODO Auto-generated method stub session.close(); } } |
首先要說明,有多個實例化類時,能夠定義定義多個映射文件xxx.hbm.xml,而後在主配文件hibernate.cfg.xml中指定全部映射文件;也能夠只定義一個映射文件,在映射文件中定義多個實例化類(class的定義)。
還有一點要注意,一個實例化類只能被映射文件定義一次。若是要對同一個表進行不一樣功能的操做,則建多個與之對應的實例化類,而後在映射文件中定義不一樣功能的實例化類。
每次作完一個小test要將數據庫表內的數據清空,不然會對其餘的測試產生影響,有可能報錯。
1 、 映射集合屬性
(1)List集合映射:
數據庫表students
schools
映射文件中添加以下配置:
<class name="Student" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <list name="schools" table="schools"> <!-- 外鍵,對應該表的某個字段,默認參考上面定義的id --> <key column="student_id" not-null="true"></key> <list-index column="list_order"></list-index> <element type="string" column="school_name"></element> </list> </class> |
實例化類以下:
package com.neusoft.test.entity;
import java.util.ArrayList; import java.util.List;
@SuppressWarnings("unchecked") public class Student { private int id; private String name; private int age; private List<String> schools = new ArrayList(); 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 getSchools() { return schools; } public void setSchools(List schools) { this.schools = schools; } } |
測試類以下:
package com.neusoft.test.action;
import java.util.ArrayList; import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student; import com.neusoft.test.utils.HibernateUtil;
public class TestListStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
//添加 Student student = new Student(); student.setAge(12); student.setName("aqq"); List list = new ArrayList(); list.add("zqas"); list.add("zxxdfg"); list.add("zaadfg"); student.setSchools(list); session.save(student); tx.commit();// 提交事務
//查詢 Query query = session.createQuery("from Student"); List<Student> list1 = query.list(); for (Student s : list1) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年齡:" + s.getAge() + " 上過的學校:"); List<String> list2 = s.getSchools(); for (String str : list2) { System.out.print(str + " "); } System.out.println(); } session.close();// 關閉session } } |
(2)Set集合映射
映射文件配置:
<class name="Student_set" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <set name="schools" table="schools"> <key column="student_id" not-null="true"></key> <element type="string" column="school_name"></element> </set> </class> |
實例化類以下:
package com.neusoft.test.entity;
import java.util.HashSet; import java.util.Set;
@SuppressWarnings("unchecked") public class Student_set { private int id; private String name; private int age; private Set<String> schools=new HashSet();
public Set<String> getSchools() { return schools; } public void setSchools(Set<String> schools) { this.schools = schools; } 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; } } |
測試類以下:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student_set; import com.neusoft.test.utils.HibernateUtil;
public class TestSetStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Student_set student = new Student_set(); student.setAge(20); student.setName("mm"); Set set = new HashSet(); set.add("zxc1"); set.add("zxc2"); student.setSchools(set); session.save(student); tx.commit();// 提交事務
Query query = session.createQuery("from Student_set"); List<Student_set> list = query.list(); for (Student_set s : list) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年齡:" + s.getAge() + " 上過的學校:"); Set<String> list2 = s.getSchools(); for (String str : list2) { System.out.print(str + " "); } System.out.println(); } session.close();// 關閉session } } |
(3)Map集合屬性
新建數據庫表scores
映射文件配置:
<class name="Student_map" table="students"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="name" /> <property name="age" /> <map name="scores" table="scores"> <key column="student_id" not-null="true"></key> <map-key type="string" column="course"></map-key> <element type="integer" column="score"></element> </map> </class> |
實例化類:
package com.neusoft.test.entity;
import java.util.HashMap; import java.util.Map;
@SuppressWarnings("unchecked") public class Student_map { private int id; private String name; private int age; private Map scores = new HashMap();
public Map getScores() { return scores; } public void setScores(Map scores) { this.scores = scores; } 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; } } |
測試類:
package com.neusoft.test.action;
import java.util.HashMap; import java.util.List; import java.util.Map;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Student_map; import com.neusoft.test.utils.HibernateUtil;
public class TestMapStudent { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Student_map student = new Student_map(); student.setAge(18); student.setName("yuiu"); Map map=new HashMap(); map.put("數學",85); map.put("語文",95); map.put("英語",89); student.setScores(map); session.save(student); tx.commit();// 提交事務
Query query = session.createQuery("from Student_map"); List<Student_map> list = query.list(); for (Student_map s : list) { System.out.print("id:" + s.getId() + " 姓名:" + s.getName() + " 年齡:" + s.getAge() + " 成績:"); Map map1 = s.getScores();
// 第一種Map遍歷 // Iterator it = map.entrySet().iterator(); // while (it.hasNext()) { // Map.Entry entry = (Map.Entry) it.next(); // Object key = entry.getKey(); // Object value = entry.getValue(); // System.out.print(key + ":" + value + " "); // }
// 第二種Map遍歷 for (Object o : map1.keySet()) { System.out.print(o + ":" + map1.get(o) + " "); } // 第三種Map遍歷 // for (Iterator i = map.keySet().iterator(); i.hasNext();) { // Object obj = i.next(); // System.out.print(obj +":" + map.get(obj) + " "); // } System.out.println(); } session.close();// 關閉session } } |
(4)映射組件屬性
組件屬性的意思是持久化類的屬性既不是基本數據類型,也不是 String 字符串,而是某個組件變量,該組件屬性的類型能夠是自定義類。
顯然沒法直接用 property 映射 name 屬性。爲了映射組件屬性, Hibernate 提供了 component 元素。每一個 component 元素映射一個組件屬性,組件屬性必須指定該屬性的類型,component 元素中的 class 屬性用於肯定組件的類型。
新建數據庫表worker_table
映射文件配置:
<class name="Worker" table="worker_table"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="age" /> <component name="name"> <property name="last" /> <property name="first" /> </component> </class> |
實例化類:
package com.neusoft.test.entity;
public class Worker { private int id; private int age; private Name name;
public Name getName() { return name; } public void setName(Name name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
輔助類:
package com.neusoft.test.entity;
public class Name { private String last; private String first;
public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } } |
測試類:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Name; import com.neusoft.test.entity.Worker; import com.neusoft.test.utils.HibernateUtil;
public class TestWorker { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Worker worker=new Worker(); Name name= new Name(); name.setLast("Cloze"); name.setFirst("Tom"); worker.setAge(25); worker.setName(name); session.save(worker); tx.commit();// 提交事務
Query query = session.createQuery("from Worker"); List<Worker> worker1 = query.list(); for (Worker w : worker1) { System.out.println("id:" + w.getId() + " 姓名:" + w.getName().getLast() + " " + w.getName().getFirst() + " 年齡:" + w.getAge()); } session.close();// 關閉session }
} |
(5)集合組件屬性映射
集合除了存放 String 字符串之外,還能夠存放組件類型。實際上,更多狀況下,集合組件存放的都是組件類型。
新建數據庫表company_table
映射文件配置:
<class name="Worker2" table="worker_table"> <id name="id"> <column name="id"></column> <generator /> </id> <property name="age" /> <component name="name"> <property name="last" /> <property name="first" /> </component> <list name="company" table="company_table"> <key column="id" not-null="true"/> <list-index column="list_order"/> <composite-element> <property name="name"></property> <property name="address"></property> </composite-element> </list> </class> |
實例化類:
package com.neusoft.test.entity;
import java.util.ArrayList; import java.util.List;
@SuppressWarnings("unchecked") public class Worker2 { private int id; private int age; private Name name; private List<Company> company = new ArrayList();
public List<Company> getCompany() { return company; } public void setCompany(List<Company> company) { this.company = company; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
輔助類:
package com.neusoft.test.entity;
public class Company { private String name; private String address;
public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } |
測試類:
package com.neusoft.test.action;
import java.util.ArrayList; import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Company; import com.neusoft.test.entity.Name; import com.neusoft.test.entity.Worker2; import com.neusoft.test.utils.HibernateUtil;
public class TestWorkerAndCompany { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); List list = new ArrayList(); Worker2 worker=new Worker2(); worker.setAge(22); Name name= new Name(); name.setLast("Cloze"); name.setFirst("Tom"); worker.setName(name); Company company=new Company(); company.setName("aaa"); company.setAddress("aaaaaaaaaa"); list.add(company); Company company2=new Company(); company2.setName("bbbb"); company2.setAddress("bbbbbbbbbb"); list.add(company2); Company company3=new Company(); company3.setName("ccc"); company3.setAddress("ccccccc"); list.add(company3); worker.setCompany(list); session.save(worker); tx.commit();// 提交事務
Query query = session.createQuery("from Worker2"); List<Worker2> worker1 = query.list(); for (Worker2 w : worker1) { System.out.println("id:" + w.getId() + " 姓名:" + w.getName().getLast() + " " + w.getName().getFirst() + " 年齡:" + w.getAge() + " 工做過的公司:"); for(Company c :w.getCompany()){ System.out.println(c.getName()+" "+c.getAddress()); } System.out.println(); } session.close();// 關閉session } } |
2 、 關聯關係映射
(1)單向 N-1
單向 N-1 關聯只需從 N 的一端能夠訪問 1 的一端。模型:多我的(Person)對應同一個地址(Address)。只須要從人實體端找到相應的地址實體。無須關心從某個地址找到所有住戶。
Person 端增長了 Address 屬性,該屬性不是一個普通的組件屬性,而是引用了另一個持久化類,使用 many-to-one 元素映射 N-1 的持久化屬性。
many-to-one 元素的做用相似於 property 元素,用於映射持久化類的某個屬性,區別是改元素映射的是關聯持久化類。與 property 元素相似,many-to-one 元素也必須擁有 name 屬性,用於肯定該屬性的名字,column 屬性肯定外鍵列的列名.
新建數據庫表person_table
address_table
映射配置:
<class name="Person" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 多對一,column是Address在該表中的外鍵列名 --> <many-to-one name="address" column="addressid"></many-to-one> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
實例化類1:
package com.neusoft.test.entity;
public class Person { private int personid; private String name; private int age; private Address address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } |
實例化類2:
package com.neusoft.test.entity;
public class Address { private int addressid; private String addressdetail; private int personid;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
測試類:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person; import com.neusoft.test.utils.HibernateUtil;
public class AddManyToOne { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Person person=new Person(); person.setName("aa"); person.setAge(22); Address address=new Address();
// 新建一個地址,而後添加給person address.setAddressdetail("wqesdasdasd"); person.setAddress(address); session.save(address);
// 直接添加已有的地址 // address.setAddressid(1); // person.setAddress(address);
session.save(person); tx.commit();// 提交事務
Query query = session.createQuery("from Person"); List<Person> list = query.list(); for (Person p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 關閉session } } |
(2)基於外鍵的單向 1-1
單向 1-1,POJO 與 N-1 沒有絲毫區別。
基於外鍵的單向 1-1 映射文件:只須要在原有的 many-to-one 元素添加 unique=「true」,用以表示 N 的一端必須惟一便可,N的一端增長了惟一約束, 即成爲單向 1-1。
(3)基於主鍵的單向 1-1
基於主鍵關聯的持久化類不能擁有本身的主鍵生成器,它的主鍵由關聯類負責生成。增長one-to-one元素來映射關聯屬性,必須爲one-to-one元素增長constrained="true"屬性,代表該類的主鍵由關聯類生成。
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <column name="personid"></column> <!-- 基於主鍵關聯時,主鍵生成策略是foreign,代表根據關聯類生成主鍵 --> <generator> <!-- 關聯持久化類的屬性名 --> <param name="property">address</param> </generator> </id> <property name="name" /> <property name="age" /> <!-- 關聯映射 基於主鍵 1-1 --> <one-to-one name="address" constrained="true"></one-to-one> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
實例化類:
package com.neusoft.test.entity;
public class Person2 { private int personid; private String name; private int age; private Address address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } |
測試類:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person2; import com.neusoft.test.utils.HibernateUtil;
public class AddOneToOne { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Person2 person=new Person2(); person.setName("aa"); person.setAge(22); Address address=new Address();
// 新建一個地址,而後添加給person address.setAddressdetail("wqesdasdasd"); person.setAddress(address); session.save(address);
session.save(person); tx.commit();// 提交事務
Query query = session.createQuery("from Person2"); List<Person2> list = query.list(); for (Person2 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 關閉session } } |
(4)單向的 1-N
單向 1-N 關聯的 POJO 須要使用集合屬性。由於一的一端須要訪問 N 的一端,而 N 的一端將以集合的形式表現。
不推薦使用單向的 1-N 關聯:使用 1 的一端控制關聯關係時,會額外多出 update 語句。插入數據時沒法同時插入外鍵列,於是沒法爲外鍵列添加非空約束
映射配置:
<class name="Person3" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 單向1-N --> <set name="address" table="address_table"> <key column="personid"></key> <one-to-many /> </set> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
實例化類:
package com.neusoft.test.entity;
import java.util.Set;
public class Person3 { private int personid; private String name; private int age; private Set<Address> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
測試類:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person3; import com.neusoft.test.utils.HibernateUtil;
public class TestOneToMany{ @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Person3 person=new Person3(); person.setName("gfg"); person.setAge(35); Set set=new HashSet();
Address address=new Address(); address.setAddressdetail("zxcvzxc"); session.save(address); set.add(address);
Address address2=new Address(); address2.setAddressdetail("esdasd"); session.save(address2); set.add(address2);
Address address3=new Address(); address3.setAddressid(105); set.add(address3); person.setAddress(set); session.save(person); tx.commit();// 提交事務
Query query = session.createQuery("from Person3"); List<Person3> list = query.list(); for (Person3 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" ); Set<Address> address1=p.getAddress(); for(Address a: address1){ System.out.println(a.getAddressdetail()); } } session.close();// 關閉session } } |
(5)單向的 N-N
與映射集合屬性相似,必須爲set,list等集合元素添加 key 子元素,用以映射關聯的外鍵列。與集合映射不一樣的是,創建 N-N 關聯時,集合中的元素使用 many-to-many,而不是使用 element 子元素
N-N 的關聯必須使用鏈接表。
新建數據庫表person_address_table
映射配置:
<class name="Person4" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 單向N-N --> <!-- person_address_table爲額外的表,表列必須含有key對應的字段和elt,其中elt是固定的 --> <set name="address" table="person_address_table"> <key column="personid" /> <many-to-many/> </set> </class> <class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> </class> |
實例化類:
package com.neusoft.test.entity;
import java.util.Set;
public class Person4 { private int personid; private String name; private int age; private int addressid; private Set<Address> address;
public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
測試類:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person4; import com.neusoft.test.utils.HibernateUtil;
public class TestManyToMany { @SuppressWarnings("unchecked") public static void main(String args[]) {
Address address1=new Address(); address1.setAddressdetail("zxcvzxc");
Address address2=new Address(); address2.setAddressdetail("esdasd");
Set set_address=new HashSet(); set_address.add(address1); set_address.add(address2);
Person4 person1=new Person4(); person1.setName("gfg"); person1.setAge(35); person1.setAddress(set_address);
Person4 person2=new Person4(); person2.setName("gfg"); person2.setAge(35); person2.setAddress(set_address);
Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
session.save(address1); session.save(address2); session.save(person1); session.save(person2);
tx.commit();// 提交事務
Query query = session.createQuery("from Person4"); List<Person4> list = query.list(); for (Person4 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" ); Set<Address> address=p.getAddress(); for(Address a: address){ System.out.println(a.getAddressdetail()); } } session.close();// 關閉session } } |
(6)雙向 1-N和N-1
對於 1-N 的關聯,Hibernate 推薦使用雙向關聯,並且不要讓 1 的一端控制關聯關係,而是使用 N 的一端控制關聯關係。
雙向 1-N 與 N-1 是徹底相同的。
1 的一端須要使用集合屬性元素來映射關聯關係。集合屬性元素一樣須要增長 key 元素,還須要使用 one-to-many 元素來映射關聯屬性。
N 的一端須要增長 many-to-one 元素來映射關聯屬性。
映射配置:
<hibernate-mapping package="com.neusoft.test.entity"> <class name="Person" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 雙向1-N(N-1) cascade級聯關係 inverse=true:將控制權拋出(給雙向的另外一方) --> <set name="address" table="address_table" cascade="save-update" inverse="true"> <key column="personid"></key> <one-to-many/> </set> </class>
<class name="Address" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <many-to-one name="person" column="personid"></many-to-one> </class> </hibernate-mapping> |
注意:在上面的配置文件中,兩個持久化類的配置文件都須要指定外鍵列的列名,此時不能夠省略。由於不使用鏈接表的1-N關聯的外鍵,而外鍵只保存在N一端的表中,若是兩邊指定的外鍵列名不一樣,將致使關聯映射出錯。若是不指定外鍵列的列名,該列名由系統自動生成,而系統很難保存自動生成的兩個列名相同。
實例化類1:
package com.neusoft.test.entity;
import java.util.Set;
public class Person { private int personid; private String name; private int age; private Set<Address> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address> getAddress() { return address; } public void setAddress(Set<Address> address) { this.address = address; } } |
實例化類2:
package com.neusoft.test.entity;
public class Address { private int addressid; private String addressdetail; private Person person;
public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } }
|
測試類:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address; import com.neusoft.test.entity.Person; import com.neusoft.test.utils.HibernateUtil;
public class test { @SuppressWarnings("unchecked") public static void main(String args[]) { Person person = new Person(); person.setName("ghgh"); person.setAge(33);
Address address = new Address(); address.setAddressdetail("gdsfasg"); address.setPerson(person);
Address address2 = new Address(); address2.setAddressdetail("rtyrtyt"); address2.setPerson(person);
Set set = new HashSet(); set.add(address); set.add(address2); person.setAddress(set);
Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); session.save(person); session.save(address); session.save(address2); tx.commit();// 提交事務
//從1的一段query Query query = session.createQuery("from Person"); List<Person> list = query.list(); for (Person p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:"); Set<Address> address1 = p.getAddress(); for (Address a : address1) { System.out.println(a.getAddressdetail()); } }
//從N的一段query Query query1 = session.createQuery("from Address"); List<Address> list1 = query1.list(); for (Address a : list1) { System.out .println(" 地址id:" + a.getAddressid() + " 詳情:" + a.getAddressdetail() + " 人id:" + a.getPerson().getPersonid() + " 人名:" + a.getPerson().getName() + " 年齡:" + a.getPerson().getAge()); } session.close();// 關閉session } } |
(7)inverse
只有集合標記(set、map、list、array、bag)纔有inverse屬性。
在 Hibernate 中,inverse 指定了關聯關係的方向。關聯關係中 inverse = false 的爲主動方,由主動方負責維護關聯關係。
在沒有設置 inverse=true 的狀況下,父子兩邊都維護父子關係 。
在 1-N 關係中,將 many 方設爲主控方(inverse = false) 將有助於性能改善(若是要國家元首記住全國人民的名字,不是太可能,但要讓全國人民知道國家元首,就容易的多);若將 1 方設爲主控方會額外多出 update 語句。插入數據時沒法同時插入外鍵列,於是沒法爲外鍵列添加非空約束。
(8)cascade
只有關係標記纔有cascade屬性:many-to-one,one-to-one ,set(map, bag, idbag, list, array) + one-to-many(many-to-many)
級聯指的是當主控方執行操做時,關聯對象(被動方)是否同步執行同一操做。
pojo和它的關係屬性的關係就是「主控方 -- 被動方」的關係,若是關係屬性是一個set,那麼被動方就是set中的每個元素。一個操做因級聯cascade可能觸發多個關聯操做。前一個操做叫「主控操做」,後一個操做叫「關聯操做」。
inverse 指的是關聯關係的控制方向,而cascade指的是層級之間的連鎖操做。
cascade屬性的可選值:
all : 全部狀況下均進行關聯操做。
none:全部狀況下均不進行關聯操做。這是默認值。
save-update:在執行save/update/saveOrUpdate時進行關聯操做。
delete:在執行delete時進行關聯操做
delete-orphan:表示刪除孤兒,delete-orphan在前者的基礎上增長了一點,針對持久化對象,若是它和它所關聯的對象的引用關係不存在了,則進行級聯刪除。
all-delete-orphan:包含all和delete-orphan的行爲
(9)雙向N-N關聯
雙向N-N關聯須要兩端都使用集合屬性,兩端都增長對集合屬性的訪問。雙向N-N關聯也必須使用鏈接表。
雙向N-N的關聯映射須要在兩邊增長集合元素,用於映射集合屬性。集合屬性應增長key子元素用以映射外鍵列,集合元素裏還應增長many-to-many子元素關聯實體類
注意:在雙向N-N關聯的兩邊都需定鏈接表的表名及外鍵列的列名。兩個集合元素set的table元素的值必須指定,並且必須相同。set元素的兩個子元素:key和many-to-many都必須指定column屬性,其中,key和many-to-many分別指定本持久化類和關聯類在鏈接表中的外鍵列名,因
此兩邊的key與many-to-many的column屬性交叉相同。也就是說,一邊的set元素的key的cloumn值爲a,many-to-many的column爲b;則另外一邊的set元素的key的column值b,many-to-many的column值爲a.
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <!-- 雙向N-N --> <!-- person_address_table爲額外的表,表列必須含有key對應的字段和elt,其中elt是固定的 --> <set name="address" table="person_address_table"> <key column="personid" /> <many-to-many column="addressid"/> </set> </class> <class name="Address2" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <!-- 雙向N-N --> <!-- person_address_table爲額外的表,表列必須含有key對應的字段和elt,其中elt是固定的 --> <set name="person" inverse="true" table="person_address_table"> <key column="addressid" /> <many-to-many column="personid"/> </set> </class> |
實例化類1:
package com.neusoft.test.entity;
import java.util.Set;
public class Person2 { private int personid; private String name; private int age; private Set<Address2> address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Set<Address2> getAddress() { return address; } public void setAddress(Set<Address2> address) { this.address = address; } }
|
實例化類2:
package com.neusoft.test.entity;
import java.util.Set;
public class Address2 { private int addressid; private String addressdetail; private Set<Person2> person;
public Set<Person2> getPerson() { return person; } public void setPerson(Set<Person2> person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
測試類:
package com.neusoft.test.action;
import java.util.HashSet; import java.util.List; import java.util.Set;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address2; import com.neusoft.test.entity.Person2; import com.neusoft.test.utils.HibernateUtil;
public class test2 { @SuppressWarnings("unchecked") public static void main(String args[]) {
Address2 address1 = new Address2(); address1.setAddressdetail("zxcvzxc");
Address2 address2 = new Address2(); address2.setAddressdetail("esdasd");
Person2 person1 = new Person2(); person1.setName("gfg"); person1.setAge(35);
Person2 person2 = new Person2(); person2.setName("gfg"); person2.setAge(35);
Set set_address = new HashSet(); set_address.add(address1); set_address.add(address2);
Set set_person = new HashSet(); set_person.add(person1); set_person.add(person2);
person1.setAddress(set_address); person2.setAddress(set_address); address1.setPerson(set_person); address2.setPerson(set_person);
Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
session.save(address1); session.save(address2); session.save(person1); session.save(person2);
tx.commit();// 提交事務
Query query = session.createQuery("from Person2"); List<Person2> list = query.list(); for (Person2 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:"); Set<Address2> address = p.getAddress(); for (Address2 a : address) { System.out.println(a.getAddressdetail()); } }
Query query1 = session.createQuery("from Address2"); List<Address2> list1 = query1.list(); for (Address2 a : list1) { System.out.println(" 地址id:" + a.getAddressid() + " 地址詳細:" + a.getAddressdetail()); Set<Person2> person = a.getPerson(); for (Person2 p : person) { System.out.println(" 人id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge()); } } session.close();// 關閉session } } |
(10)雙向1-1關聯
單向的1-1關聯有三種映射策略:基於主鍵,基於外鍵和使用鏈接表。雙向的1-1關聯一樣有這三種映射策略。
雙向的1-1關聯須要修改POJO類,讓兩邊都增長對關聯類的訪問
基於外鍵的雙向1-1關聯
映射配置:
<!-- 雙向1-1主實體 --> <class name="Person3" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <one-to-one name="address" cascade="all" property-ref="person"></one-to-one> </class> <!-- 雙向1-1從屬實體 --> <class name="Address3" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator /> </id> <property name="addressdetail" /> <!-- unique="true" 肯定是雙向的1-1 --> <many-to-one name="person" column="personid" unique="true"></many-to-one> </class> |
實例化類1:
package com.neusoft.test.entity;
public class Person3 { private int personid; private String name; private int age; private Address3 address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address3 getAddress() { return address; } public void setAddress(Address3 address) { this.address = address; } } |
實例化類2:
package com.neusoft.test.entity;
public class Address3 { private int addressid; private String addressdetail; private Person3 person;
public Person3 getPerson() { return person; } public void setPerson(Person3 person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
測試類:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address3; import com.neusoft.test.entity.Person3; import com.neusoft.test.utils.HibernateUtil;
@SuppressWarnings("unchecked") public class test3 { public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Person3 person=new Person3(); person.setName("uytua"); person.setAge(28); Address3 address=new Address3();
// 新建一個地址,而後添加給person address.setAddressdetail("wqesdasdasd"); address.setPerson(person); person.setAddress(address);
session.save(address); session.save(person); tx.commit();// 提交事務
Query query = session.createQuery("from Person3"); List<Person3> list = query.list(); for (Person3 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 關閉session } } |
基於主鍵的雙向1-1關聯
基於主鍵的映射策略:指一端的主鍵生成器使用foreign略,代表根據對方的主鍵來生成本身的主鍵,本身並不能獨立生成主鍵。
任意一邊均可以採用foreign主鍵生成器,代表根據對方主鍵生成本身的主鍵。
採用foreign主鍵生成器策略的一端增長one-to-one元素映射關聯屬性,其one-to-one屬性還應增長constrained=「true」屬性;另外一端增長one-to-one元素映射關聯屬性。
constrained(約束) :代表該類對應的表對應的數據庫表,和被關聯的對象所對應的數據庫表之間,經過一個外鍵引用對主鍵進行約束。
映射配置:
<!-- 基於主鍵的雙向1-1關聯 --> <class name="Person4" table="person_table"> <id name="personid"> <column name="personid"></column> <generator /> </id> <property name="name" /> <property name="age" /> <one-to-one name="address" cascade="all"></one-to-one> </class> <class name="Address4" table="address_table"> <id name="addressid"> <column name="addressid"></column> <generator> <param name="property">person</param> </generator> </id> <property name="addressdetail" /> <one-to-one name="person" constrained="true"></one-to-one> </class> |
實例化類1:
package com.neusoft.test.entity;
public class Person4 { private int personid; private String name; private int age; private Address4 address;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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 Address4 getAddress() { return address; } public void setAddress(Address4 address) { this.address = address; } } |
實例化類2:
package com.neusoft.test.entity;
public class Address4 { private int addressid; private String addressdetail; private Person4 person;
public Person4 getPerson() { return person; } public void setPerson(Person4 person) { this.person = person; } public int getAddressid() { return addressid; } public void setAddressid(int addressid) { this.addressid = addressid; } public String getAddressdetail() { return addressdetail; } public void setAddressdetail(String addressdetail) { this.addressdetail = addressdetail; } } |
測試類:
package com.neusoft.test.action;
import java.util.List;
import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Address4; import com.neusoft.test.entity.Person4; import com.neusoft.test.utils.HibernateUtil;
@SuppressWarnings("unchecked") public class test4 { public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction(); Person4 person=new Person4(); person.setName("uytua"); person.setAge(28); Address4 address=new Address4();
// 新建一個地址,而後添加給person address.setAddressdetail("wqesdasdasd"); address.setPerson(person); person.setAddress(address);
session.save(address); session.save(person); tx.commit();// 提交事務
Query query = session.createQuery("from Person4"); List<Person4> list = query.list(); for (Person4 p : list) { System.out.println("id:" + p.getPersonid() + " 姓名:" + p.getName() + " 年齡:" + p.getAge() + " 地址:" + p.getAddress().getAddressdetail()); } session.close();// 關閉session } } |
3 、繼承映射
對於面向對象的程序設計語言而言,繼承和多態是兩個最基本的概念。Hibernate 的繼承映射能夠理解持久化類之間的繼承關係。例如:人和學生之間的關係。學生繼承了人,能夠認爲學生是一個特殊的人,若是對人進行查詢,學生的實例也將被獲得。
Hibernate支持三種繼承映射策略:
每一個具體類一張表(table per concrete class) 將域模型中的每個實體對象映射到一個獨立的表中,也就是說不用在關係開數據模型中考慮域模型中的繼承關係和多態。
每一個類分層結構一張表(table per class hierarchy) 對於繼承關係中的子類使用同一個表,這就須要在數據庫表中增長額外的區分子類類型的字段。
每一個子類一張表(table per subclass) 域模型中的每一個類映射到一個表,經過關係數據模型中的外鍵來描述表之間的繼承關係。這也就至關於按照域模型的結構來創建數據庫中的表,並經過外鍵來創建表之間的繼承關係。
( 1 ) subclass 繼承映射 ( 單表繼承 )
採用 subclass 元素的繼承映射能夠實現對於繼承關係中的子類使用同一個表。(全部父類和子類都映射同一個表)
在這種映射策略下,整個繼承樹的全部實例都保保存在同一個表內。由於父類和子類的實例所有保存在同一個表中,所以須要在該表內增長一列,使用該列來區分每行記錄到低是哪一個類的實例----這個列被稱爲辨別者列(discriminator)。
在這種映射策略下,使用 subclass 來映射子類,使用 discriminator-value 指定辨別者列的值。
新建數據庫表person_table
映射配置:
<hibernate-mapping package="com.neusoft.test.entity"> <class name="Person" table="person_table" lazy="false"> <id name="personid"> <generator /> </id> <discriminator column="type" type="string" /> <property name="name" /> <property name="age" /> <subclass name="Student" discriminator-value="Student"> <property name="school_name" /> </subclass> <subclass name="Worker" discriminator-value="Worker"> <property name="company_name" /> </subclass> </class> </hibernate-mapping> |
實體類1:
package com.neusoft.test.entity;
public class Person { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
實體類2:
package com.neusoft.test.entity;
public class Student extends Person { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
實體類3:
package com.neusoft.test.entity;
public class Worker extends Person { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
測試類:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Person; import com.neusoft.test.entity.Student; import com.neusoft.test.entity.Worker; import com.neusoft.test.utils.HibernateUtil;
public class test { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
Person person = new Person(); person.setName("小麗"); person.setAge(22); Student student = new Student(); student.setName("小明"); student.setAge(19); student.setSchool_name("清華"); Worker worker = new Worker(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事務
List personList = session.createQuery("from Person").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person a = (Person)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年齡:"+a.getAge()+" 職業:"); //可以正確鑑別出正直的類型,HQL是支持多態查詢的。 if (a instanceof Student) { System.out.print("Student"); Student s=(Student)a; System.out.println(" 學校:"+s.getSchool_name()); } else if (a instanceof Worker) { System.out.print("Worker"); Worker w=(Worker)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什麼都不是"); }
// List list = session.createQuery("from java.lang.Object").list(); // for (Iterator iter = list.iterator(); iter.hasNext();){ // Object o =iter.next(); // if (o instanceof Student) { // Student s=(Student)o; // System.out.print(" 姓名:"+s.getName()+" 年齡:"+s.getAge()+" 職業:"); // System.out.print("Student"); // System.out.println(" 學校:"+s.getSchool_name()); // } else if (o instanceof Worker) { // Worker w=(Worker)o; // System.out.print(" 姓名:"+w.getName()+" 年齡:"+w.getAge()+" 職業:"); // System.out.print("Worker"); // System.out.println(" 公司:"+w.getCompany_name()); // }else{ // Person p=(Person)o; // System.out.print(" 姓名:"+p.getName()+" 年齡:"+p.getAge()+" 職業:"); // System.out.println("什麼都不是"); // } // } session.close();// 關閉session } } |
( 2 ) joined-subclass 繼承映射 (具體表繼承)
採用 joined-subclass 元素的繼承映射,每一個類映射一個表。(父類映射一個表,每一個子類也映射各自的表,子類表字段不是徹底的)
對象模型不用變化,存儲模型須要變化。
採用這種映射策略時,父類實例保存在父類表中,子類實例由父類表和子類表共同存儲。由於子類實例也是一個特殊的父類實例,所以必然也包含了父類實例的屬性。因而將子類和父類共有的屬性保存在父類表中,子類增長的屬性,則保存在子類表中。
在這種映射策略下,無須使用鑑別者列,但須要爲每一個子類使用 key 元素映射共有主鍵,該主鍵必須與父類標識屬性的列名相同。但若是繼承樹的深度很深,可能查詢一個子類實例時,須要跨越多個表,由於子類的數據一次保存在多個父類中。
子類增長的屬性能夠添加非空約束。由於子類的屬性和父類的屬性沒有保存在同一個表中
新建數據庫表person_table
student_table
worker_table
映射配置:
<class name="Person2" table="person_table"> <id name="personid"> <generator/> </id> <property name="name" /> <property name="age" /> <!--<joined-subclass>標籤:繼承映射 每一個類映射成一個表 --> <joined-subclass name="Student2" table="student_table"> <!-- <key>標籤:會在相應的表(當前映射的表)裏,加入一個外鍵 , 參照指向當前類的父類(當前Class標籤對象的表)--> <key column="id"/> <property name="school_name"/> </joined-subclass> <joined-subclass name="Worker2" table="worker_table"> <key column="id"/> <property name="company_name"/> </joined-subclass> </class> |
實體類1:
package com.neusoft.test.entity;
public class Person2 { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
實體類2:
package com.neusoft.test.entity;
public class Student2 extends Person2 { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
實體類3:
package com.neusoft.test.entity;
public class Worker2 extends Person2 { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
測試類:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.*; import com.neusoft.test.utils.HibernateUtil;
public class test2 { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
Person2 person = new Person2(); person.setName("小麗"); person.setAge(22); Student2 student = new Student2(); student.setName("小明"); student.setAge(19); student.setSchool_name("清華"); Worker2 worker = new Worker2(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事務
List personList = session.createQuery("from Person2").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person2 a = (Person2)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年齡:"+a.getAge()+" 職業:"); //可以正確鑑別出正直的類型,HQL是支持多態查詢的。 if (a instanceof Student2) { System.out.print("Student"); Student2 s=(Student2)a; System.out.println(" 學校:"+s.getSchool_name()); } else if (a instanceof Worker2) { System.out.print("Worker"); Worker2 w=(Worker2)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什麼都不是"); } session.close();// 關閉session } } |
採用 union-subclass 元素能夠實現將每個實體對象映射到一個獨立的表中。(父類映射一個表,每一個子類映射各自的表,子類表的字段是徹底的)
union-subclass 與 joined-subclass 映射策略相似:子類增長的屬性也能夠有非空約束 --- 即父類實例的數據保存在父表中,而子類實例的數據保存在子類表中。
與 joined-subclass 不一樣的是,子類實例的數據僅保存在子類表中,而在父類表中沒有任何記錄。
在這種映射策略下,子類表的字段會比父類表的映射字段要多,由於子類表的字段等於父類表的字段加子類增長屬性的總和
在這種映射策略下,既不須要使用鑑別者列,也無須使用 key 元素來映射共有主鍵.
新建數據庫表person_table
student_table
worker_table
映射配置:
<class name="Person3" table="person_table"> <id name="personid"> <generator/> </id> <property name="name" /> <property name="age" /> <!-- 使用<union-subclass>標籤來映射"每一個具體類映射成一張表"的映射關係 --> <union-subclass name="Student3" table="student_table"> <property name="school_name"/> </union-subclass> <union-subclass name="Worker3" table="worker_table"> <property name="company_name"/> </union-subclass> </class> |
實體類1:
package com.neusoft.test.entity;
public class Person3 { private int personid; private String name; private int age;
public int getPersonid() { return personid; } public void setPersonid(int personid) { this.personid = personid; } 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; } } |
實體類2:
package com.neusoft.test.entity;
public class Student3 extends Person3 { private String school_name;
public String getSchool_name() { return school_name; } public void setSchool_name(String schoolName) { school_name = schoolName; } } |
實體類3:
package com.neusoft.test.entity;
public class Worker3 extends Person3 { private String company_name;
public String getCompany_name() { return company_name; } public void setCompany_name(String companyName) { company_name = companyName; } } |
測試類:
package com.neusoft.test.action;
import java.util.Iterator; import java.util.List;
import org.hibernate.Session; import org.hibernate.Transaction;
import com.neusoft.test.entity.Person3; import com.neusoft.test.entity.Student3; import com.neusoft.test.entity.Worker3; import com.neusoft.test.utils.HibernateUtil;
public class test3 { @SuppressWarnings("unchecked") public static void main(String args[]) { Session session = HibernateUtil.getSession(); // 開啓事務 Transaction tx = session.beginTransaction();
Person3 person = new Person3(); person.setName("小麗"); person.setAge(22); Student3 student = new Student3(); student.setName("小明"); student.setAge(19); student.setSchool_name("清華"); Worker3 worker = new Worker3(); worker.setName("小王"); worker.setAge(26); worker.setCompany_name("neusoft");
session.save(person); session.save(student); session.save(worker); tx.commit();// 提交事務
List personList = session.createQuery("from Person3").list(); for (Iterator iter = personList.iterator(); iter.hasNext();) { Person3 a = (Person3)iter.next(); System.out.print(" 姓名:"+a.getName()+" 年齡:"+a.getAge()+" 職業:"); //可以正確鑑別出正直的類型,HQL是支持多態查詢的。 if (a instanceof Student3) { System.out.print("Student"); Student3 s=(Student3)a; System.out.println(" 學校:"+s.getSchool_name()); } else if (a instanceof Worker3) { System.out.print("Worker"); Worker3 w=(Worker3)a; System.out.println(" 公司:"+w.getCompany_name()); }else System.out.println("什麼都不是"); } session.close();// 關閉session } } |
(4)三種繼承關聯映射的比較:
1、 第一種:它把全部的數據都存入一個表中,優勢:效率好(操做的就是一個表);缺點:存在庸於字段,若是將庸於字段設置爲非空,則就沒法存入數據;
2、 第二種:井井有條,缺點:效率很差(表間存在關聯表)
3、 第三種:主鍵字段不能夠設置爲自增主鍵生成策略。
建議使用第一種