我们大家都知道,在域模型(实体域)中,关联关系是类与类之间最普遍的关系,他是指通过一个对象持有另一个对象的实例根据UML语言,关系是有方向的。实质上关联映射的本质:将关联关系映射到数据库,所谓的关联关系是对象模型在内存中的一个或多个引用。搞清关联映射的的关键就在于搞清实体之间的关系。
单向一对多:
所谓单向一对多,就是实体之间的关系由“一” 的一端加载“多” 的一端,关系由“一”的一端来维护,在JavaBean中是在“一”的一端中持有“多”的一端的集合,Hibernate把这种关系反映到数据库的策略是在“多”的一端的表上加一个外键指向“一” 的一端的表的主键。比如Class(班级)和Student(学生)之间是一对多的关系。一个班级里面有很多的学生,站在班级的角度上来看就是一个班级对应多个学生。在一的一端含有一个多的引用的集合,我们可以根据班级找到它有哪些学生,而不能根据学生找到他对应的班级。
package com.usc.bean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Class implements Serializable { private int id; private String cname; private String cdes; private Set<Student> students = new HashSet<>(); public Class() { } public Class(String cname, String cdes) { super(); this.cname = cname; this.cdes = cdes; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> syudents) { this.students = syudents; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public String getCdes() { return cdes; } public void setCdes(String cdes) { this.cdes = cdes; } @Override public String toString() { return "Class [id=" + id + ", cname=" + cname + ", cdes=" + cdes + ", students=" + students + "]"; } }
package com.usc.bean; import java.io.Serializable; public class Student implements Serializable{ private int sid; private String sname; private int sage; public Student() { } public Student(String sname, int sage) { this.sname = sname; this.sage = sage; } 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 int getSage() { return sage; } public void setSage(int sage) { this.sage = sage; } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", sage=" + sage + "]"; } }
实体类配置文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.usc.bean.Class" table="class" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <property name="cname" type="java.lang.String"> <column name="cname" /> </property> <property name="cdes" type="string"> <column name="cdes" /> </property> <set name="students"> <key column="s_gid"></key> <one-to-many class="com.usc.bean.Student"/> </set> </class> </hibernate-mapping>
在一对多中,在一方实体类中创建多方的集合,并在配置文件中用set集合在配置one-to-many。而在多方不需要作额外配置
name为--持久化对象的集合的属性名称
<key column="s_gid" ></key>外键的名称
<one-to-many class=“cn.edu.bzu.hibernate.Student" />持久化类
<set>元素的inverse属性:在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据.
sql建表语句
create table student ( sid int(10) not null auto_increment primary key, sname varchar(15) , sage int(10), s_gid int(15) not null, foreign key (s_gid) references class(id) ); create table class( id int(10) not null auto_increment primary key, cname varchar(15), cdes varchar(15) );
单向多对一:
单向多对一关联是最常见的单向关联关系,如:多个用户属于同一个组,多个学生处于同一个班级。之所以叫他多对一而不是一对多,是因为他们之间的关系是多的一方来维护的。多对一用的更多
多个用户属于一个组,我们用多的一方来维护,所以我们可以根据用户可以知道他在哪个组,而不需要知道一个组里有哪些学生,这就是所谓的单向的。多对一映射原理:在多的一端加入一个外键指向一的一端,它维护的关系多指向一,一对多映射原理,在多的一端加入一个外键指向一的一端,她维护的关系是一指向多,也就是说一对多与多对一的映射原理是一样的,只是站的角度不一样。
实体类
package com.usc.bean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; public class Class implements Serializable { private int id; private String cname; private String cdes; public Class() { } public Class(String cname, String cdes) { super(); this.cname = cname; this.cdes = cdes; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public String getCdes() { return cdes; } public void setCdes(String cdes) { this.cdes = cdes; } @Override public String toString() { return "Class [id=" + id + ", cname=" + cname + ", cdes=" + cdes + ", students=" + "]"; } }
实体类的配置文件
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.usc.bean.Class" table="class" catalog="test"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <property name="cname" type="java.lang.String"> <column name="cname" /> </property> <property name="cdes" type="string"> <column name="cdes" /> </property> </class> </hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.usc.bean.Student" table="student" catalog="test"> <id name="sid" type="java.lang.Integer"> <column name="sid" /> <generator class="native" /> </id> <property name="sname" type="java.lang.String"> <column name="sname" /> </property> <property name="sage" type="int"> <column name="sage" /> </property> <many-to-one name="mClass" class="com.usc.bean.Class" column="s_gid"></many-to-one> </class> </hibernate-mapping>
在多对一的关系中,在一方不需要作额外配置,而在多方需要在实体类中添加一方对象,并且在多方配置mangy-to-one
<many-to-one name="mClass" class="com.usc.bean.Class" column="s_gid"></many-to-one>
name:一方的对象
class:一方的实体类
column:一方在多方的外键列
双向的一对多
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>(); //在此同样省略相应的方法 }
<?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(); } } }
参考自:http://blog.csdn.net/csh624366188/article/details/7585129