hibernate之關聯映射

1.集合映射

      需求:用戶購買,填寫地址,一個用戶可以對應多個地址

首先是javabean設計

public class User {

	private int userId;
	private String userName;
	// 一個用戶,對應的多個地址
	private Set<String> address;
	private List<String> addressList = new ArrayList<String>(); 
	//private String[] addressArray; // 映射方式和list一樣     <array name=""></array>
	private Map<String,String> addressMap = new HashMap<String, String>();
	
}

然後是xml配置

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.a_collection">
	
	<class name="User" table="t_user">
		<id name="userId" column="id">
			<generator class="native"></generator>
		</id>	
		<property name="userName"></property>
		
		<!-- 
			set集合屬性的映射
				name 指定要映射的set集合的屬性
				table 集合屬性要映射到的表
				key  指定集合表(t_address)的外鍵字段
				element 指定集合表的其他字段
					type 元素類型,一定要指定
		 -->
		 <set name="address" table="t_address">
		 	<key column="uid"></key>
		 	<element column="address" type="string"></element>
		 </set>
		 
		 <!-- 
		 	list集合映射
		 		list-index  指定的是排序列的名稱 (因爲要保證list集合的有序)
		  -->
		  <list name="addressList" table="t_addressList">
		  	  <key column="uid"></key>
		  	  <list-index column="idx"></list-index>
		  	  <element column="address" type="string"></element>
		  </list>
		  
		  <!-- 
		  	map集合的映射
		  		key  指定外鍵字段
		  		map-key 指定map的key 
		  		element  指定map的value
		   -->
		  <map name="addressMap" table="t_addressMap">
		  	<key column="uid"></key>
		  	<map-key column="shortName" type="string" ></map-key>
		  	<element column="address" type="string" ></element>
		  </map>
           </class>
</hibernate-mapping>

保存方法相關代碼:

// 保存set
	@Test
	public void testSaveSet() throws Exception {
		Session session = sf.openSession();
		session.beginTransaction();
		
		//-- 保存
		Set<String> addressSet = new HashSet<String>();
		addressSet.add("廣州");
		addressSet.add("深圳");
		// 用戶對象
		User user = new User();
		user.setUserName("Jack");
		user.setAddress(addressSet);
		
		// 保存
		session.save(user);
		
		session.getTransaction().commit();
		session.close();
	}
	
	// 保存list/map
	@Test
	public void testSaveList() throws Exception {
		Session session = sf.openSession();
		session.beginTransaction();
		User user = new User();
		user.setUserName("Tom");
//		// 用戶對象  --  list
//		user.getAddressList().add("廣州");
//		user.getAddressList().add("深圳");
//		// 保存
//		session.save(user);
		
		// 用戶對象  --  Map
		user.getAddressMap().put("A0001", "廣州");
		user.getAddressMap().put("A0002", "深圳");
		
		// 保存
		session.save(user);
		
		session.getTransaction().commit();
		session.close();
	}


2.關聯映射
  

需求1

         部門與員工

                     一個部門有多個員工;       【一對多】

                     多個員工,屬於一個部門    【多對一】

需求2

         項目與開發員工

                   一個項目,有多個開發人員!

                   一個開發人員,參與多個項目!   【多對多】

 

public class Dept {

	private int deptId;
	private String deptName;
	// 【一對多】 部門對應的多個員工
	private Set<Employee> emps = new HashSet<Employee>();
	

這裏省略get和set方法代碼

public class Employee {

	private int empId;
	private String empName;
	private double salary;
	// 【多對一】員工與部門
	private Dept dept;

然後是xml配置

Dept.hbm.xml 

<hibernate-mapping package="cn.itcast.b_one2Many">
	
	<class name="Dept" table="t_dept">
		<id name="deptId">
			<generator class="native"></generator>   <span style="color:#ff0000;">native表示框架會自動根據數據庫底層選擇對應的自增方式</span>
		</id>	
		<property name="deptName" length="20"></property>
		
		<!-- 
			一對多關聯映射配置  (通過部門管理到員工)
			Dept 映射關鍵點:
			1.  指定 映射的集合屬性: "emps"
			2.  集合屬性對應的集合表: "t_employee"
			3.  集合表的外鍵字段   "t_employee. dept_id"
			4.  集合元素的類型
			
		 -->
		 <set name="emps">   <!-- table="t_employee" -->
		 	 <key column="dept_id"></key>
		 	 <one-to-many class="Employee"/>如果配置文件和實體類不在一個包下,class後要加上包名
		 </set>
		 
		 
	</class>
	

</hibernate-mapping>

Employee.hbm.xml,兩處外鍵字段要相同都是dept_id

<hibernate-mapping package="cn.itcast.b_one2Many">
	
	<class name="Employee" table="t_employee">
		<id name="empId">
			<generator class="native"></generator>
		</id>	
		<property name="empName" length="20"></property>
		<property name="salary" type="double"></property>
		
		<!-- 
			多對一映射配置
			Employee 映射關鍵點:
			1.  映射的部門屬性  :  dept
			2.  映射的部門屬性,對應的外鍵字段: dept_id
			3.  部門的類型
		 -->
		 <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
		 
	</class>
	

</hibernate-mapping>

測試

public class App {
	
	private static SessionFactory sf;<span style="color:#ff0000;">靜態方便類直接調用,而且只加載一次</span>
	static {
		sf = new Configuration()
			.configure()
			.addClass(Dept.class)   
			.addClass(Employee.class)   // 測試時候使用
			.buildSessionFactory();
	}

	// 保存, 部門方 【一的一方法操作】
	@Test
	public void save() {
		
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 部門對象
		Dept dept = new Dept();
		dept.setDeptName("應用開發部");
		// 員工對象
		Employee emp_zs = new Employee();
		emp_zs.setEmpName("張三");
		Employee emp_ls = new Employee();
		emp_ls.setEmpName("李四");
		// 關係
		dept.getEmps().add(emp_zs);
		dept.getEmps().add(emp_ls);

		// 保存
		session.save(emp_zs);
		session.save(emp_ls);
		session.save(dept); // 保存部門,部門下所有的員工  
		
		session.getTransaction().commit();
		session.close();
		/*
		 *  結果
		 *  Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_dept (deptName) values (?)
			Hibernate: update t_employee set deptId=? where empId=?    維護員工引用的部門的id
			Hibernate: update t_employee set deptId=? where empId=?
		 */
	}
	// 【推薦】 保存, 部員方 【多的一方法操作】
	@Test
	public void save2() {
		
		Session session = sf.openSession();
		session.beginTransaction();
		
		// 部門對象
		Dept dept = new Dept();
		dept.setDeptName("綜合部");
		// 員工對象
		Employee emp_zs = new Employee();
		emp_zs.setEmpName("張三");
		Employee emp_ls = new Employee();
		emp_ls.setEmpName("李四");
		// 關係<span style="color:#ff0000;">,不要忘記添加關係維護</span>
		emp_zs.setDept(dept);
		emp_ls.setDept(dept);
		
		
		// 保存
		session.save(dept); // 先保存一的方法,<span style="color:#ff0000;">注意session保存的順序</span>
		session.save(emp_zs);
		session.save(emp_ls);// 再保存多的一方,關係回自動維護(映射配置完)
		
		session.getTransaction().commit();
		session.close();
		/*
		 *  結果
		 *  Hibernate: insert into t_dept (deptName) values (?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
			少生成2條update  sql
		 */
	}
	
}

總結:

  在一對多與多對一的關聯關係中,保存數據最好的通過多的一方來維護關係,這樣可以減少update語句的生成,從而提高hibernate的執行效率!



Inverse屬性



Inverse屬性,是在維護關聯關係的時候起作用的。


      表示控制權是否轉移。(在一的一方起作用)


 


Inverse , 控制反轉。


Inverse = false  不反轉;   當前方有控制權


                   True  控制反轉; 當前方沒有控制權

除了對獲取數據沒有影響,對於保存數據,解除關聯關係,刪除數據都有影響。


cascade屬性

cascade 表示級聯操作  【可以設置到一的一方或多的一方】

         none         不級聯操作, 默認值

         save-update     級聯保存或更新

         delete                 級聯刪除

         save-update,delete    級聯保存、更新、刪除

         all                 同上。級聯保存、更新、刪除



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章