Hibernate中的关系映射
-
都需要 hibernate.cfg.xml 中配置 mapper
* hibernate.cfg.xml <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 数据源 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/hibernate01</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <!-- SQL dialect sql方言--> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <!-- 控制台打印sql以及格式化sql --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!--映射文件 --> <mapping resource="com/demos/bean/News.hbm.xml"/> <mapping resource="com/demos/bean/Student.hbm.xml"/> <mapping resource="com/demos/bean/Paper.hbm.xml"/> <mapping resource="com/demos/bean/Grade.hbm.xml"/> <mapping resource="com/demos/bean/Course.hbm.xml"/> </session-factory> </hibernate-configuration>
-
双向的一对一
Student-----Paper 1.表与表之间的关系转换为实体和实体之间的关系,在双方的实体类中加入另一方的实体类型属性 在Student类中添加Papper类型的属性以及其set和get方法,(一定不能写 gid 外键字段,会冲突) * 字段 (sid,sname,sex,gid) * public class Student { private int sid; private String sname; private String sex; private Paper paper; } 在Paper类中添加Student类型的属性以及其set和get方法。 * 字段(pid(既是主键,又是外键),pdesc) * public class Paper { private int pid; private String pdesc; private Student student; } 2.在映射文件中配置自定义类型属性映射 * Paper.hbm.xml <?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"> <!--package:实体类所在的包名,可以省略,省略后class里的类名写全路径(包名+类名) --> <hibernate-mapping package="com.demos.bean"> <!-- name:指定类名 ,table:实体类对应的数据库表名--> <class name="Paper" table="paper" > <!--id:主键,name:类中主键对应的的属性名,column:表里主键的列名 --> <id name="pid" type="java.lang.Integer"> <column name="pid" /> <!-- 设置主键的增长方式:使用另外一个相关联的对象的主键作为该对象主键 --> <generator class="foreign"> <!-- 设置另外一个相关联的对象(在当前类中关联另一方的属性名) --> <param name="property">student</param> </generator> </id> <!-- column省略不写,默认和属性名一致, type:指定列或者属性的类型,有三种指定方式(属性类型,hibernate 提供的类型,数据库列的类型) --> <property name="pdesc" type="java.lang.String"> <column name="pdesc" length="50" not-null="true" /> </property> <!-- name:自定义类型的属性名, class="自定义属性的类型" , cascade:级联操作,默认none,save-update,delete,all constrained通过外键来级联--> <one-to-one name="student" class="Student" cascade="all" constrained="true"></one-to-one> </class> </hibernate-mapping> 语法: <one-to-one name="自定义类型的属性名" class="自定义类型的属性的类型"> </one-to-one> 注意:含有外键的实体映射文件中主键的增长方式 * Student.hbm.xml <?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"> <!-- 此处表示的是进行POJO类与数据表之间的映射 --> <hibernate-mapping package="com.demos.bean"> <!-- 配置的是类的相关定义,name表示类的名字,同时设置table对应的数据表,catalog表示的是数据库的名字 --> <class name="Student" table="student"> <!-- 配置主键,name表示的是类之中的属性名称,type表示的是student类的sid类型 --> <id name="sid" type="java.lang.Integer"> <column name="sid" /> <!-- 主键的生成方式,根据代码自动分配 --> <generator class="assigned"></generator> </id> <property name="sname" type="java.lang.String"> <!-- 定义类中的属性与表之中的映射字段 --> <column name="sname" length="50" not-null="true" /> </property> <property name="sex" type="java.lang.String"> <column name="sex" length="10" /> </property> <!-- name:自定义类型的属性名,class="自定义属性的类型" --> <one-to-one name="paper" class="Paper"></one-to-one> </class> </hibernate-mapping> 3.测试使用 public class OneToOne { Session session; @Before public void startUp() { Configuration configure = new Configuration().configure("hibernate.cfg.xml"); SessionFactory sf = configure.buildSessionFactory(); session = sf.openSession(); } // 根据学生的id查询学生的基本信息以及其学生证信息(面向对象) @Test public void getinfo() { Student student = session.get(Student.class, 6001); System.out.println(student); //Paper paper = student.getPaper(); //System.out.println(paper); } // 保存学生以及学生的学生证信息 @Test public void saveStuPaper() { Student s = new Student(); s.setSid(71503001); s.setSname("小张"); s.setSex("男"); Paper p = new Paper(); p.setPdesc("河大"); p.setStudent(s); //session.save(s); session.save(p); session.beginTransaction().commit(); session.close(); } // 根据学生证号71503001更新学生证描述以及学生的姓名 @Test public void updateSp() { // 获取学生证信息根据学生证号 Paper paper = session.get(Paper.class,71503001); paper.setPdesc("北京大学"); Student student = paper.getStudent(); student.setSname("夏夏"); session.beginTransaction().commit(); session.close(); } }
-
一对多
Grade ----Student 1.在一的一方加入多的一方的Set集合属性,在多的一方加入一的一方的实体属性。 在Grade中加入Student的Set集合属性以及属性的set,get方法 Grade.java public class Grade { private int gid; private String gname; private String gdesc; private Set<Student> sSet = new HashSet<>(); } 在Student中加入Grade的实体属性以及属性的set,get方法 Student.java private Grade grade; 2.映射文件 一的一方的映射文件: * Grade.hbm.xml <?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 package="com.demos.bean"> <class name="Grade" table="grade" > <id name="gid" type="java.lang.Integer"> <column name="GID" /> <generator class="assigned" /> </id> <property name="gname" type="java.lang.String"> <column name="GNAME" length="10" not-null="true" /> </property> <property name="gdesc" type="java.lang.String"> <column name="GDESC" length="50" /> </property> <!--name:set集合属性名 --> <set name="sSet"> <!--column:多的一方表中的外键字段 --> <key column="gid"></key> <!--class:关联的另一方的类型 --> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> 多的一方的映射文件: * Student.hbm.xml <?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"> <!-- 此处表示的是进行POJO类与数据表之间的映射 --> <hibernate-mapping package="com.demos.bean"> <!-- 配置的是类的相关定义,name表示类的名字,同时设置table对应的数据表,catalog表示的是数据库的名字 --> <class name="Student" table="student"> <!-- 配置主键,name表示的是类之中的属性名称,type表示的是student类的sid类型 --> <id name="sid" type="java.lang.Integer"> <column name="sid" /> <!-- 主键的生成方式,根据代码自动分配 --> <generator class="assigned"></generator> </id> <property name="sname" type="java.lang.String"> <!-- 定义类中的属性与表之中的映射字段 --> <column name="sname" length="50" not-null="true" /> </property> <property name="sex" type="java.lang.String"> <column name="sex" length="10" /> </property> <!-- name:自定义类型的属性名,class="自定义属性的类型" --> <one-to-one name="paper" class="Paper" ></one-to-one> <!--name:关联的一的一方的属性名,class:属性的类型 column:当前方和另一方关联的外键字段--> <many-to-one name="grade" class="Grade" column="gid"></many-to-one> </class> </hibernate-mapping> 3.测试 public class OneToMany { Session session; @Before public void startUp() { Configuration configure = new Configuration().configure("hibernate.cfg.xml"); SessionFactory sf = configure.buildSessionFactory(); session = sf.openSession(); } // 根据年级的id获取年级的基本信息以及该年级下的学生 @Test public void getinfo() { Grade grade = session.get(Grade.class, 4); /*System.err.println(grade); Set<Student> sSet = grade.getsSet(); for (Student student : sSet) { System.err.println(student); }*/ System.out.println(grade.getGname() + "--" + grade.getGdesc()); Set<Student> sset = grade.getsSet(); for (Student s : sset) { System.out.println(s.getSid() + "--" + s.getSname()); } } // 将某个新生加入到4年级 @Test public void addStuToGtade() { Grade grade = session.get(Grade.class, 4); Student s = new Student(); s.setSid(71503003); s.setSname("小李"); s.setSex("男"); //grade.getsSet().add(s); s.setGrade(grade); session.save(s); session.beginTransaction().commit(); session.close(); } }
-
多对多
学生----课程 1.在双方的实体类中加入另一方的set集合属性 * 在Student 类中添加Course的集合属性以及其set,get方法 private Set<Course> cSet = new HashSet<>(); * 在Course类中添加Student的集合属性以及其set,get方法 private Set<Student> sSet = new HashSet<>(); 2.映射文件 * Student.hbm.xml <?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"> <!-- 此处表示的是进行POJO类与数据表之间的映射 --> <hibernate-mapping package="com.demos.bean"> <!-- 配置的是类的相关定义,name表示类的名字,同时设置table对应的数据表,catalog表示的是数据库的名字 --> <class name="Student" table="student"> <!-- 配置主键,name表示的是类之中的属性名称,type表示的是student类的sid类型 --> <id name="sid" type="java.lang.Integer"> <column name="sid" /> <!-- 主键的生成方式,根据代码自动分配 --> <generator class="assigned"></generator> </id> <property name="sname" type="java.lang.String"> <!-- 定义类中的属性与表之中的映射字段 --> <column name="sname" length="50" not-null="true" /> </property> <property name="sex" type="java.lang.String"> <column name="sex" length="10" /> </property> <!-- name:自定义类型的属性名,class="自定义属性的类型" --> <one-to-one name="paper" class="Paper" ></one-to-one> <!--name:关联的一的一方的属性名,class:属性的类型 column:当前方和另一方关联的外键字段--> <many-to-one name="grade" class="Grade" column="gid"></many-to-one> <!--name:另一方的集合属性名,table:中间表 --> <set name="cSet" table="sc"> <!--column:当前方和中间表关联的外键字段 --> <key column="sid"></key> <!--column:关联的另一方和中间表关联的外键字段 class: 关联的另一方的类型 --> <many-to-many column="cid" class="Course"></many-to-many> </set> </class> </hibernate-mapping> * Course.hbm.xml <?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 package="com.demos.bean"> <class name="Course" table="COURSE" > <id name="cid" type="java.lang.Integer"> <column name="CID" /> <generator class="assigned" /> </id> <property name="cname" type="java.lang.String"> <column name="CNAME" length="20" not-null="true" /> </property> <property name="cdesc" type="java.lang.String"> <column name="CDESC" length="50" /> </property> <set name="sSet"> <!--column:当前方和中间表关联的外键字段 --> <key column="cid"></key> <!--column:关联的另一方和中间表关联的外键字段 class: 关联的另一方的类型 --> <many-to-many column="sid" class="Student"></many-to-many> </set> </class> </hibernate-mapping> 3.测试 public class ManyToMany { Session session; @Before public void startUp() { Configuration configure = new Configuration().configure("hibernate.cfg.xml"); SessionFactory sf = configure.buildSessionFactory(); session = sf.openSession(); } // 根据学生的id查询学生的基本信息以及学生选修的所有课程 @Test public void getStuCous() { Student stu = session.get(Student.class, 71503001); System.out.println(stu.getSname()); Set<Course> cset = stu.getcSet(); for (Course c : cset) { System.out.println(c.getCname()); } } // 让某个学生选修某门课程 @Test public void tosc() { Student stu = session.get(Student.class, 71503002);// 持久状态 Course course = session.get(Course.class, 1001);// 持久状态 stu.getcSet().add(course); // course.getSset().add(stu); // session.update(stu); session.beginTransaction().commit(); session.close(); } }