hibernate映射
来源:互联网 发布:acrobat dc mac 编辑:程序博客网 时间:2024/04/29 01:49
参考:http://www.cnblogs.com/kubixuesheng/p/5300437.html
多对一单向外键关联关系
多对一关联时多方持有一方的引用。比如学生和班级,多个学生对应一个班级。
单向多对一关联中,(1)多方需要持有一方的引用,(2)多方(学生类)需要额外的配置,需要对持有一方引用的注解<many-to-one>
(3)多方必须保留一个不带参数的构造器 一方班级类无需做任何多余操作 <many-to-one>
具有以下属性:
name:一方的引用名
class:一方对应的持久化类
column:外键的列名
fetch:抓取策略
cascade:级联操作,有以下取值
- all 对所有操作进行级联操作
- save-update执行保存和更新操作时进行级联操作
- delete执行删除操作时进行级联操作
- none对所有操作不进行级联操作
多方:学生类和其对应的hbm.xml(因为hibernate具有二级缓存,缓存会将对象写进缓存,所以一般要实现serializable接口)
public class Student implements Serializable{ private int sid; private String sname; private String sex; private Grade grade;//持有多方的引用 public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; } public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Student() { // TODO Auto-generated constructor stub } public Student(String sname, String sex) { super(); this.sname = sname; this.sex = sex; }}
<?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"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="entity.Student" table="student"> <id name="sid" type="java.lang.Integer"> <column name="sid" /> <generator class="increment" /> </id> <property name="sname" type="java.lang.String"> <column name="sname" length="20" not-null="true"/> </property> <property name="sex" type="java.lang.String"> <column name="sex"></column> </property> <many-to-one name="grade" class="entity.Grade" column="gid" cascade="all"></many-to-one> </class></hibernate-mapping>
一方:班级类(无需多余定义)
public class Grade implements Serializable { private int gid; private String gname; private String gdesc; public int getGid() { return gid; } public void setGid(int gid) { this.gid = gid; } public String getGname() { return gname; } public void setGname(String gname) { this.gname = gname; } public String getGdesc() { return gdesc; } public void setGdesc(String gdesc) { this.gdesc = gdesc; } public Grade(String gname, String gdesc) { super(); this.gname = gname; this.gdesc = gdesc; } public Grade() { // TODO Auto-generated constructor stub }}
<?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"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="entity.Grade" table="grade"> <id name="gid" type="java.lang.Integer"> <column name="gid" /> <generator class="increment" /> </id> <property name="gname" type="java.lang.String"> <column name="gname" length="20" not-null="true"/> </property> <property name="gdesc" type="java.lang.String"> <column name="gdesc" length="50"></column> </property> </class></hibernate-mapping>
HibernateSessionFactoryUtil类用于获得sessionFactory和获得Session
public class HibernateSessionFactoryUtil { private static SessionFactory sessionFactory; private static Session session; static { //创建Configuration对象,读取hibernate.cfg.xml文件,完成初始化 Configuration cof = new Configuration().configure(); //ServiceRegistry 是 Service 的注册表, 它为Service提供了一个统一的加载 /初始化 /存放 /获取机制. ServiceRegistryBuilder ssrb = new ServiceRegistryBuilder() .applySettings(cof.getProperties()); ServiceRegistry ssr=ssrb.buildServiceRegistry(); sessionFactory=cof.buildSessionFactory(ssr); } public static SessionFactory getSessionFactory(){ return sessionFactory; } public static Session getSession(){ session=sessionFactory.openSession(); return session; } public static void closeSession(Session session){ if(session!=null) session.close(); } }
下面进行测试
public class Test { public static void main(String[] args) { add(); } public static void add(){ Grade g=new Grade("java开发","java开发一班"); Student stu1=new Student("张三","女"); Student stu2=new Student("李四","男"); Session session=HibernateSessionFactoryUtil.getSession(); Transaction tx=session.beginTransaction(); stu1.setGrade(g); stu2.setGrade(g); //由于进行了级联操作,只需save学生类,班级类会自动存储 session.save(stu1); session.save(stu2); tx.commit(); HibernateSessionFactoryUtil.closeSession(session); }
hibernate.cfg.xml加上:
<mapping resource="entity/Grade.hbm.xml" /><mapping resource="entity/Student.hbm.xml"/>
执行结果:
控制台输出:
Hibernate: select max(sid) from student
Hibernate: select max(gid) from grade
Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?)
Hibernate: insert into student (sname, sex, gid, sid) values (?, ?, ?, ?)
Hibernate: insert into student (sname, sex, gid, sid) values (?, ?, ?, ?)
数据库添加的记录:
student表
grade表
一对多单向外键关联
当类与类建立了关联,程序能很方便的从一个对象导航到另一个或一组与之关联的对象,有了student对象,就可以通过student对象得到grade的信息–student.getGrade(),对于班级对象,如果想要得到学生的信息,怎么办呢?这时候可以反过来控制,一方控制多方,接下来进行一对多单向外键关联
(1)一方持有多方的集合(2)一方的hbm.xml有<set>
配置,其含有子标签<one-to-many>
和<key>
子标签(3)不管是一对多还是多对一,多方都要保留无参构造器
多方:grade增加了Set<Stuent>
public class Grade implements Serializable { private int gid; private String gname; private String gdesc; //在一方定义多方的集合 private Set<Student> students=new HashSet<Student>(); public int getGid() { return gid; } public void setGid(int gid) { this.gid = gid; } public String getGname() { return gname; } public void setGname(String gname) { this.gname = gname; } public String getGdesc() { return gdesc; } public void setGdesc(String gdesc) { this.gdesc = gdesc; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public Grade(String gname, String gdesc) { super(); this.gname = gname; this.gdesc = gdesc; } public Grade() { // TODO Auto-generated constructor stub }}
Grade.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"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="entity.Grade" table="grade"> <id name="gid" type="java.lang.Integer"> <column name="gid" /> <generator class="increment" /> </id> <property name="gname" type="java.lang.String"> <column name="gname" length="20" not-null="true"/> </property> <property name="gdesc" type="java.lang.String"> <column name="gdesc" length="50"></column> </property> <set name="students" table="student" inverse="false" cascade="save-update"> <key column="gid"></key> <one-to-many class="entity.Student"/> </set> </class> <!-- 添加了set,name表示Grade类中Set变量的名字,table表示对应的数据库中的表,inverse指定关联关系的控制方向,默认由one方控制,也就是在多方的inverse属性,有关这个理解见我另一篇博文 -->
student类不做任何添加,在这里省去
下面执行test
public class Test { public static void main(String[] args) { add(); } public static void add(){ Grade g=new Grade("java开发","java开发一班"); Student stu1=new Student("张三","女"); Student stu2=new Student("李四","男"); Session session=HibernateSessionFactoryUtil.getSession(); Transaction tx=session.beginTransaction(); g.getStudents().add(stu1); g.getStudents().add(stu2); session.save(g); tx.commit(); HibernateSessionFactoryUtil.closeSession(session); }
控制台输出:
Hibernate: select max(gid) from grade
Hibernate: select max(sid) from student
Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?)
Hibernate: insert into student (sname, sex, sid) values (?, ?, ?)
Hibernate: insert into student (sname, sex, sid) values (?, ?, ?)
Hibernate: update student set gid=? where sid=?
Hibernate: update student set gid=? where sid=?
数据库数据也载入正常
总结:多对一的时候,多方设置EAGER(积极加载),一方设置LAZY(懒加载),也就是说,如果是多对一,多方控制一方,那么多方设置积极加载,一方无需多余配置,反过来,如果是一对多关系,一方控制多方,那么一方设置懒加载,多方无需多余配置,但是不论哪种,多方都显式加上一个不带参数的构造器。(其实对于懒加载与否,这些配置是默认的)
一对多双向关联
其实类似之前的一对一双向外键关联,也是互相持有对方的引用,故也叫双向一对多自身关联。多方持有一方的引用,反过来,一方也持有多方的集合
多对多单向关联
在多对多关联关系中,显然不能互相持有对方主键做外键,那么就需要用到一个新的表作为中间表进行映射
举例:学生和老师
创建表teacher和teachers_students
create table teacher( -> tid int primary key, -> tname varchar(20)); create table teachers_students( -> sid int not null, -> tid int not null); alter table teachers_students add primary key (sid,tid);
Student类新增:
public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } public Grade getGrade() { return grade; }
Student.hbm.xml新增
<!-- table设置中间表 --><set name="teachers" table="teachers_students" cascade="all" inverse="false"><!-- key设置本对象在中间表的外键sid --><key column="sid" /><!-- tid设置对方的表(老师)在中间表的外键tid --><many-to-many class="entity.Teacher" column="tid"></many-to-many></set>
老师不做多余配置
public class Teacher implements Serializable{ private int tid; private String tname; public int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public Teacher(String tname) { super(); this.tname = tname; } public Teacher() { super(); // TODO Auto-generated constructor stub }}
<?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"><!-- Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping> <class name="entity.Teacher" table="teacher"> <id name="tid" type="java.lang.Integer"> <column name="tid" /> <generator class="increment" /> </id> <property name="tname" type="java.lang.String"> <column name="tname" length="20" not-null="true"/> </property> </class></hibernate-mapping>
测试:
Student s=new Student("学生1","女"); Set<Teacher> teas=s.getTeachers(); Teacher t1=new Teacher("张三"); Teacher t2=new Teacher("李四"); Teacher t3=new Teacher("王五"); teas.add(t1); teas.add(t2); teas.add(t3); Session session=HibernateSessionFactoryUtil.getSession(); Transaction tx=session.beginTransaction(); session.save(s); tx.commit(); HibernateSessionFactoryUtil.closeSession(session);
控制台输出
Hibernate: select max(sid) from student
Hibernate: select max(tid) from teacher
Hibernate: insert into student (sname, sex, gid, sid) values (?, ?, ?, ?)
Hibernate: insert into teacher (tname, tid) values (?, ?)
Hibernate: insert into teacher (tname, tid) values (?, ?)
Hibernate: insert into teacher (tname, tid) values (?, ?)
Hibernate: insert into teachers_students (sid, tid) values (?, ?)
Hibernate: insert into teachers_students (sid, tid) values (?, ?)
Hibernate: insert into teachers_students (sid, tid) values (?, ?)
数据库存储正常
多对多双向外键关联
和之前的类似,是互相持有对方的集合,双方持有对方的集合对象
Teacher类添加:
private Set<Student> students=new HashSet<Student>(); public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; }
Teacher.hbm.xml添加
<set name="students" table="teachers_students" cascade="all" inverse="false"> <key column="tid"></key> <many-to-many class="entity.Student" column="sid"></many-to-many> </set>
关联关系的优缺点
用关联关系,就可以直接操作内存中的对象,不用每次都查询数据库,会提高效率;而且域模型真实反映了客观世界的关系,但是缺点就是建立复杂的关联关系会给程序开发带来麻烦,当修改一个对象时,会牵连其它的对象
问题小结
(1)注意在多对一/一对多关系里:多方必须保留一个不带参数的构造器!
(2)如果没有设置级联ALL,那么需要在保存的时候先保存班级,在保存学生,否则出错: object references an unsaved transient instance - save the transient instance before flushing:
(3)多对一时候,多方设置EAGER加载,一对多的时候,一方设置LAZY加载
(4)多对多关联,多方需要保留一个无参构造器。
- hibernate映射
- hibernate映射
- hibernate映射
- hibernate映射
- Hibernate 映射
- hibernate映射
- hibernate映射
- Hibernate------映射
- Hibernate映射
- hibernate映射
- hibernate 映射
- hibernate映射
- Hibernate映射
- hibernate映射
- Hibernate映射
- hibernate映射
- hibernate映射
- HIbernate映射
- 设计模式之策略模式
- JS选项卡之---判断鼠标是移到自己还是选项卡上面
- oracle sys_connect_by_path 函数
- 获取View在onCreate中的坐标
- UML类图几种关系的总结(转载http://blog.csdn.net/tianhai110/article/details/6339565)
- hibernate映射
- iOS 设置圆角
- APP产品整体运营方案及上架一个月动作
- SAP HR Schema 详解(三)工资核算基础
- 【Jenkins】Jenkins入门系列之——01第一章 Jenkins是什么?
- ntellij idea 修改背景保护色&&修改字体&&快捷键大全
- 标题:算年龄
- XML生成Java类代码
- 最近所有博客