1. 程式人生 > >hibernate系列之四

hibernate系列之四

new 獲取 冗余 posit Coding 對象關系 color type 一次

數據庫中表之間的關系:

一對一、一對多、多對多

技術分享圖片

一對多的建表原則:在多的一方創建外鍵指向一的一方的主鍵;

多對多的建表原則:創建一個中間表,中間表中至少有兩個字段作為外鍵分別指向多對多雙方的主鍵;

一對一建表原則:唯一外鍵對應:假設一對一中的任意一方為多,在多的一方創建外鍵指向一的一方的主鍵,將外鍵設置為唯一

      主鍵對應:一方的主鍵作為另一方的主鍵;

在hibernate中采用java對象關系描述數據表之間的關系:

技術分享圖片

一對多的映射關系的實現案例:

客戶實體類:在hibernate系列一中已經實現點擊連接查看:https://www.cnblogs.com/wang-xuan/p/9195795.html

同時在客戶實體類中添加屬性:

//一個客戶對應多個聯系人
	private Set<LinkMan> linkMans = new HashSet<LinkMan>();
public Set<LinkMan> getLinkMans() {
		return linkMans;
	}
	public void setLinkMans(Set<LinkMan> linkMans) {
		this.linkMans = linkMans;
	}

實現聯系人實體類LinkMan:

package com.itwx.hibernate.pojo;

public class LinkMan {

	private Long lkm_id;
	private String lkm_name;
	private String lkm_gender;
	private String lkm_phone;
	private String lkm_mobile;
	private String lkm_email;
	private String lkm_qq;
	private String lkm_position;
	private String lkm_memo;
	
	private Customer customer;

	public Long getLkm_id() {
		return lkm_id;
	}

	public void setLkm_id(Long lkm_id) {
		this.lkm_id = lkm_id;
	}

	public String getLkm_name() {
		return lkm_name;
	}

	public void setLkm_name(String lkm_name) {
		this.lkm_name = lkm_name;
	}

	public String getLkm_gender() {
		return lkm_gender;
	}

	public void setLkm_gender(String lkm_gender) {
		this.lkm_gender = lkm_gender;
	}

	public String getLkm_phone() {
		return lkm_phone;
	}

	public void setLkm_phone(String lkm_phone) {
		this.lkm_phone = lkm_phone;
	}

	public String getLkm_mobile() {
		return lkm_mobile;
	}

	public void setLkm_mobile(String lkm_mobile) {
		this.lkm_mobile = lkm_mobile;
	}

	public String getLkm_email() {
		return lkm_email;
	}

	public void setLkm_email(String lkm_email) {
		this.lkm_email = lkm_email;
	}

	public String getLkm_qq() {
		return lkm_qq;
	}

	public void setLkm_qq(String lkm_qq) {
		this.lkm_qq = lkm_qq;
	}

	public String getLkm_position() {
		return lkm_position;
	}

	public void setLkm_position(String lkm_position) {
		this.lkm_position = lkm_position;
	}

	public String getLkm_memo() {
		return lkm_memo;
	}

	public void setLkm_memo(String lkm_memo) {
		this.lkm_memo = lkm_memo;
	}

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	
}

配置LinkMan.hbm.xml的映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.itwx.hibernate.pojo.LinkMan" table="linkman">
		<id name="lkm_id" column="lkm_id">
			<generator class="native" />
		</id>
		<property name="lkm_name" column="lkm_name" />
		<property name="lkm_gender" column="lkm_gender" />
		<property name="lkm_phone" column="lkm_phone" />
		<property name="lkm_mobile" column="lkm_mobile" />
		<property name="lkm_email" column="lkm_email" />
		<property name="lkm_qq" column="lkm_qq" />
		<property name="lkm_position" column="lkm_position" />
		<!-- 配置關聯對象 -->
		<!--  
			many-to-one:代表多對一:
				name屬性:在實體類中的屬性:一的一方的對象的名稱;
				class屬性:一的一方的類的全路徑
				column:表中的外鍵,在一的一方中配置的外鍵;
		-->
		<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
			column="lkm_cust_id" />
	</class>
</hibernate-mapping>

核心配置文件hibernate.cfg.xml

<!-- 配置加載映射文件:全路徑-->
			<mapping resource="com/itwx/hibernate/pojo/Customer.hbm.xml"/>
			<mapping resource="com/itwx/hibernate/pojo/LinkMan.hbm.xml"/>

Customer.hbm.xml配置文件添加一對多的關系映射配置

<!-- 配置多一之間的映射關系 -->
    	<!-- 
    		set標簽:name屬性:在實體類中的屬性,指多的一方的集合的屬性名稱
    		key標簽:column:多的一方的外鍵的名稱
    		one-to-many標簽:class屬性:多的一方的類的全路徑
    	-->
		<set name="linkMans">
			<key column="lkm_cust_id" />
			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
		</set>

測試類中進行測試一對多的關系映射

@Test
	public void test4() {
		// 獲取當前與線程綁定的session
		Session session = HibernateUtils.getCurrentSession();
		// 開啟事務
		Transaction transaction = session.beginTransaction();
		// 創建關系對象
		Customer customer = new Customer();// 此處可以使用帶參構造方法
		customer.setCust_name("張三");
		customer.setCust_source("產品");

		LinkMan linkMan1 = new LinkMan();
		linkMan1.setLkm_name("周芷若");
		linkMan1.setLkm_phone("1223445");
		LinkMan linkMan2 = new LinkMan();
		linkMan2.setLkm_name("張無忌");
		linkMan2.setLkm_gender("男");
		// 建立關系
		/**
		 * 首先獲取到set集合對象,然後才能進行添加元素; 所以先調用getXXX()方法獲取對象,然後add
		 */
		// 客戶關聯聯系人
		customer.getLinkMans().add(linkMan1);
		customer.getLinkMans().add(linkMan2);
		// 聯系人關聯客戶
		linkMan1.setCustomer(customer);
		linkMan2.setCustomer(customer);
		// 執行操作
		session.save(linkMan1);
		session.save(linkMan2);
		session.save(customer);
		// 提交事務
		transaction.commit();
          //執行結果 /** * Hibernate: insert into linkman (lkm_name, lkm_gender, lkm_phone, * lkm_mobile, lkm_email, lkm_qq, lkm_position, lkm_cust_id) values (?, * ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into linkman (lkm_name, * lkm_gender, lkm_phone, lkm_mobile, lkm_email, lkm_qq, lkm_position, * lkm_cust_id) values (?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into * customer (cust_name, cust_source, cust_industry, cust_level, * cust_phone, cust_mobile) values (?, ?, ?, ?, ?, ?) Hibernate: update * linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, lkm_mobile=?, * lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? where lkm_id=? * Hibernate: update linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, * lkm_mobile=?, lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? * where lkm_id=? Hibernate: update linkman set lkm_cust_id=? where * lkm_id=? Hibernate: update linkman set lkm_cust_id=? where lkm_id=? */ }

級聯操作:

指在主控方執行保存、更新和刪除操作時,其關聯(被控方)也執行相同操作。在映射文件中通過對cascade屬性的設置來控制是否對關聯對象采用級聯操作,級聯操作對各種關聯關系都是有效的;

級聯具有方向性:在保存一的一方級聯多的一方和在多的一方可以級聯一的一方;

在映射文件中配置cascade=“save-update”;

級聯刪除和級聯保存、更新:誰是主控方,則可以在映射文件中配置cascade=“delete、save-update”,也可以同時配置;

級聯刪除:在set標簽中配置cascade=“delete”或者在mony-to-one中配置cascade屬性;

<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
			column="lkm_cust_id" cascade="save-update"  />

或者

<set name="linkMans" cascade="delete,save-update" >
			<key column="lkm_cust_id" />
			<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
		</set>

防止SQL語句冗余:雙向維護關系,持久態對象可以自動更新數據庫,更新客戶的時候會修改一次外鍵,更新聯系人的時候會修改一次外鍵,所以會產生SQL語句冗余;

解決方案:一方放棄外鍵的維護,通常交給多的一方去維護,所以一的一方就需要放棄維護,即需要配置inverse=“true”;

<set name="linkMans" cascade="delete,save-update" inverse="true">
<key column="lkm_cust_id" />
<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
</set>

hibernate系列之四