1. 程式人生 > >Hibernate(六)實現一對多、多對一對映關聯關係

Hibernate(六)實現一對多、多對一對映關聯關係

一對多、多對一這種關係在現實生活中很多,例如部門與員工的關係,學校裡班級與學生的關係...

那麼在具體的系統實現中如果i實現這種關聯關係呢?這裡以部門和員工的關係為例。

部門實體類

package test.hibernate.hbmOneToMany;

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

public class Department {

	private Integer id;
	private String name;
	private Set<Employee> employees = new HashSet<Employee>();

	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 Set<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "[employee:id=" + id + ",name=" + name + "]";
	}

}
員工實體類
package test.hibernate.hbmOneToMany;

public class Employee {

	private Integer id;
	private String name;
	private Department department=new Department();

	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 Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

}
部門對映Department.hbm.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="test.hibernate.hbmOneToMany">
	<class name="Department" table="department">
		<id name="id" type="integer" column="id">
			<generator class="native" />
		</id>
		<property name="name" />
		<!-- inverse屬性:預設為false,表示本方維護關聯關係;
		                                        如果設為true,表示本方不維護關聯關係 
		     只是影響是否能設定外來鍵列的值(設成有效值或是null值),對獲取資訊沒有影響                                   
		-->
		<set name="employees" inverse="false">
			<key column="departmentId"></key>
			<one-to-many class="Employee" />
		</set>
	</class>
</hibernate-mapping>

inverse=false



inverse=true



員工對映檔案Employee.hbm.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="test.hibernate.hbmOneToMany">
	<class name="Employee" table="employee">
		<id name="id" type="integer" column="id">
			<generator class="native" />
		</id>
		<property name="name"/>
		<many-to-one name="department" class="Department" column="departmentId"></many-to-one>

	</class>
</hibernate-mapping>
測試類App
package test.hibernate.hbmOneToMany;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Department.class)// 新增Hibernate實體類(載入對應的對映檔案)
			.addClass(Employee.class)//
			.buildSessionFactory();

	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 構建物件
		Department department = new Department();
		department.setName("開發部");

		Employee employee = new Employee();
		employee.setName("張三");

		Employee employee2 = new Employee();
		employee2.setName("李瑟");

		// 關聯起來
		employee.setDepartment(department);
		employee2.setDepartment(department);
		department.getEmployees().add(employee);
		department.getEmployees().add(employee2);

		// 儲存
		session.save(department);
		session.save(employee);
		session.save(employee2);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 獲取到部門關聯的員工
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();

		// 獲取資料
		Department department = (Department) session.get(Department.class, 1);
		System.out.println(department.getId());
		System.out.println(department.getName());
		System.out.println(department.getEmployees());

		session.getTransaction().commit();
		session.close();
	}

	// 解除關聯關係
	@Test
	public void testRemoveRelation() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------
		// 從員工解除與部門的關聯,也就是員工不再屬於任何部門
		// Employee employee=(Employee) session.get(Employee.class, 8);
		// employee.setDepartment(null);

		// 從部門解除員工關係
		Department department = (Department) session.get(Department.class, 1);
		// 要使這句有效,需將對映檔案裡的inverse設為false,即部門恢復維護關係
		department.getEmployees().clear();

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 刪除部門及對員工的影響
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 刪除員工,對部門沒有影響
		// Employee employee=(Employee) session.get(Employee.class, 9);
		// session.delete(employee);

		/*
		 * 如果沒有關聯的員工,能刪除
		 * 如果有關聯的員工且inverse=true,由於不能維護關聯關係,會直接執行刪除且報異常
		 * 如果有關聯的員工且inverse=false,由於可以維護關聯關係,會將員工的外來鍵設為null,再刪除自己
		 */
		Department department = (Department) session.get(Department.class, 8);
		session.delete(department);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}
}

級聯是指操作主物件時,對關聯的物件也做相同的操作。 預設為none,代表不級聯。可設為:delete、save-update、all、none... 一般在多對一或一對多的時候使用級聯,多對多的時候不使用級聯。

修改後的測試程式碼:

Department.hbm.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="test.hibernate.hbmOneToMany">
	<class name="Department" table="department">
		<id name="id" type="integer" column="id">
			<generator class="native" />
		</id>
		<property name="name" />
		<!-- inverse屬性:預設為false,表示本方維護關聯關係;
		                                        如果設為true,表示本方不維護關聯關係 
		     只是影響是否能設定外來鍵列的值(設成有效值或是null值),對獲取資訊沒有影響        
		  cascade級聯屬性:
		  即刪掉一個Department,會同時刪掉department下的所有employees                          
		-->
		<set name="employees" inverse="false" cascade="save-update">
			<key column="departmentId"></key>
			<one-to-many class="Employee" />
		</set>
	</class>
</hibernate-mapping>
package test.hibernate.hbmOneToMany;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Department.class)// 新增Hibernate實體類(載入對應的對映檔案)
			.addClass(Employee.class)//
			.buildSessionFactory();

	@Test
	public void testSave() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 構建物件
		Department department = new Department();
		department.setName("開發部");

		Employee employee = new Employee();
		employee.setName("張三");

		Employee employee2 = new Employee();
		employee2.setName("李瑟");

		// 關聯起來
		employee.setDepartment(department);
		employee2.setDepartment(department);
		department.getEmployees().add(employee);
		department.getEmployees().add(employee2);

		// 儲存
//		session.save(department);
//		session.save(employee);
//		session.save(employee2);
		
		//級聯儲存,將cascade設為save-update
		session.save(department);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 獲取到部門關聯的員工
	@Test
	public void testGet() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();

		// 獲取資料
		Department department = (Department) session.get(Department.class, 1);
		System.out.println(department.getId());
		System.out.println(department.getName());
		System.out.println(department.getEmployees());

		session.getTransaction().commit();
		session.close();
	}

	// 解除關聯關係
	@Test
	public void testRemoveRelation() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------
		// 從員工解除與部門的關聯,也就是員工不再屬於任何部門
		// Employee employee=(Employee) session.get(Employee.class, 8);
		// employee.setDepartment(null);

		// 從部門解除員工關係
		Department department = (Department) session.get(Department.class, 1);
		// 要使這句有效,需將對映檔案裡的inverse設為false,即部門恢復維護關係
		department.getEmployees().clear();

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}

	// 刪除部門及對員工的影響
	@Test
	public void testDelete() throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		// --------------------------------------------

		// 刪除員工,對部門沒有影響
		// Employee employee=(Employee) session.get(Employee.class, 9);
		// session.delete(employee);

		/*
		 * 如果沒有關聯的員工,能刪除
		 * 如果有關聯的員工且inverse=true,由於不能維護關聯關係,會直接執行刪除且報異常
		 * 如果有關聯的員工且inverse=false,由於可以維護關聯關係,會將員工的外來鍵設為null,再刪除自己
		 */
		Department department = (Department) session.get(Department.class, 10);
		session.delete(department);

		// --------------------------------------------
		session.getTransaction().commit();
		session.close();
	}
}