一.概述
单向一对多,双向多对多我就不写了,网上好多。一对多,多对一都是为了表级完整性,防止数据冗余,无意义数据记录的产生。作用其实就是相当于前台的表单验证,你输了一个密码,这个密码在表里不存在,会出错。
一对多和多对一都是在多那一段的表建立外键关联,就是去维护数据方不同。
单向一对多:当一这一端的对象需要用到多这一端的对象。比如班级类对象,一个班级有很多学生,我想在加载班级的时候顺便加载所有的学生,显示他们的名字,这样的话我们就要在班级对象里存放一个集合属性,用来存放相关班级的所有学生了。
我这里用的是list,对应你实际的例子用对应的最好的东西,list是有序可以重复,set是无序不可以重复,因为不能重复所以往往用set
二.代码
1.单向一对多。
①class.java--班级类,代表一这端
package com.st.test; import java.util.ArrayList; import java.util.List; public class Class { private int id;//自增主键 private String className;//班级名 private List<Student> students=new ArrayList<Student>();//一对多中用到的多一端的对象 //对应getter,setter public int getId() { return id; } public void setId(int id) { this.id = id; } public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { System.out.println(students.size()); for(Student s:students){ System.out.println("设置studnets+"+s.getStudentname()); } this.students = students; } }
②student.java
package com.st.test; public class Student { private int id;//主键 private String studentname;//学生名 //对应gettter,setter public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStudentname() { return studentname; } public void setStudentname(String studentname) { this.studentname = studentname; } }
③Class.hbm.xml--关键的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 2017-4-24 15:36:01 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <!-- 下面就是这个class对应的配置 --> <class name="com.st.test.Class" table="CLASS"> <!-- 下面这个节点是配置主键 --> <id name="id" type="int"> <column name="ID" /> <generator class="identity" /> </id> <!-- 普通的属性配置 --> <property name="className" type="java.lang.String"> <column name="CLASSNAME" /> </property> <!-- 下面是个重要的点:key里的column表示你想在student表里作为外键关联的那列的列名,别用自动生成的’ID‘这个名字,会和student的自增主键id冲突 --> <list name="students" inverse="false" table="STUDENT" lazy="true"> <key> <column name="class_id" /> </key> <!-- 这个是用list做集合时会有的,它会在表后面再加一列idx,作为元素在list里的位子。 --> <list-index></list-index> <one-to-many class="com.st.test.Student" /> </list> </class> </hibernate-mapping>
④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 2017-4-24 13:55:39 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="com.st.test.Student" table="STUDENT"> <id name="id" type="int"> <column name="ID" /> <generator class="identity" /> </id> <property name="studentname" type="java.lang.String"> <column name="STUDENTNAME" /> </property> </class> </hibernate-mapping>
⑤测试代码
package com.st.test; import java.util.ArrayList; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.springframework.transaction.annotation.Transactional; @Transactional public class Test { public static void main(String[] args) { Configuration cfg = new Configuration(); cfg.configure();//此处不指定,会默认读取src根目录下名为hibernate.cfg.xml的文件。也可以指定如:cfg.configure(“hibernate.xml”); SessionFactory sessionfactory = cfg.buildSessionFactory(); Session session=sessionfactory.openSession(); session.beginTransaction();//事务开始 //先声明要用到的多的一端的对象,并且保存,不保存,这个对象还是游离对象 Student s1=new Student(); s1.setStudentname("student1"); Student s2=new Student(); s2.setStudentname("student2"); session.save(s1); session.save(s2); //student对象声明结束 //list是因为我们要设置这个班级的属性student学生集合时用的 List<Student> list=new ArrayList<Student>(); list.add(s1); list.add(s2); //声明一端对象class,并且保存到数据库 Class c=new Class(); c.setClassName("class1"); c.setStudents(list); session.save(c); session.getTransaction().commit();//事务提交,这之后数据库就会改变 } }
⑥sql语句
Hibernate: insert into STUDENT (STUDENTNAME) values (?) Hibernate: insert into STUDENT (STUDENTNAME) values (?) Hibernate: insert into CLASS (CLASSNAME) values (?) Hibernate: update STUDENT set class_id=?, idx=? where ID=? Hibernate: update STUDENT set class_id=?, idx=? where ID=?
*从这里我们也可以看出,由一这一端去维护后面要多用update语句去更新对应的student的外键关联列,这里还好只是2个对象,要是多了,这update语句就可怕了。所以多对一比一对多要好一些的。
*还有就是,在student表的那个外键class_id不可以设置为not null,因为设置了非空约束的话,一开始的保存student对象就会出错,因为你保存student时是暂时没有设置外键关联的那个class的id值的
三.总结
这是我在测试hibernate,单向一对多,单向多对一,双向多对多过程中,单向一对多是唯一不小心出错的,简单记录下,这个东西网上有很多的参考。前辈们路过,有错的地方请指正,谢谢大家。