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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章