<!-- Hibernate chapter2 各表连接查询配置 Goal:达到各种表之间的连接查询,也就是其中的关系的连接:多对单,单对单,单对多! --> 简单说明: 单对多/多对单:通俗点说就是多个对象与一个对象想对应,就拿学生表和班级表来说吧, 一个班下面有很多学生,也就是说很多学生对应一个班级,这就是单对多/多对单的关系! 单对单:也就是说一个对象只能对应一个对象!也就是说,比如现在多了一个表,这个表是 记录有关班级的属性的,也就是数这个表中的一条(有且只有一条)数据只对应了一个班级! 一个班级也只对应了那有且只有一条的数据的关系就叫单对单! 一,操作: a)数据库表格的建立: <!-- 假设数据库中有这几张表: //班级表 table ClassInfo( cid int primary key identity, cname varchar(20) not null, remark varchar(50) not null ) //学生表 table StuInfo( sid int primary key identity, sname varchar(20) not null, cid int foreign key (cid) references ClassInfo(cid), remark varchar(50) ) //班级详情表(就是那个有且只有一条数据与班级表的单条数据相对应) table ClassDetail( cid int primary key,/*注意这里没有必要设置外键约束*/ detail varchar(200), remark varchar(50) ) --> b)实体的建立: //班级实体 public class ClassInfo{ private int cid; private String cname; private String remark; //注意这里了:为了能够查询到该班级下的所有学生,所以我们要设置一个学生的集合Set<StuInfo> //为什么是Set而不是List:List可以元素重复,Set不能有重复元素! private Set<StuInfo> stu_set; //省略了getter&setter } //学生实体 public class StuInfo{ private int sid; private String sname; private String remark; //为了能够查询到该学生所在的班级信息,所以这里不能建立外键,而是需要一个实体 private ClassInfo classInfo; //省略了getter&setter } //班级详细信息实体 public class ClassDetail{ //为了能够达到单对单的关系,所以这个Id外键列需要写出来 private int cid; private String detail; private String remark; //同理,也需要把班级实体引用过来! private ClassInfo classInfo; //省略getter&setter } c)关键的来了~配置xml文件! <!--记住加上这句来控制编码! <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> --> 1)班级->学生(单对多关系) //注:文件名:ClassInfo.hbm.xml <hibernate-mapping> <class name="com.shu.model.ClassInfo(类名)" table="ClassInfo(表名)"> <id name="cid(字段ID列)" column="cid(表格ID列)"> <generator class="native"/> </id> <property name="cname" column="cname"/> <property name="remark" column="remark"/> <!--开始配置一对多的关系--> <set name="stu_set(实体中的set名)"> <key name="cid(依据那个列来进行的)"/> <one-to-many class="com.shu.model.StuInfo(many对象所在类)"> </set> </class> </hibernate-mapping> <!--在java中进行查询,并且输入该班级的人数以及各个同学的信息 //省略N创建各种对象的步骤 ClassInfo ci=(ClassInfo)session.get(ClassInfo.class,班级ID); //得到属于该班级的人数: ci.getStu_set().size(); //迭代输出信息 Iterator<StuInfo> it=ci.getStu_set().iterator(); while(it.hasNext()){ StuInfo si=it.next(); //do whatever you want! } --> 2)学生->班级(多对单关系) //注:文件名:StuInfo.hbm.xml <hibernate-mapping> <class name="com.shu.model.StuInfo" table="StuInfo"> <id name="sid" column="sid"> <generator class="native"> </id> <property name="sname" column="sname"/> <property name="remark" column="remark"/> <!--开始配置多对单关系--> <many-to-one class="com.shu.model.ClassInfo" name="classInfo(实体中的那个classInfo)" column="cid"/> </class> </hibernate-mapping> <!--在java中进行学员班级的连接查询 //省略N创建各种对象的步骤 StuInfo si=(StuInfo)session.get(StuInfo.class,学员id); ClassInfo ci=si.getClassInfo(); //then do whatever you want! --> 3)班级->班级详细信息(单对单关系) //注:文件名:ClassDetail.hbm.xml <hibernate-mapping> <class name="com.shu.model.ClassDetail" table="ClassTable"> <id name="cid" column="cid"> /*注意这里不一样了哦:用的是foreign,不是native了*/ <generator class="foreign"> /*还要记住配置里面的信息,中间的值就是在类中定义的那个引用类型的属性!*/ <param name="property">classInfo</param> </generator> </id> <property name="detail" column="detail"/> <property name="remark" column="remark"/> <!--开始配置单对单关系--> <one-to-one name="classInfo" class="com.shu.model.ClassInfo"/> </class> </hibernate-mapping> <!--在java中的运用! //首先要了解单对单的作用:也就是我向ClassInfo插入数据时会自动想ClassDetail中插入数据 //省略创建各个对象的步骤 ClassInfo ci=new ClassInfo(); ci.setCname("java_7"); ci.setRemark("java7班"); ClassDetail cd=new ClassDetail(); cd.setClassInfo(ci); cd.setDetail("Sorry~No detail here!"); cd.setRemark("the Java Seven"); //关键的来了~session中只需要save(cd)就可以达到同时save(ci)的目的! session.save(cd); <!-- //对了,这里突然想起一件事,也就是老师说的一个对象只对应一条数据! eg: ClassInfo ci=new ClassInfo(); ci.setCname("java7"); ci.setRemark("7"); session.save(ci); ci.setCname("java8"); ci.setRemark("8"); session.save(ci); ci.setCname("java9"); ci.setRemark("9"); session.save(ci); 这些代码运行下去其实数据中是不会存入三条数据的,就只会存入最后一条(已测试)! --> 二,关于表中的联级操作 当配置信息中已形成各个表格中的关系时,这个的增删改就会产生联动关系,这个比较棘手~ 但是产生联动关系都是外键表影响主表(也就是ClassInfo影响StuInfo)! eg: 1,当我们把ClassInfo中的cname改掉的话,就会对StuInfo产生比较头疼的影响! 2,当我们删除外键表时要是有数据在主键表那么就会报错! 为了解决以上问题,我们需要在标签<set>中添加两个属性 万一没有set怎么办?呵呵~没有的话~就建一个吧~反正会用到的! <set name="" inverse="true" cascade="delete"> <key> <one-to-many/> </set> inverse="true"表示修改外键表后依然要保持主键表中原有的数据! cascade="delete"表示可以进行联级删除,也就是时候可以通过外键表删除主键表! 三,把这个配置文件好好的记一下,我记忆力衰退了么~记着这么吃力! <!-- Author:Lovingshu's Forever Date:2011-11-08 21:23 Remark:Happy Birthday to Myself~and Call Of Duty:Modern Warfare 3! -->