Video-No.02 尚硅谷_Hibernate4視頻教程

一、Ecplise hibernate插件安裝:java

    下載zip格式的Eclipse插件,(http://sourceforge.net/projects/jboss/files/JBossTools/JBossTools4.1.x/hibernatetools-Update-4.1.1.Final_2013-12-08_01-06-33-B605.zip) mysql

    Eclipse-》Help-》Install New Software.. -》add..-》Archive 選擇剛纔下載的hibernate插件sql

二、Hibernate開發步驟數據庫

    1)建立hibernate配置文件(hibernate.cfg.xml):配置數據庫相關配置信息和hibernate相關初始化配置信息
編程

<?xml version="1.0" encoding="UTF-8"?>
<!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="connection.username">root</property>
    	<property name="connection.password">root</property>
    	<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    	<property name="connection.url"><![CDATA[jdbc:mysql://127.0.0.1:3306/atguigu_hibernate?useUnicode=true&characterEncoding=utf8]]></property>
   
   	<!-- hibernate基本配置信息  -->
   		
   	<!-- hibernate數據庫方言 -->
   	<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
   		
   	<!-- 執行操做時,是否在後臺打印SQL語句 -->
   	<property name="show_sql">true</property>
   		
   	<!-- 是否對SQL語句進行格式化 -->
   	<property name="format_sql">true</property>
   		
   	<!-- 指定自動生成數據表的策略 -->
   	<!-- 
   		create: 會根據*.hbm,xml文件生成新的數據表,每次都會刪除上一次的數據表從新生成表
   		create-drop:會根據*.hbm,xml文件生成新的數據表,可是每次sessionFactory關閉都會刪除表
   		update:最經常使用的值,會根據*.hbm,xml文件生成新的數據表,若是*.hbm,xml所定義的表結構與數據庫中表結果不一樣,hibernate將更新數據表結構,但不會刪除已有的行和列
   		validate:會和數據庫中的表進行比較,若是*.hbm,xml配置文件中的列在數據庫中不存在,則拋出異常
   	-->
   	<property name="hbm2ddl.auto">update</property>
   		
   	<!-- 設置 Hibernate 的事務隔離級別 -->
   	<property name="connection.isolation">2</property>
   		
   	<!-- 刪除對象後, 使其 OID 置爲 null -->
   	<property name="use_identifier_rollback">true</property>
   		
       <!-- 配置 C3P0 數據源 -->
    	<property name="hibernate.c3p0.max_size">10</property>
    	<property name="hibernate.c3p0.min_size">5</property>
    	<property name="c3p0.acquire_increment">2</property>
    	
    	<property name="c3p0.idle_test_period">2000</property>
    	<property name="c3p0.timeout">2000</property>
    	
    	<property name="c3p0.max_statements">10</property>
    	
    	<!-- 設定 JDBC 的 Statement 讀取數據的時候每次從數據庫中取出的記錄條數 -->
    	<property name="hibernate.jdbc.fetch_size">100</property>
    	
    	<!-- 設定對數據庫進行批量刪除,批量更新和批量插入的時候的批次大小 -->
    	<property name="jdbc.batch_size">30</property>
   		
   	<!-- 指定關聯的map映射 -->
   	<mapping resource="com/shma/hibernate/entity/User.hbm.xml"/>
   	<mapping resource="com/shma/hibernate/entity/Worker.hbm.xml"/>	
    </session-factory>
    
</hibernate-configuration>

    2)建立持久化層實體類
緩存

package com.shma.hibernate.entity;

import java.sql.Blob;
import java.util.Date;

public class User {

	private Integer id;
	private String name;
	private Integer age;
	private Date date;
	
	private String oldContent;
	private Blob image;
	
	private String desc;
	
	public User() {
		super();
	}
	
	public User(String name, Integer age, Date date) {
		super();
		this.name = name;
		this.age = age;
		this.date = date;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public String getOldContent() {
		return oldContent;
	}

	public void setOldContent(String oldContent) {
		this.oldContent = oldContent;
	}

	public Blob getImage() {
		return image;
	}

	public void setImage(Blob image) {
		this.image = image;
	}
}

package com.shma.hibernate.entity;

public class Worker {

	private int id;
	private String name;
	
	private Pay pay;

	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 Pay getPay() {
		return pay;
	}

	public void setPay(Pay pay) {
		this.pay = pay;
	}
}

package com.shma.hibernate.entity;

public class Pay {

	private double monthPay;
	private double yearPay;
	private int yearDay;
	
	private Worker worker;
	
	public double getMonthPay() {
		return monthPay;
	}
	public void setMonthPay(double monthPay) {
		this.monthPay = monthPay;
	}
	public double getYearPay() {
		return yearPay;
	}
	public void setYearPay(double yearPay) {
		this.yearPay = yearPay;
	}
	public int getYearDay() {
		return yearDay;
	}
	public void setYearDay(int yearDay) {
		this.yearDay = yearDay;
	}
	public Worker getWorker() {
		return worker;
	}
	public void setWorker(Worker worker) {
		this.worker = worker;
	}
	
	
}

    3)建立對象-關係映射文件
安全

<?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.shma.hibernate.entity">
	<!-- 
		class:
		1)dynamic-insert:默認爲false,若是設置爲true,則表示保存一個insert時,動態生成sql語句,僅保存字段不能爲空的值
		2)dynamic-update:默認爲false,若是設置爲true,則表示更新一個update時,動態生成sql語句,僅更新修改的字段值
	 	3)select-before-update:在執行update以前,是否執行一次查詢,默認爲false
	 -->
    <class name="User" table="USER" select-before-update="true" dynamic-insert="true">
        <!-- 
      		id:
      		unsaved-value:表示持久化對象的oid若是爲該屬性值20,則認爲是一個臨時對象,執行保存操做
      		type:能夠爲java類型,也能夠設置爲hibernate類型
      		class:設置持久化類設置惟一標識符方式
      			increment:由hibernate先執行查詢max,再+1,併發下不安全
      			identity:底層數據庫自增,底層數據庫必須設置爲自增,適用於mysql、sqlserver
      			sequence:底層數據庫提供序列生成惟一標識符,如oracle
      			hilo:hibernate生成組件,在數據庫建立一張表,讀取並修改該表保存自增
      			native:經常使用,自動識別使用identity、sequence、hilo
         -->
        <id name="id" type="java.lang.Integer" unsaved-value="20">
            <column name="ID"  />
            <generator class="native" />
        </id>
        <!-- 
        	property:
        		1) access:制定hibernate默認屬性訪問策略,默認爲property,調用getter和setter方法,若設置爲field,則經過反射訪問
        		2) unique:設置屬性惟一值
        		3) index:設置索引
        		4) length: 設置字段長度
        		5) scale: 當字段爲double或float類型時,指定小數點後保留位數
        		6) formula: 派生屬性,sql表達式,用()括起來
         -->
        <property name="name" type="java.lang.String" 
        		access="property" unique="true" index="user_index" length="20">
            <column name="NAME" />
        </property>
        <property name="age" type="java.lang.Integer" index="user_index">
            <column name="AGE" />
        </property>
        <!-- 
        	在 Java 中, 表明時間和日期的類型包括: java.util.Date 和 java.util.Calendar. 
        	此外, 在 JDBC API 中還提供了 3 個擴展了 java.util.Date 類的子類: java.sql.Date, java.sql.Time 和 java.sql.Timestamp, 這三個類分別和標準 SQL 類型中的 DATE, TIME 和 TIMESTAMP 類型對                應在標準 SQL 中, DATE 類型表示日期, TIME 類型表示時間, TIMESTAMP 類型表示時間戳, 同時包含日期和時間信息
         -->
        <property name="date" type="timestamp">
            <column name="DATE" />
        </property>
        <property name="desc" formula="(select concat(name,',',date) from user t where t.id = id)"></property>
    	<!-- 映射大對象 -->
    	<property name="oldContent">
    		<column name="OLD_CONTENT" sql-type="text"></column>
    	</property>
    	
    	<!-- 
    	mysql數據庫不支持
    	<property name="realContent">
    		<column name="real_Content" sql-type="clob"></column>
    	</property>
    	 -->
    	
    	<property name="image">
    		<column name="image" sql-type="blob"></column>
    	</property>
    </class>
</hibernate-mapping>

    4)經過Hibernate API編程訪問操做數據庫代碼session

package com.shma.hibernate.entity;

import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.Test;

public class UserTest {

	@Test
	public void test() {
		//1) 建立一個SessionFactory對象
		SessionFactory sessionFactory = null;
		
		//建立Configuration配置對象,加載hibernate基本配置文件和關係對象映射文件
		Configuration configuration = new Configuration().configure();
		
		//棄用
//		sessionFactory = configuration.buildSessionFactory();
		
		//建立ServiceRegistry服務註冊對象,hibernate任何配置和服務都須要在這個對象中註冊後才能夠使用
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
											.applySettings(configuration.getProperties())
											.buildServiceRegistry();
		
		try {
			sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		//2) 建立一個Session對象
		Session session = sessionFactory.openSession();
		
		//3) 開啓事務
		Transaction transaction = session.beginTransaction();
		
		//4) 執行相關操做
		User user = null;
		try {
			user = new User("馬韶華", 23, new Date(new SimpleDateFormat("yyyy-MM-dd").parse("1989-11-10").getTime()));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		session.save(user);
		
		//5) 提交事務
		transaction.commit();
		
		//6) 關閉Session對象
		session.close();
		
		//7) 關閉SessionFactroy對象
		sessionFactory.close();
	}

}

三、Session併發

    1)session接口是hibernate向引用程序提供的操做數據庫的最主要的接口,提供了基本的增刪改和加載java對象的操做;oracle

    2)session具備一個緩存,被稱之爲hibernate一級緩存;位於緩存中的對象稱之爲持久化對象;

package com.shma.hibernate.entity;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class UserTest {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
						new ServiceRegistryBuilder().applySettings(configuration.getProperties())
													.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	/**
	 * clear(): 清理緩存
	 */
	@Test
	public void clear() {
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		User user2 = (User) session.get(User.class, 1);
		System.out.println(user2);
		session.clear();
		
		User user3 = (User) session.get(User.class, 1);
		System.out.println(user3);
	}
	
	/**
	 * reflesh():會強制發送 SELECT 語句, 以使 Session 緩存中對象的狀態和數據表中對應的記錄保持一致!使數據庫中的記錄同步到session緩存中
	 */
	@Test
	public void reflesh() {
		
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		session.refresh(user);
		System.out.println(user);
	}
	
	/**
	 * flush(): 使session緩存中的數據同步到數據庫中,爲了保存一致,可能會發送對應的SQL語句操做
	 * 
	 * flush()被調用的契機:
	 * 	1) 手動調用session.flush()方法
	 * 	2) 在Transaction對象提交事務以前,會先調用session對象的flush()方法,在提交事務
	 * 	3) 執行HQL或者QBC查詢時,若是緩存中持久化對象屬性發生變化,則會先flush()一次,以保證查詢出來的是最新的數據
	 * 	4) 若是持久化對象主鍵採用native生成OID(記錄的 ID 是由底層數據庫使用自增的方式生成),在調用save()方法時,先發生insert()語句,以建立主鍵id,保證save()方法後主鍵id是存在的
	 */
	@Test
	public void testSessionFlush() {
//		User user = (User) session.get(User.class, 1);
//		user.setAge(27);
//		user.setName("齊嬌嬌");
//		
//		session.flush(); //將session緩存中的數據同步到數據庫中,執行update方法,可是數據庫值沒有修改,沒有commit
//		System.out.println(user);
		
//		User user = (User) session.get(User.class, 1);
//		
//		//執行HQL或者QBC查詢時,若是緩存中持久化對象屬性發生變化,則會先flush()一次,以保證查詢出來的是最新的數據
//		User user2 = (User) session.createCriteria(User.class).uniqueResult();
//		
//		System.out.println(user == user2);
		
		
		User user3 = new User("孫威", 28, new Date());
		session.save(user3);

	}

	/**
	 * 驗證session緩存
	 */
	@Test
	public void testSessionCache() {
		User user = (User) session.get(User.class, 1);
		System.out.println(user);
		
		User user2 = (User) session.get(User.class, 1); //從session緩存中獲取,沒有查詢數據庫
		System.out.println(user2);
		
		System.out.println(user == user2);
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}

}

四、持久化對象狀態

    1)站在持久化的角度上,hibernate將對象分爲四種狀態:

         持久化狀態:存在session緩存中,存在數據庫記錄中,存在OID

            臨時狀態:不存在session緩存中,不存在數據庫記錄中,不存在OID    

            遊離狀態:存在OID,不存在session緩存中,可能存在數據庫記錄中,通常狀況下游離對象是由持久化對象轉變而來

            刪除狀態:存在OID,可是數據庫中不存在對應的記錄,不存在數據庫中,不存在session緩存中

package com.shma.hibernate.entity;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class UserTest2 {
	
	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	/**
	 * 調用存儲過程
	 */
	@Test
	public void testDoWork() {
		session.doWork(new Work() {
			
			@Override
			public void execute(Connection conn) throws SQLException {
				//調用存儲過程
			}
		});
	}
	
	/**
	 * evict():從緩存中移除指定的持久化對象
	 */
	@Test
	public void testEvict() {
		User user = (User) session.get(User.class, 8);
		User user2 = (User) session.get(User.class, 9);
		
		user.setName("nihao");
		user2.setName("haha");
		
		session.evict(user);
	
	}
	
	/**
	 * delete: 執行刪除操做. 只要 OID 和數據表中一條記錄對應, 就會準備執行 delete 操做
	 * 若 OID 在數據表中沒有對應的記錄, 則拋出異常
	 * 
	 * 能夠經過設置 hibernate 配置文件 hibernate.use_identifier_rollback 爲 true,
	 * 使刪除對象後, 把其 OID 置爲  null
	 */
	@Test
	public void testDelete() {
//		User user = new User();
//		user.setId(1);
//		session.delete(user); 
		
		User user = (User) session.get(User.class, 3);
		session.delete(user);
		
		System.out.println(user);
	}
	
	/**
	 * saveOrUpdate:
	 * 	包含了save和update方法,當對象處於遊離狀態時,則執行save操做,當對象處於持久化狀態時,則執行update操做
	 * 判斷是否爲臨時狀態:
	 * 	一、Java對象的OID爲null
	 * 	二、若是OID在數據庫表記錄中不存在,則會拋出異常,
	 * 	      除非映射文件中<id>設置了unsaved-value屬性,而且java對象中的oid值與設置的unsaved-value值一致
	 */
	@Test
	public void testSaveOrUpdate() {
//		User user = new User("王二", 22, new Date());
//		
//		//user處於遊離狀態,執行save
//		session.saveOrUpdate(user);
//		
//		// 執行save操做後user轉變爲持久化對象
//		user.setAge(45);
//		user.setName("王五");
//		
//		session.saveOrUpdate(user);
		
		User user2 = new User("aidai", 10, new Date());
		user2.setId(999);
		session.saveOrUpdate(user2);
	}
	
	/**
	 * update():
	 * 	1) 若更新一個持久化對象,不須要顯示調用update方法,由於在調用Transaction的commit方法
	 * 	   時,會調用session的flush()方法
	 * 	
	 * 	2) 若更新一個遊離對象,須要顯示的調用update方法,把一個遊離對象轉換爲持久化對象
	 * 
	 * 	須要注意的地方:
	 * 	一、不管要更新的遊離對象和數據庫表中的記錄是否一致(持久化對象會先檢查,不一致才執行update),都會調用update
	 * 	       操做,如何能讓 update方法再也不盲目的出發 update 語句呢 ? 在 .hbm.xml 文件的 class 節點設置
	 *    select-before-update=true (默認爲 false). 這個屬性的含義是在每次update以前先查詢一遍數
	 *    據庫,若是有修改在執行update,但一般不須要設置該屬性. 
	 *    
	 *  二、若數據表中沒有對應的記錄, 但還調用了 update 方法, 會拋出異常
	 *  
	 * 	三、當 update() 方法關聯一個遊離對象時, 
	 *    若是在 Session 的緩存中已經存在相同 OID 的持久化對象, 會拋出異常. 由於在 Session 緩存中
	 * 	      不能有兩個 OID 相同的對象!
	*/
	@Test
	public void testUpdate() {
		
		// 持久化對象,不須要顯示調用update方法
		User user = (User) session.get(User.class, 1);
//		user.setName("齊嬌嬌");
		
//		session.update(user);
		
//		session.clear();
		
		// 遊離狀態,必須顯示調用update方法
//		user.setName("馬韶華");
//		session.update(user);
		
		User user2 = (User) session.get(User.class, 1);
		session.update(user); //session 中已經存在user2
	}
	
	@Before
	public void init() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
						new ServiceRegistryBuilder().applySettings(configuration.getProperties())
													.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	/**
	 * 1) 執行get()方法:當即執行查詢操做加載對象,get爲當即檢索
	 *    執行load()方法:如不使用該對象,則不會執行查詢操做,而是返回一個代理對象,load爲延遲檢索
	 * 2) 當使用load延時檢索時,若是session關閉,可能會拋出LazyInitializationException異常
	 * 3) 若是查詢的oid數據庫沒有對應的數據記錄,而且session也沒有關閉
	 * 	  	get方法返回null
	 * 	  	load方法若是不使用實體對象屬性,加載不會拋出異常,使用的時候會拋出異常
	 * 		
	 */
	@Test
	public void testLoad() {
		User user = (User) session.load(User.class, 10);
		System.out.println(user.getClass().getName());
		
//		session.close();
		System.out.println(user);
	}
	
	/**
	 * get/load:根據一個oid,從數據庫中加載一個持久化對象到session緩存中
	 */
	@Test
	public void testGet() {
		User user = (User) session.get(User.class, 10);
		System.out.println(user.getClass().getName());
//		session.close();
		System.out.println(user);
	}
	
	/**
	 * persist(): 和save方法同樣保存記錄到持久化對象
	 * 和save()方法區別:當對一個OID不爲null的對象執行save時,會把對象以一個新oid保存到數據庫中,而persist則會拋出異常
	 */
	@Test
	public void testPersist() {
		User user = new User();
		user.setAge(20);
		user.setDate(new Date());
		user.setName("zhangsan");
		user.setId(10); // 拋出異常
		
		session.persist(user);
	}
	
	/**
	 * save():用於將臨時對象轉換爲持久化對象,插入記錄
	 * 執行步驟:1) 使一個臨時對象保存到session緩存中,轉換爲持久化對象
	 * 		 2) 爲持久化對象生成惟一的UID
	 * 		 3) 執行一條insert語句:在flush緩存時
	 * 		 4) 在save以前的設置id是無效的
	 * 		 5) 在save以後的設置id是不能被修改的,修改會拋出異常
	 */
	@Test
	public void testSave() {
		
		User user = new User();
		user.setAge(20);
		user.setDate(new Date());
		user.setName("zhangsan");
//		user.setId(10); // 設置id是無效的
		
		session.save(user);
		
		System.out.println(user);
		
		user.setId(10); //save()後修改id,拋出異常
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	   @Test
	public void testWorker() {
		Worker worker = new Worker();
		Pay pay = new Pay();
		pay.setMonthPay(13000.23d);
		pay.setYearDay(5);
		pay.setYearPay(153422.12344d);
		
		worker.setName("馬韶華");
		worker.setPay(pay);
		
		session.save(worker);
	}

}

五、映射對象關係

    1)單向多對一

package com.shma.hibernate.entity.n21;

public class Customer {

	private int customerId;
	
	private String customerName;

	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	@Override
	public String toString() {
		return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]";
	}

}

package com.shma.hibernate.entity.n21;

public class Order {

	private int orderId;
	
	private String orderName;
	
	private Customer customer;

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	public Customer getCustomer() {
		return customer;
	}

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

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]";
	}
	
}

package com.shma.hibernate.entity.n21;

import static org.junit.Assert.*;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestN21 {

	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
						new ServiceRegistryBuilder().applySettings(configuration.getProperties())
													.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testMany2OneDel() {
//		Order order = (Order)session.get(Order.class, 2); 
//		session.delete(order);
//		
//		session.delete(order.getCustomer());
		
		//在不設定級聯關係的狀況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接刪除 1 這一端的對象
		Customer customer = (Customer) session.get(Customer.class, 2);
		session.delete(customer);
		
		
	}
	
	@Test
	public void testMany2OneUpdate() {
		Order order = (Order)session.get(Order.class, 1);
		order.setOrderName("order-112222");
		order.getCustomer().setCustomerName("AAAAAAAA");
	}
	
	@Test
	public void testMany2OneGet() {
		Order order = (Order)session.get(Order.class, 1);
		System.out.println(order);
		System.out.println(order.getCustomer().getClass());
		
		//若是session被關閉,將拋出異常
//		session.close();

		//延時加載Customer
		Customer customer = order.getCustomer();
		System.out.println(customer);
		
		System.out.println(customer.getClass());
		
	}
	
	@Test
	public void testMany2OneSave() {
//		Customer customer = new Customer();
//		customer.setCustomerName("AAA");
//		
//		Order order01 = new Order();
//		order01.setOrderName("Order-01");
//		
//		Order order02 = new Order();
//		order02.setOrderName("Order-02");
//		
//		order01.setCustomer(customer);
//		order02.setCustomer(customer);
//		
//		//先savecustomer,會saveorder,執行三次insert
//		session.save(customer);
//		session.save(order01);
//		session.save(order02);
		
		
		Customer customer = new Customer();
		customer.setCustomerName("BBB");
		
		Order order01 = new Order();
		order01.setOrderName("Order-03");
		
		Order order02 = new Order();
		order02.setOrderName("Order-04");
		
		order01.setCustomer(customer);
		order02.setCustomer(customer);
		
		//先save order,會save customer,執行三次insert,會執行2次update
		session.save(order01);
		session.save(order02);
		session.save(customer);
		
		
		
	}

}
<?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>
    <class name="com.shma.hibernate.entity.n21.Customer" table="CUSTOMERS">
        <id name="customerId" type="int">
            <column name="CUSTOMER_ID" />
            <generator class="native" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" />
        </property>
        
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.shma.hibernate.entity.n21">
    <class name="Order" table="ORDERS">
        <id name="orderId" type="int">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" />
        </property>
        
        <!-- 多對一映射關係
        	name:多這一端的一那一端的屬性名稱
        	class:一端的類型
        	column:一那一端對應在多端的外鍵名稱
         -->
        <many-to-one name="customer" class="Customer">
        	<column name="customer_id"></column>
        </many-to-one>
    </class>
</hibernate-mapping>

    2)雙向一對多

package com.shma.hibernate.entity.n21.bath;

import java.util.HashSet;
import java.util.Set;

public class Customer {

	private int customerId;
	
	private String customerName;
	
	/**
	 * 一、聲明集合須要使用接口,由於hibernate延遲加載,在獲取集合的時候是獲取到的hibernate內部集合實例
	 * 二、須要把集合進行初始化, 能夠防止發生空指針異常
	 */
	private Set<Order> orders = new HashSet<>();

	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public Set<Order> getOrders() {
		return orders;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

}

package com.shma.hibernate.entity.n21.bath;

public class Order {

	private int orderId;
	
	private String orderName;
	
	private Customer customer;

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	public Customer getCustomer() {
		return customer;
	}

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

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName + ", customer=" + customer + "]";
	}
	
}

package com.shma.hibernate.entity.n21.bath;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class Test12N {

	private SessionFactory sessionFactory = null;
	private Session session = null;
	private Transaction transaction = null;
	
	@Before
	public void init() {
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = 
						new ServiceRegistryBuilder().applySettings(configuration.getProperties())
													.buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}
	
	@After
	public void destory() {
		transaction.commit();
		session.close();
		sessionFactory.close();
	}
	
	@Test
	public void testOne2ManyDel() {
		//在不設定級聯關係的狀況下, 且 1 這一端的對象有 n 的對象在引用, 不能直接刪除 1 這一端的對象
		Customer customer = (Customer) session.get(Customer.class, 1);
		session.delete(customer.getOrders().iterator().next());
	}
	
	@Test
	public void testOne2ManyUpdate() {
		
		Customer customer = (Customer) session.get(Customer.class, 1);
		customer.setCustomerName("CCCCCC");
		
		Customer customer2 = (Customer) session.get(Customer.class, 2);
		customer.getOrders().iterator().next().setCustomer(customer2);
		
	}
	
	@Test
	public void testOne2ManyGet() {
		Customer customer = (Customer) session.get(Customer.class, 1);
		System.out.println(customer.getCustomerName());
		//延時加載
		//返回的多的一端的集合時 Hibernate 內置的集合類型. 
		//該類型具備延遲加載和存放代理對象的功能.
		System.out.println(customer.getOrders().getClass());
		
		//3. 可能會拋出 LazyInitializationException 異常 
//		session.close();
		
		System.out.println(customer.getOrders().iterator().next().getOrderName());
		//再須要使用集合中元素的時候進行初始化. 
	}
	
	@Test
	public void testOne2ManySave() {
		
//		Customer customer = new Customer();
//		customer.setCustomerName("AAA");
//		
//		Order order01 = new Order();
//		order01.setOrderName("Order-01");
//		
//		Order order02 = new Order();
//		order02.setOrderName("Order-02");
//		
//		order01.setCustomer(customer);
//		order02.setCustomer(customer);
//		
//		customer.getOrders().add(order01);
//		customer.getOrders().add(order02);
//		
//		//先savecustomer,會saveorder,執行三次insert
//		session.save(customer);
//		session.save(order01);
//		session.save(order02);
		
		
		Customer customer = new Customer();
		customer.setCustomerName("BBB");
		
		Order order01 = new Order();
		order01.setOrderName("Order-03");
		
		Order order02 = new Order();
		order02.setOrderName("Order-04");
		
		order01.setCustomer(customer);
		order02.setCustomer(customer);
		
		customer.getOrders().add(order01);
		customer.getOrders().add(order02);
		
		//先save order,會save customer,執行三次insert,會執行2次update
		session.save(order01);
		session.save(order02);
		session.save(customer);
		
		
		
	}

}
<?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.shma.hibernate.entity.n21.bath">
    <class name="Customer" table="CUSTOMERS">
        <id name="customerId" type="int">
            <column name="CUSTOMER_ID" />
            <generator class="native" />
        </id>
        <property name="customerName" type="java.lang.String">
            <column name="CUSTOMER_NAME" />
        </property>
        
        <!--
        	1對多映射關係那個屬性集合
        	set:映射集合爲set類型
        	table:set中集合類型的所對應的表名,須要與多對一中的表名一致
        	inverse:指定由哪一方來維護關聯關係. 一般設置爲 true, 以指定由多的一端來維護關聯關係
        	cascade:級聯操做,save-update級聯保存並修改關聯,delete:級聯刪除
        	order-by:排序,字段是數據庫裏面的字段類型
        	name:1的集合屬性名稱
         -->
        <set name="orders" table="ORDERS" inverse="true" order-by="order_name desc">
			<!-- 執行多的表中的外鍵列的名字 -->
			<key column="CUSTOMER_ID"></key>
			<!-- 指定映射類型 -->
			<one-to-many class="Order"/>       
        </set>
    </class>
</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-7-18 15:21:35 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.shma.hibernate.entity.n21.bath">
    <class name="Order" table="ORDERS">
        <id name="orderId" type="int">
            <column name="ORDER_ID" />
            <generator class="native" />
        </id>
        <property name="orderName" type="java.lang.String">
            <column name="ORDER_NAME" />
        </property>
        
        <!-- 多對一映射關係
        	name:多這一端的一那一端的屬性名稱
        	class:一端的類型
        	column:一那一端對應在多端的外鍵名稱
         -->
        <many-to-one name="customer" class="Customer">
        	<column name="customer_id"></column>
        </many-to-one>
    </class>
</hibernate-mapping>
相關文章
相關標籤/搜索