在上篇博客我们讲了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);
}
}
多对一的关联关系
在这里其实我们只需改变实体类中的属性以及对应的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方法
}
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();
}
}
}