接上篇
为了实现 从 student 端操作增加了字段 classes
package cn.itcast.hiberate.sh.domain; import java.io.Serializable; public class Student implements Serializable{ private Long sid; private String sname; private String description; private Classes classes; public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } public Long getSid() { return sid; } public void setSid(Long sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", description=" + description + "]"; } }
Student 的映射文件 作相应修改
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- name的值代表的是一个实体 --> <class name="cn.itcast.hiberate.sh.domain.Student"> <!-- id用于指定主键 column,主键在数据库表列 , increment,主键自增 --> <!-- length,指定长度 type,类型,也可以不写 --> <id name="sid" length="5" type="java.lang.Long"> <generator class="increment"></generator> </id> <!-- 表示表中普通的属性 --> <property name="sname" length="20" type="java.lang.String"></property> <property name="description" length="100" type="java.lang.String"></property> <!-- column 是指的外键 --> <many-to-one name="classes" class="cn.itcast.hiberate.sh.domain.Classes" column="cid" cascade="save-update"></many-to-one> </class> </hibernate-mapping>
测试类
package cn.itcast.hibernate.sh.test; import java.util.HashSet; import java.util.Set; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import cn.itcast.hiberate.sh.domain.Classes; import cn.itcast.hiberate.sh.domain.Student; import cn.itcast.hibernate.sh.utils.HibernateUtils; public class TestManyToOne extends HibernateUtils{ static{ url="/hibernate.cfg.xml"; } // 新建班级的时候同时新建学生 /** * Hibernate: select max(sid) from Student Hibernate: select max(cid) from Classes Hibernate: insert into Classes (cname, description, cid) values (?, ?, ?) Hibernate: insert into Student (sname, description, cid, sid) values (?, ?, ?, ?) */ // 注意 : 相比于 一对多 ,此时多对一的操作并没有发出 update 语句 // 当一对多 时操作的是classes hibernate 会查看两个表,这是外键是在student表中, //会通过外键 cid 自动的维护两个表之间的关系,发出 update 语句 // 当多对一时 外键本身就在 student 表中 ,操作的是 student,会直接维护相应的关系 // 所以通过 操作多的一方能达到一定的优化效果 @Test public void test_saveStudent_cascade_saveClasses(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Classes classes = new Classes(); classes.setCname("峡谷3"); classes.setDescription("召唤师峡谷3"); Student student = new Student(); student.setSname("黄金"); student.setDescription("不错了"); student.setClasses(classes); // 多对一的时候这样操作了 session.save(student); transaction.commit(); session.close(); } // 已经存在一个学生,新建一个班级 /** * Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, * student0_.description as descript3_1_0_, student0_.cid as cid1_0_ from Student student0_ where student0_.sid=? Hibernate: select max(cid) from Classes Hibernate: insert into Classes (cname, description, cid) values (?, ?, ?) Hibernate: update Student set sname=?, description=?, cid=? where sid=? */ @Test public void test_existStudent_saveClasses(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Student student = (Student) session.get(Student.class, 5L); Classes classes = new Classes(); classes.setCname("峡谷4"); classes.setDescription("召唤师峡谷4"); // 建立两个表的关系 student.setClasses(classes); transaction.commit(); session.close(); } //已经存在一个班级,新建一个学生,建立学生与班级之间的关系 /** * Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=? Hibernate: select max(sid) from Student Hibernate: insert into Student (sname, description, cid, sid) values (?, ?, ?, ?) */ /** * Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, * classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=? Hibernate: select students0_.cid as cid0_1_, students0_.sid as sid1_, students0_.sid as sid1_0_, students0_.sname as sname1_0_, students0_.description as descript3_1_0_, students0_.cid as cid1_0_ from Student students0_ where students0_.cid=? Hibernate: select max(sid) from Student Hibernate: insert into Student (sname, description, cid, sid) values (?, ?, ?, ?) Hibernate: update Student set cid=? where sid=? */ /** * 操作 classes 来建立两个表的关系,但是保存的是student 这时也能完成目标,不过会发出update 语句 * 这时可以看出 classes.getStudents().addAll(students);//在hibernate内部查看的是classes.hbm.xml session.save(student);//在hibernate内部查看的是Student.hbm.xml */ @Test public void test_existClasses_saveStudent(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Classes classes = (Classes) session.get(Classes.class, 6L); Student student = new Student(); student.setSname("黄金1"); student.setDescription("挺好的"); // 建立两个表的关系 //student.setClasses(classes); // 将其注释另外测试,通过classes建立联系,保存的还是 student Set<Student> students = new HashSet<Student>(); students.add(student); classes.getStudents().addAll(students); session.save(student); transaction.commit(); session.close(); } //把一个学生从一个班级转移到另一个班级 /** * Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, * student0_.description as descript3_1_0_, student0_.cid as cid1_0_ from Student student0_ where student0_.sid=? Hibernate: select classes0_.cid as cid0_0_, classes0_.cname as cname0_0_, classes0_.description as descript3_0_0_ from Classes classes0_ where classes0_.cid=? Hibernate: update Student set sname=?, description=?, cid=? where sid=? */ @Test public void testTransform(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Student student = (Student) session.get(Student.class, 6L); Classes classes = (Classes) session.get(Classes.class, 5L); student.setClasses(classes); transaction.commit(); session.close(); } // 解除某个学生与班级的关系 /** * Hibernate: select student0_.sid as sid1_0_, student0_.sname as sname1_0_, * student0_.description as descript3_1_0_, student0_.cid as cid1_0_ from Student student0_ where student0_.sid=? Hibernate: update Student set sname=?, description=?, cid=? where sid=? */ @Test public void testRelease(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Student student = (Student) session.get(Student.class, 6L); student.setClasses(null); transaction.commit(); session.close(); } }
多对一,其实相当于是另一个方向的一对多
而一对多,从多的一端维护关系效率比较高