hibernate 2 一对多、多对一 双向映射
多对一或一对多中,在多的一方维护关系效率高
一:java实体类
1、Classes.java
1 package cn.gs.ly.school.entity; 2 3 import java.util.Set; 4 5 public class Classes { 6 private int cid; 7 private String cname; 8 private String cdescription; 9 private Set<Student> students; 10 public int getCid() { 11 return cid; 12 } 13 public void setCid(int cid) { 14 this.cid = cid; 15 } 16 public String getCname() { 17 return cname; 18 } 19 public void setCname(String cname) { 20 this.cname = cname; 21 } 22 public String getCdescription() { 23 return cdescription; 24 } 25 public void setCdescription(String cdescription) { 26 this.cdescription = cdescription; 27 } 28 public Set<Student> getStudents() { 29 return students; 30 } 31 public void setStudents(Set<Student> students) { 32 this.students = students; 33 } 34 35 }
2、Student.java
1 package cn.gs.ly.school.entity; 2 3 public class Student { 4 private int sid; 5 private String sname; 6 private String sdescription; 7 private Classes classes; 8 9 public int getSid() { 10 return sid; 11 } 12 public void setSid(int sid) { 13 this.sid = sid; 14 } 15 public String getSname() { 16 return sname; 17 } 18 public void setSname(String sname) { 19 this.sname = sname; 20 } 21 public String getSdescription() { 22 return sdescription; 23 } 24 public void setSdescription(String sdescription) { 25 this.sdescription = sdescription; 26 } 27 public Classes getClasses() { 28 return classes; 29 } 30 public void setClasses(Classes classes) { 31 this.classes = classes; 32 } 33 34 }
二:配置映射信息,建立表与类之间关系
1、Classes.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 6 <!-- 配置表与实体对象的关系 --> 7 <hibernate-mapping> 8 <class name="cn.gs.ly.school.entity.Classes" > 9 <id name="cid" column="cid" type="java.lang.Integer"> 10 <generator class="assigned"></generator> 11 </id> 12 <property name="cname" column="cname" type="java.lang.String"></property> 13 <property name="cdescription" column="cdescription" type="java.lang.String"></property> 14 15 <!-- 16 cascade="save-update" 级联操作 17 当保存班级的时候对学生进行什么操作 18 inverse="false" 是否维护关系 19 true不维护关系、false维护关系 20 --> 21 <set name="students" cascade="save-update" inverse="false"> <!-- 级联 --> 22 <!-- 23 key 用来描述外键 24 set元素对用classes类中的set集合 25 通过key是 通过外键的形式将两张表建立联系 26 通过one-to-many让两个类建立关联 27 --> 28 <key> 29 <column name="cid"></column> 30 </key> 31 <one-to-many class="cn.gs.ly.school.entity.Student"/> 32 </set> 33 </class> 34 35 </hibernate-mapping>
2、Student.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 6 <!-- 配置表与实体对象的关系 --> 7 <hibernate-mapping> 8 <class name="cn.gs.ly.school.entity.Student" > 9 <id name="sid" column="sid" type="java.lang.Integer"> 10 <generator class="assigned"></generator> 11 </id> 12 <property name="sname" column="sname" type="java.lang.String"></property> 13 <property name="sdescription" column="sdescription" type="java.lang.String"></property> 14 <!-- 多对一column 描述外键 --> 15 <many-to-one name="classes" class="cn.gs.ly.school.entity.Classes" column="cid" cascade="save-update"></many-to-one> 16 </class> 17 18 </hibernate-mapping>
3、编写配置文件,连接数据库,引入映射信息文件
hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 6 <hibernate-configuration> 7 <!-- 一个session-factory只能链接一个数据库 --> 8 <session-factory> 9 <!-- 10 进行数据库连接 11 driver:驱动 12 url:地址 13 username:数据库连接用户名 14 password:数据库连接密码 15 数据库方言 16 不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成. 17 sql99标准: DDL 定义语言 库表的增删改查 18 DCL 控制语言 事务 权限 19 DML 操纵语言 增删改查 20 注意: MYSQL在选择方言时,请选择最短的方言. 21 --> 22 <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> 23 <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 24 <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property> 25 <property name="connection.username">liuyang</property> 26 <property name="connection.password">orcl</property> 27 <!-- 28 自动建表 29 auto schema export 自动导出表结构. 自动建表 30 hibernate.hbm2ddl.auto create 自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用) 31 hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用) 32 hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据). 33 hibernate.hbm2ddl.auto validate 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败. 34 --> 35 <!-- <property name="hbm2ddl.auto">update</property> --> 36 <property name="hbm2ddl.auto">update</property> 37 38 <!-- 将hibernate生成的sql语句打印到控制台 --> 39 <property name="show_sql">true</property> 40 <!-- 添加映射文件 --> 41 <mapping resource="cn/gs/ly/entity/Person.hbm.xml"></mapping> 42 <mapping resource="cn/gs/ly/school/entity/Student.hbm.xml"></mapping> 43 <mapping resource="cn/gs/ly/school/entity/Classes.hbm.xml"></mapping> 44 </session-factory> 45 </hibernate-configuration>
三:测试类
oneToManyTest.java
1 package cn.gs.ly.school.test; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.List; 6 import java.util.Set; 7 8 import org.hibernate.SessionFactory; 9 import org.hibernate.Transaction; 10 import org.hibernate.cfg.Configuration; 11 import org.hibernate.classic.Session; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 16 import cn.gs.ly.school.entity.Classes; 17 import cn.gs.ly.school.entity.Student; 18 import sun.util.calendar.CalendarSystem; 19 20 /** Hibernate执行流程: 21 * Configuration:读取并解析配置文件(hibernate.cfg.xml) 22 * 一个Configuration实例代表hibernate所有的java类到SQL数据库映射的集合 23 * SessionFactory:读取并解析映射信息(***.hbm.xml) 24 * 将Configuration对象中的所有配置信息拷贝到SessionFactory的缓存中 25 * 打开Session,让SessionFactory提供连接。 26 * SessionFactory factory = con.buildSessionFactory(); 27 * Transaction:开启事务。 28 * Transaction tr = se.beginTransaction(); 29 * 数据库操作(get,delete,update,save)完成:提交事务、关闭Session 30 * tr.commit(); 31 * se.close(); 32 * 33 * Hibernate对象三种状态 34 * save():将对象由瞬时态转变为持久态 35 * liad()/get():获得的对象的状态处于持久态 36 * find():获得的List集合中的对象的状态处于持久态 37 * upload()/saveOrUpload()/lock():可将托管状态对象转变为持久态 38 * close():调用后,Session的缓存会被清空,缓存中所有持久态对象状态都转变为托管态 39 * 处于托管状态的对象称为游离对象,当游离对象不再被引用时,将被JVM垃圾回收机制清除 40 * evict():可将Session缓存中一个指定的持久态对象删除,使其转变为托管态对象 41 * 当缓存中保存了大量持久态对象时,为了节省内存空间,可以调用此方法删除一些持久态对象 42 * 43 * */ 44 45 public class OneToManySingleTest { 46 SessionFactory factory =null; 47 Session se = null; 48 Transaction tr = null; 49 50 //@Before:读取并解析配置文件、映射信息、打开Session、开启事务 51 @Before 52 public void test1(){ 53 //读取配置文件 //1 创建,调用空参构造 54 Configuration con = new Configuration(); 55 //2 读取指定主配置文件 => 空参加载方法,加载src下的hibernate.cfg.xml文件 56 con.configure(); 57 //创建一个session工厂 //4 根据配置信息,创建 SessionFactory对象 58 factory = con.buildSessionFactory(); 59 //5 获得session 打开一个新的session对象 60 se = factory.openSession(); 61 //开启事务 //开启事务并获得操作事务的tr对象(建议使用) 62 tr = se.beginTransaction(); 63 } 64 //@After:提交事务、关闭Session 65 @After 66 public void afterClose(){ 67 //提交事务 68 tr.commit(); 69 //关闭session 70 se.close(); 71 } 72 73 //1.新建一个班级 74 @Test 75 public void testCreateClasses(){ 76 Classes classes = new Classes(); 77 classes.setCid(1); 78 classes.setCname("gs01"); 79 classes.setCdescription("一群大老爷们"); 80 se.save(classes); 81 } 82 83 //2.新建一个学生 84 @Test 85 public void testCreateStudent(){ 86 Student student = new Student(); 87 student.setSid(1); 88 student.setSname("张涛"); 89 student.setSdescription("诸城一爷们"); 90 se.save(student); 91 } 92 93 //3.新建一个班级的同时新建一个学生 94 @Test 95 public void testCreateStudentClasses(){ 96 Student student = new Student(); 97 student.setSid(2); 98 student.setSname("刘超"); 99 student.setSdescription("中华小题库"); 100 101 Classes classes = new Classes(); 102 classes.setCid(2); 103 classes.setCname("gs02"); 104 classes.setCdescription("一群学霸"); 105 106 Set<Student> stus = new HashSet<Student>(); 107 stus.add(student); 108 classes.setStudents(stus); 109 se.save(classes); 110 } 111 112 //4.已经存在一个班级,新建一个学生。建立联系:inverse(true不维护关系,false不维护关系) 113 @Test 114 public void testUpdateClass_Inverse_createStudent(){ 115 Classes classes = (Classes)se.get(Classes.class, 1); //id为1 的班级即gs01 116 117 Student student = new Student(); 118 student.setSid(3); 119 student.setSname("萌萌"); 120 student.setSdescription("一个光头的男人"); 121 122 classes.getStudents().add(student); 123 //se.update(classes); 124 } 125 126 //5.已经存在一个学生,新建一个班级 127 @Test 128 public void testCreateClassLinkStudent(){ 129 Classes classes = new Classes(); 130 classes.setCid(3); 131 classes.setCname("gs03"); 132 classes.setCdescription("一个新的班级"); 133 134 Student student = (Student)se.get(Student.class, 1); 135 136 Set<Student> stus = new HashSet<Student>(); 137 stus.add(student); 138 classes.setStudents(stus); 139 se.save(classes); 140 } 141 142 //6.把一个学生从一个班级转到另一个班级 143 @Test 144 public void testMoveStudent(){ 145 Student student = (Student)se.get(Student.class, 1); //获得要转班的学生 146 Classes classes = (Classes)se.get(Classes.class, 2); //获得要转到的那个班级 147 //Classes classes1 = (Classes)se.get(Classes.class, 3);//原来的班级 148 //classes1.getStudents().remove(student); //把这个学生从原来班级删除 149 classes.getStudents().add(student); //把这个学生添加到要转去的那个新班级 150 } 151 152 //7.解除一个班级和一个学生的关系 153 @Test 154 public void test7(){ 155 Student student = (Student)se.get(Student.class, 4); //获得要转班的那个学生 156 Classes classes = (Classes)se.get(Classes.class, 3); //获得这个学生原来所在的班级 157 classes.getStudents().remove(student); //把这个学生从原来班级删除 158 } 159 160 //8.解除一个班级和一些学生的关系 161 @Test 162 public void test8(){ 163 Classes classes = (Classes)se.get(Classes.class, 3); //解除关系的班级 164 Set<Student> students = classes.getStudents(); //此班级里所有学生,返回set集合 165 //set无下标,只查看集合不修改集合,所以用list集合进行修改 ,Set转List 166 List<Student> list = new ArrayList<Student>(students); 167 for (int i=0;i<list.size();i++) { 168 if(list.get(i).getSid()==4||list.get(i).getSid()==6){ //id为4和6的学生 169 list.remove(i);//移除后,集合大小动态改变,集合大小-1 170 i--; //集合变小,i也需要变化 171 } 172 } 173 //List转Set集合, 174 students = new HashSet<Student>(list); 175 classes.setStudents(students); 176 } 177 178 //9.解除一个班级和所有学生的关系 179 @Test 180 public void test9(){ 181 Classes classes = (Classes)se.get(Classes.class, 3); //获得一个班级 182 // Set<Student> students = classes.getStudents(); 183 // students.clear(); 184 classes.setStudents(null); 185 } 186 187 //10.已经存在了一个班级,也存在一个学生 建立班级与学生的关系 188 @Test 189 public void test10(){ 190 Classes classes = (Classes)se.get(Classes.class, 2); // id 为1 的班级即gs01 191 Student student = (Student)se.get(Student.class, 7); 192 classes.getStudents().add(student); 193 } 194 195 @Test //11.已经存在了一个班级,也存在许多学生 建立班级与学生的关系 196 public void test11(){ //未完成 ===================== 197 // Classes classes = (Classes)se.get(Classes.class, 3); 198 // Set<Student> students = classes.getStudents(); 199 // //set无下标,只查看集合不修改集合,所以用list集合 ,set转list 200 // List<Student> list = new ArrayList<Student>(students); 201 // for (int i=0;i<list.size();i++) { 202 // if(list.get(i).getSid()==4||list.get(i).getSid()==5||list.get(i).getSid()==6){ 203 // 204 // }else{ 205 // list.remove(i); 206 // } 207 // } 208 // //list转set集合 209 // students = new HashSet<Student>(list); 210 // classes.setStudents(students); 211 } 212 213 //12.删除学生 214 @Test 215 public void test12(){ 216 Student student = (Student)se.get(Student.class, 2); 217 se.delete(student); 218 } 219 220 // 13.删除班级(需先解除关系) 221 // 1.在删除班级前,解除班级与学生之间的关系: inverse="false" 维护关系 删除班级解除关系 222 // 2.在删除班级的时候同时删除学生: 级联操作 cascade="all" 或 cascade="delete" 223 @Test 224 public void test13(){ 225 Classes classes = (Classes)se.get(Classes.class, 3); 226 //classes.setStudents(null); //解除关系 inverse="true"时需此操作来解除关系 227 se.delete(classes); 228 } 229 230 }
ManyToOneTest.java
1 package cn.gs.ly.school.test; 2 3 import java.util.ArrayList; 4 import java.util.HashSet; 5 import java.util.List; 6 import java.util.Set; 7 8 import org.hibernate.SessionFactory; 9 import org.hibernate.Transaction; 10 import org.hibernate.cfg.Configuration; 11 import org.hibernate.classic.Session; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 16 import cn.gs.ly.school.entity.Classes; 17 import cn.gs.ly.school.entity.Student; 18 import sun.util.calendar.CalendarSystem; 19 20 public class ManyToOneSingleTest2 { 21 22 SessionFactory factory =null; 23 Session se = null; 24 Transaction tr = null; 25 @Before 26 public void test1(){ 27 //读取配置文件 //1 创建,调用空参构造 28 Configuration con = new Configuration(); 29 //2 读取指定主配置文件 => 空参加载方法,加载src下的hibernate.cfg.xml文件 30 con.configure(); 31 //创建一个session工厂 //4 根据配置信息,创建 SessionFactory对象 32 factory = con.buildSessionFactory(); 33 //5 获得session 打开一个新的session对象 34 se = factory.openSession(); 35 //开启事务 //开启事务并获得操作事务的tr对象(建议使用) 36 tr = se.beginTransaction(); 37 } 38 @After 39 public void afterClose(){ 40 //提交事务 41 tr.commit(); 42 //关闭session 43 se.close(); 44 } 45 46 // 一对多双向 47 /** 48 * 多对一或一对多中,在多的一方维护关系效率高 student角度 49 * 50 * */ 51 52 @Test //1.新建一个班级 53 public void testCreateClasses(){ 54 Classes classes = new Classes(); 55 classes.setCid(10); 56 classes.setCname("gs010"); 57 classes.setCdescription("一群大老爷们"); 58 se.save(classes); 59 } 60 61 @Test //2.新建一个学生 62 public void testCreateStudent(){ 63 Student student = new Student(); 64 student.setSid(10); 65 student.setSname("张涛"); 66 student.setSdescription("诸城一爷们"); 67 se.save(student); 68 } 69 70 @Test //3.新建一个班级的同时新建一个学生 71 public void testCreateStudentClasses(){ 72 Student student = new Student(); 73 student.setSid(11); 74 student.setSname("刘杨"); 75 student.setSdescription("学霸"); 76 77 Classes classes = new Classes(); 78 classes.setCid(21); 79 classes.setCname("gs021"); 80 classes.setCdescription("一群学霸"); 81 82 student.setClasses(classes); 83 se.save(student); 84 85 } 86 87 @Test //4.已经存在一个班级,新建一个学生 建立联系 inverse(true不维护false维护) 88 public void testUpdateClass_Inverse_createStudent(){ 89 Classes classes = (Classes)se.get(Classes.class, 21); // id 为1 的班级即gs01 90 Student student = new Student(); 91 student.setSid(12); 92 student.setSname("萌萌"); 93 student.setSdescription("一个光头的男人"); 94 95 student.setClasses(classes); 96 se.save(student); 97 } 98 99 // @Test //5.已经存在一个学生,新建一个班级 100 // public void testCreateClassLinkStudent(){ 101 // Classes classes = new Classes(); 102 // classes.setCid(3); 103 // classes.setCname("gs03"); 104 // classes.setCdescription("一个新的班级"); 105 // 106 // Student student = (Student)se.get(Student.class, 1); 107 // 108 // Set<Student> stus = new HashSet<Student>(); 109 // stus.add(student); 110 // classes.setStudents(stus); 111 // se.save(classes); 112 // } 113 // 114 // @Test //6.把一个学生从一个班级转到另一个班级 115 // public void testMoveStudent(){ 116 // Student student = (Student)se.get(Student.class, 1); //获得要转班的那个学生 117 // Classes classes = (Classes)se.get(Classes.class, 2); //获得要转到的那个班级 118 // //Classes classes1 = (Classes)se.get(Classes.class, 3);//原来的班级 119 // //classes1.getStudents().remove(student); //把这个学生从原来班级删除 120 // classes.getStudents().add(student); //把这个学生添加到要转去的那个新班级 121 // } 122 // 123 // @Test //7.解除一个班级和一个学生的关系 124 // public void test7(){ 125 // Student student = (Student)se.get(Student.class, 4); //获得要转班的那个学生 126 // Classes classes = (Classes)se.get(Classes.class, 3); //获得这个学生原来所在的班级 127 // classes.getStudents().remove(student); //把这个学生从原来班级删除 128 // } 129 130 @Test //8.解除一个班级和一些学生的关系 131 public void test8(){ 132 //Classes classes = (Classes)se.get(Classes.class, 21); 133 Student s1 = (Student)se.get(Student.class, 4); 134 Student s2 = (Student)se.get(Student.class, 5); 135 s1.setClasses(null); 136 s2.setClasses(null); 137 } 138 139 @Test //9.解除一个班级和所有学生的关系 140 public void test9(){ 141 Classes classes = (Classes)se.get(Classes.class, 3); 142 // Set<Student> students = classes.getStudents(); 143 // students.clear(); 144 classes.setStudents(null); 145 } 146 147 @Test //10.已经存在了一个班级,也存在一个学生 建立班级与学生的关系 148 public void test10(){ 149 Classes classes = (Classes)se.get(Classes.class, 2); // id 为1 的班级即gs01 150 Student student = (Student)se.get(Student.class, 7); 151 classes.getStudents().add(student); 152 } 153 154 @Test //11.已经存在了一个班级,也存在许多学生 建立班级与学生的关系 155 public void test11(){ 156 Classes classes = (Classes)se.get(Classes.class, 3); 157 Set<Student> students = classes.getStudents(); 158 //set无下标,只查看集合不修改集合,所以用list集合 ,set转list 159 List<Student> list = new ArrayList<Student>(students); 160 for (int i=0;i<list.size();i++) { 161 if(list.get(i).getSid()==4||list.get(i).getSid()==5||list.get(i).getSid()==6){ 162 163 }else{ 164 list.remove(i); 165 } 166 } 167 //list转set集合 168 students = new HashSet<Student>(list); 169 classes.setStudents(students); 170 } 171 172 @Test //12.删除学生 173 public void test12(){ 174 Student student = (Student)se.get(Student.class, 2); 175 se.delete(student); 176 } 177 178 @Test // 13.删除班级 (解除关系) 179 // 1.在删除班级前,解除班级与学生之间的关系: inverse="false" 维护关系 删除班级解除关系 180 // 2.在删除班级的时候同时删除学生: cascade="all" 或 cascade="delete" 181 public void test13(){ 182 Classes classes = (Classes)se.get(Classes.class, 3); 183 //classes.setStudents(null); //解除关系 inverse="true"时需此操作 184 se.delete(classes); 185 } 186 187 }