Hibernate關聯映射之一對多,多對一以及雙向一對多

在上篇博客我們講了hibernate對單表的操作,本篇博客就來講講對多表的關聯映射操作。首先我們拿來做例子的表爲班級表1---n學生表,在這次的測試主鍵我用的是序列,創建代碼如下:

--班級表
drop table classes;
create table classes(
       cid int primary key,
       cname varchar2(50)
);

drop sequence seq_classes_cid;
create sequence seq_classes_cid
       START WITH 1000    -- 從1000開始計數 
       INCREMENT BY 1     -- 每次加1個

--學生表
drop table student;
create table student(
       sid int primary key,
       sname varchar2(50),
       cid int constraint FK_student_cid references classes(cid)
);

drop sequence seq_student_sId;
create sequence seq_student_sId
       START WITH 1000    -- 從1000開始計數 
       INCREMENT BY 1     -- 每次加1個


對於使用hibernate我們都需要配置cfg文件,所以在此貼出我的cfg文件
<?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">hibernate</property>
		<property name="connection.password">a</property>
		<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
		<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
		<!-- 方言 -->
		<property name="dialect">org.hibernate.dialect.OracleDialect</property>

		<!-- 是否在運行的時候顯示sql語句 -->
		<property name="show_sql">true</property>
		<!-- 顯示的sql語句是否進行排版 -->
		<property name="format_sql">true</property>
		<!-- 表結構生成策略 -->
		<property name="hbm2ddl.auto">update</property>
		<!-- getCurrentSession所需的參數(本地事務) -->
		<property name="hibernate.current_session_context_class">thread</property>

	</session-factory>
</hibernate-configuration>

一對多的關聯關係

1.首先我們需要編寫學生和班級的實體類
package com.yc.entity;

import java.io.Serializable;

public class Student implements Serializable{
	private static final long serialVersionUID = 3914237588346266940L;

	private int sid;
	private String sname;

	public Student() {
	}
	public Student(String sname) {
		this.sname = sname;
	}
	public Student(int sid, String sname) {
		this.sid = sid;
		this.sname = sname;
	}

	public int getSid() {
		return sid;
	}
	public void setSid(int sid) {
		this.sid = sid;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}

	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + "]";
	}
}
package com.yc.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Classes implements Serializable {
	private static final long serialVersionUID = 948637569053708320L;

	private int cid;
	private String cname;
	//在一方定義一個多方的集合 一對多
	private Set<Student> students=new HashSet<Student>();

	public Classes() {

	}
	public Classes(String cname) {
		this.cname = cname;
	}
	public Classes(int cid, String cname, Set<Student> students) {
		this.cid = cid;
		this.cname = cname;
		this.students = students;
	}

	public int getCid() {
		return cid;
	}
	public void setCid(int cid) {
		this.cid = cid;
	}
	public String getCname() {
		return cname;
	}
	public void setCname(String cname) {
		this.cname = cname;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}

	public String toString() {
		return "Classes [cid=" + cid + ", cname=" + cname + ", students="
				+ students + "]";
	}
}

2.根據實體類創建對應的hbm文件
Student.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">
<!-- Generated 2016-8-12 19:33:30 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Student" table="STUDENT">
        <id name="sid" type="int">
            <column name="SID" />
            <generator class="sequence" >
            	<param name="sequence">seq_student_sId</param>
            </generator>
        </id>
        <property name="sname" type="java.lang.String">
            <column name="SNAME" />
        </property>
    </class>
</hibernate-mapping>
Classes.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">
<!-- Generated 2016-8-12 19:33:30 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Classes" table="CLASSES">
        <id name="cid" type="int">
            <column name="CID" />
            <generator class="sequence" >
            	<param name="sequence">seq_classes_cid</param>
            </generator>
        </id>
        <property name="cname" type="java.lang.String">
            <column name="CNAME" />
        </property>
        <!-- 配置單向的一對多關聯關係 -->
        <set name="students" table="STUDENT" inverse="false" lazy="true">
        	<!-- 指定關聯的外鍵列 -->
            <key>
                <column name="CID" />
            </key>
            <one-to-many class="com.yc.entity.Student" />
        </set>
    </class>
</hibernate-mapping>

3.在cfg文件中加入映射路徑
<!-- 測試一對多 -->
<mapping resource="Classes.hbm.xml" />
<mapping resource="Student.hbm.xml" />

4.編寫測試類測試
package com.yc.test;

import java.util.Collections;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.yc.entity.Classes;
import com.yc.entity.Student;
import com.yc.utils.HibernateUtil;

public class MyTest {

	@Test
	//插入數據的測試
	public void testAdd() {
		Classes c=new Classes("龍宮");

		Student s1=new Student("龍太子");
		Student s2=new Student("玄彩娥");

		//如果希望在學生表中添加對應的班級編號,需要在班級中添加學生,建立關聯關係
		Collections.addAll(c.getStudents(), s1,s2);

		Session session=HibernateUtil.getSession();
		Transaction transaction=session.beginTransaction();

		session.save(c);
		session.save(s1);
		session.save(s2);

		transaction.commit();
		HibernateUtil.closeSession(session);
	}

	@Test
	//查詢班級中包含的學生
	public void testFind() {
		Session session=HibernateUtil.getSession();
		Classes c=(Classes) session.get(Classes.class, 1000);
		//建立關聯關係後,可以方便的從一個對象導航到另一個對象
		System.out.println(c);
	}

	@Test
	//修改學生信息
	public void testUpdate() {
		Classes c=new Classes("普陀山");

		Session session=HibernateUtil.getSession();
		Transaction transaction=session.beginTransaction();

		Student s=(Student) session.get(Student.class, 1001);
		c.getStudents().add(s);

		session.save(c);

		transaction.commit();
		HibernateUtil.closeSession(session);
	}

	@Test
	//刪除
	public void testDelete() {
		Session session=HibernateUtil.getSession();
		Transaction transaction=session.beginTransaction();

		Student s=(Student) session.get(Student.class, 1000);
		session.delete(s);

		transaction.commit();
		HibernateUtil.closeSession(session);
	}
}

5.測試結果,在這裏我只貼出testAdd方法的測試結果,其餘方法小夥伴門可以自己嘗試


多對一的關聯關係

在這裏其實我們只需改變實體類中的屬性以及對應的hbm文件即可,其實多對一更加符合我們的數據庫表的設計
1.實體類
package com.yc.entity;

public class Student {
	private int sid;
	private String sname;
	private Classes cid; //多對一
	//在此就不貼出對應的set,get方法以及構造函數,toString方法
}
package com.yc.entity;

public class Classes {
	private int cid;
	private String cname;
	//在此就不貼出對應的set,get方法以及構造函數,toString方法
}

2.hbm文件
Student.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">
<!-- Generated 2016-8-12 20:59:00 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Student" table="STUDENT">
        <id name="sid" type="int">
            <column name="SID" />
            <generator class="sequence" >
            	<param name="sequence">seq_student_sId</param>
            </generator>
        </id>
        <property name="sname" type="java.lang.String">
            <column name="SNAME" />
        </property>
        <many-to-one name="cid" class="com.yc.entity.Classes" fetch="join">
            <column name="CID" />
        </many-to-one>
    </class>
</hibernate-mapping>
Classes.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">
<!-- Generated 2016-8-12 20:59:00 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Classes" table="CLASSES">
        <id name="cid" type="int">
            <column name="CID" />
            <generator class="sequence" >
            	<param name="sequence">seq_classes_cid</param>
            </generator>
        </id>
        <property name="cname" type="java.lang.String">
            <column name="CNAME" />
        </property>
    </class>
</hibernate-mapping>

3.編寫測試類運行
package com.yc.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.yc.entity.Classes;
import com.yc.entity.Student;
import com.yc.utils.HibernateUtil;

//測試多對一
public class MyTest2 {

	@Test
	//測試多對一
	public void testSave(){
		Classes ct=new Classes();
		ct.setCname("陰曹地府");

		Student st1=new Student();
		st1.setSname("殺破狼");

		Student st2=new Student();
		st2.setSname("骨精靈");

		//設置關聯關係
		st1.setCid(ct);
		st2.setCid(ct);

		Session session=HibernateUtil.getSession();
		Transaction tx=session.beginTransaction();

		session.save(ct);
		session.save(st1);
		session.save(st2);

		tx.commit();
		HibernateUtil.closeSession(session);
	}

	@Test
	//測試多對一
	public void testFind(){
		Session session=HibernateUtil.getSession();

		Student s=(Student) session.get(Student.class,1002);
		System.out.println(s);

		HibernateUtil.closeSession(session);
	}
}

4.測試運行,同樣在這裏我只測試testSave方法

          

雙向的一對多

其實雙向的一對多就是將上述兩種方法結合,以便於之後的操作
1.實體類
package com.yc.test3;

import java.io.Serializable;

public class Student3 implements Serializable{
	private static final long serialVersionUID = 4829740592306007293L;

	private int sid;
	private String sname;
	private Classes3 cid;
	//在此同樣省略相應的方法
}


package com.yc.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Classes implements Serializable {
	private static final long serialVersionUID = 948637569053708320L;

	private int cid;
	private String cname;
	//在一方定義一個多方的集合
	private Set<Student> students=new HashSet<Student>();

	//在此同樣省略相應的方法
}

2.hbm文件
Student.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">
<!-- Generated 2016-8-13 10:41:54 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Student" table="STUDENT">
        <id name="sid" type="int">
            <column name="SID" />
            <generator class="sequence" >
            	<param name="sequence">seq_student_sId</param>
            </generator>
        </id>
        <property name="sname" type="java.lang.String">
            <column name="SNAME" />
        </property>
        <many-to-one name="cid" class="com.yc.entity.Classes" fetch="join">
            <column name="CID" />
        </many-to-one>
    </class>
</hibernate-mapping>
Classes.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">
<!-- Generated 2016-8-13 10:41:54 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.yc.entity.Classes" table="CLASSES">
        <id name="cid" type="int">
            <column name="CID" />
            <generator class="sequence" >
            	<param name="sequence">seq_classes_cid</param>
            </generator>
        </id>
        <property name="cname" type="java.lang.String">
            <column name="CNAME" />
        </property>
        <set name="students" table="STUDENT" inverse="false" lazy="true" >
        	<!-- 指定關聯的外鍵列 -->
            <key>
                <column name="CID" />
            </key>
            <one-to-many class="com.yc.entity.Student" />
        </set>
    </class>
</hibernate-mapping>

3.測試類
package com.yc.test;

import java.util.Collections;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.yc.entity.Classes;
import com.yc.entity.Student;
import com.yc.utils.HibernateUtil;

//測試雙向一對多
public class MyTest3 {
	@Test
	//測試多對一
	public void testSave(){
		Classes c=new Classes("大唐官府");

		Student s1=new Student("劍俠客");
		Student s2=new Student("飛燕女");

		//設置關聯關係
		Collections.addAll(c.getStudents(), s1,s2);
		s1.setCid(c);
		s2.setCid(c);

		Session session=HibernateUtil.getSession();
		Transaction tx=session.beginTransaction();

		session.save(c);
		session.save(s1);
		session.save(s2);

		tx.commit();

		HibernateUtil.closeSession(session);
	}

	@Test
	public void testFind(){
		Session session=HibernateUtil.getSession();

		Classes c=(Classes) session.get(Classes.class, 1002);
		Student s=(Student) session.get(Student.class, 1003);

		System.out.println(c);
		System.out.println(s);

		HibernateUtil.closeSession(session);
	}

	@Test
	//查詢學生所在的班級的信息
	public void testFingStudentClass(){
		Session session=HibernateUtil.getSession();

		Student s=(Student) session.get(Student.class, 1003);

		System.out.println(s.getCid());

		HibernateUtil.closeSession(session);
	}
}

4.測試運行,一樣這裏只測試testSave方法

寫到這裏我突然想起一件事情,HibernateUtil的代碼忘記貼了,下面是我的代碼
package com.yc.utils;

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

public class HibernateUtil {
	private static SessionFactory sessionFactory;
	private static Session session;

	static{
		// 創建配置對象
		Configuration config = new Configuration().configure();
		// 創建服務註冊對象
		ServiceRegistry serviceRegistry=new 
				ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
		// 創建會話工廠對象
		sessionFactory = config.buildSessionFactory(serviceRegistry);
	}

	public static Session getSession(){
		//創建會話對象
		session = sessionFactory.openSession();

		return session;
	}

	public static void closeSession(Session session){
		if(session!=null){
			//關閉會話
			session.close();
		}
	}
}



發佈了36 篇原創文章 · 獲贊 4 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章