hibernate表关联
很多同学在进行编程学习时缺乏系统学习的资料。本页面基于hibernate表关联内容,从基础理论到综合实战,通过实用的知识类文章,标准的编程教程,丰富的视频课程,为您在hibernate表关联相关知识领域提供全面立体的资料补充。同时还包含 h6、hack、hadoop 的知识内容,欢迎查阅!
hibernate表关联相关知识
-
myeclipse试用小记----Hibernate多对一双向关联(2)myeclipse试用小记----Hibernate多对一双向关联(2) 在上篇文章“myeclipse试用小记----Hibernate多对一单向关联(1)”中,讲到了“Hibernate多对一单向关联”,现在我打算把这个做成双向的,也就是多对一双向关联,看看myeclipse是如何实现的。 环境、数据库还和上篇文章的一样。只是表中的数据清空了。 注意:对于有外键的表,清空数据有两种方法:第一是先drop掉外键约束后,进行清除。第二种是先清除从表数据(orders),然后清除主表的数据(customers),具体我及不说了,有空我在写写数据库外键约束的方面的文章,这点也很重要的。 步骤1、清除orders、customers两表数据。2、用myeclipse新建web工程sx_d2y,加入hibernate支持。3、同时选中orders、customers生成实体Bean和mapping文件,并对mapping做小的改动。4、写两个测试类,分别保存Orders对象和
-
Hibernate一对一关联关系介绍和简单demo开头说两句: Hibernate一对一关系分为两种: 1.主键关联一对一映射:例如在两个表a,b中,一个字段在a表中是主键,a表中的该字段级联b表中的字段,该字段在b表中作为主键,也就是当a表中该字段修改时,b表中的字段随之改变;通过<one-to-one>元素配置, 2.唯一外键关联一对一映射:一对多关系的一种特例,主键表对应实体类的配置文件中通过one-to-one元素配置。 在这里我说一下第一种情况,第二种情况就不再说明了,好了,我们开始做demo. demo介绍:有两个表,分别是register表和userInfo表
-
Oracle:Hibernate关联映射Hibernate关联映射 一:关联关系 从一个表到另一个表的关联就称为:单向关联 如果同时包含两种表就称:为双向关联 *映射关系如下: 多对一单向关联关系 一对多双向关联关系 多对多关联关系 持久化操作:保存 Public class EmpDao extends BaseDao{ Public void save(Emp emp){ This.currentSession().save(emp);//省略其它代码 } } 建立双向一对多关联关系: 列如:给定Emp对象,如果想获得与它关联的Dept对象:如下 Dept dept=emp.getDept();//从Emo对象导航到关联的De
-
Hibernate【入门篇】tags: Hibernate 前言 本博文主要讲解介绍Hibernate框架,ORM的概念和Hibernate入门,相信你们看了就会使用Hibernate了! 什么是Hibernate框架? Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象! 为什么要使用Hibernate? 既然Hibernate是关于Java对象和关系数据库之间的联系的话,也就是我们MVC中的数据持久层->在编写程序中的DAO层... 首先,我们来回顾一下我们在DAO层写程序的历程吧: 在DAO
hibernate表关联相关课程
hibernate表关联相关教程
- 2. 关联映射 关系数据库中的数据以表为家,一张表一个家,一个家住一类数据。众多表组成关系型社区,关系型社区群体中的数据关系通过主外键方式描述。表与表之间的数据根据彼此的关系可分为:一对一关系: 如老公表和老婆表的关系;一对多关系: 如用户表和银行账号表关系;多对一关系: 如银行帐号表对用户表关系;多对多关系: 如学生表和课程表关系。不管是哪种关系,都可以通过主外键方式联系。一对多、多对一本质一样,正如一块硬币的正反面,看待同一个事物的角度不同。多对多通过中间表的方式拆分成两个一对多(多对一)。以上都是关系型数据库中的基础知识,美好的回忆有助于巩固。开发者使用 Hibernate 操作某一张表中的数据时,有 2 件事情要做:在程序中构建一个与表结构相似的类(这个类可称为实体 [entity] 类);使用注解或 XML 语法把类结构和表结构关联映射起来(此时这个类可称为 PO)。有了 PO,Hibernate 就能在程序和数据库之间进行数据贸易往来。
- 3. 关联映射中的延迟加载 关联多表查询时可选择是否启用延迟加载。PO 之间的映射,意味着 Hibernate 不仅能查询到指定表中数据,还能查询相关联表中的数据。但,有时只需要查询学生基本信息,并不需要地址信息,或者地址信息并不需要马上查询出来,能不能告诉 Hibernate,只查询学生信息,暂且别查询地址信息。同样,有时只需要查询所在地址,并不关心地址对应学生信息。可以启动关联映射中的延迟加载实现上面的需求。学生类中修改代码如下:@OneToOne(targetEntity = Address.class,fetch=FetchType.LAZY)@JoinColumn(name = "addressId")public Address getAddress() { return address;}@OneToOne 注解有 fetch 属性,为枚举类型,其值可选择:FetchType.LAZY;FetchType.EAGER。其作用便是告诉 Hibernate,是否延后或立即查询相关联表中的数据。执行下面测试代码:try { transaction = session.beginTransaction(); Student stu = (Student) session.get(Student.class, new Integer(1)); System.out.println("----------------学生信息---------------"); System.out.println("学生姓名:" + stu.getStuName()); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}查看结果:Hibernate: select student0_.stuId as stuId1_1_0_, student0_.addressId as addressI6_1_0_, student0_.stuName as stuName2_1_0_, student0_.stuPassword as stuPassw3_1_0_, student0_.stuPic as stuPic4_1_0_, student0_.stuSex as stuSex5_1_0_ from Student student0_ where student0_.stuId=?----------------学生信息---------------学生姓名:Hibernate老大Hibernate 只构建了一条简单的 Sql 语句, 用于查询学生信息。继续执行下面测试实例:try { transaction = session.beginTransaction(); Student stu = (Student) session.get(Student.class, new Integer(1)); System.out.println("----------------学生信息---------------"); System.out.println("学生姓名:" + stu.getStuName()); System.out.println("-----------------地址信息-----------------"); System.out.println("学生家庭地址:" + stu.getAddress().getAddressName()); transaction.commit();} catch (Exception e) { transaction.rollback();} finally { session.close();}输出结果:Hibernate: select student0_.stuId as stuId1_1_0_, student0_.addressId as addressI6_1_0_, student0_.stuName as stuName2_1_0_, student0_.stuPassword as stuPassw3_1_0_, student0_.stuPic as stuPic4_1_0_, student0_.stuSex as stuSex5_1_0_ from Student student0_ where student0_.stuId=?----------------学生信息---------------学生姓名:Hibernate老大-----------------地址信息-----------------Hibernate: select address0_.addressId as addressI1_0_0_, address0_.addressName as addressN2_0_0_, address0_.descript as descript3_0_0_ from Address address0_ where address0_.addressId=?学生家庭地址:北京Hibernate 分别构建了 2 条简单的查询 Sql 语句,可得出结论:只有当需要获取地址信息时,才会构建 Sql 语句查询地址表;这就是关联映射中的延迟加载。@OneToOne 默认情况下是采用立即策略,通过构建多表查询语句一次性全部查询。
- 4. 一对多关联映射中的级联操作 什么是级联操作?关系型数据库中由主外键维系的两张表,具有主从关系。如学生表和班级表,班级班是主表,学生表是从表。类似于删除某一个班级的信息,则需要先删除所在班的学生信息,再删除班级信息,这个操作就是级联操作。所谓级联操作,指操作一张表时,是否会牵连到与之有关联的其它表。现在,咱们是使用 Hibernate 进行数据操作,不可能还要劳驾自己亲力亲为吧。只需要做些简单配置,就可以让 Hibernate 自动做级联操作。进入班级类,修改代码如下:@OneToMany(targetEntity=Student.class,mappedBy="classRoom",cascade=CascadeType.REMOVE) public Set<Student> getStudents() { return students; }很简单,只需要使用 @OneToMany 的 cascade 属性,就能让 Hibernate 明白如何做级联操作。默认情况下,没有级联效应。cascade 是一个枚举类型:public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH}ALL: 级联所有操作;PERSIST: 级联新增;MERGE: 级联更新或者新增;REMOVE: 级联删除;REFRESH: 级联刷新;DETACH: 级联分离。测试删除班级实例:HibernateTemplate<ClassRoom> hibernateTemplate = new HibernateTemplate<ClassRoom>(); hibernateTemplate.template(new Notify<ClassRoom>() { @Override public ClassRoom action(Session session) { ClassRoom classRoom=(ClassRoom)session.get(ClassRoom.class, new Integer(1)); session.delete(classRoom); return null; } });如果不添加 cascade 相关说明,因为有学生引用班级信息,班级信息是不能被删除的。添加后再测试,查看表中内容:班级以及班级所在学生信息全部删除!删除班级时能级联删除学生,反过来,删除学生能删除班级吗?想法很好,实践是检验真理的唯一手段,学生类中修改成如下代码:@ManyToOne(targetEntity=ClassRoom.class,cascade=CascadeType.REMOVE) @JoinColumn(name="classRoomId") public ClassRoom getClassRoom() { return classRoom; }测试实例:HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { Student stu=(Student)session.get(Student.class, new Integer(2)); session.delete(stu); return stu; } });结果很残酷!学生被删除了,班级也被删除了!级联级联,只要设置了级联,不管删除学生还是班级,只要在对应表中有引用关系的数据就会被删除。现在,学生类、班级类中的级联删除都打开了。如果对下面情形的数据(编号 1、2 的学生的班级编号都为 1)进行删除操作,则会发生什么事情?数据库中的数据如下:测试删除编号为 1 的学生:HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { Student stu=(Student)session.get(Student.class, new Integer(1)); session.delete(stu); return stu; } });进入 MySql,查看一下:天呀!这是级联还是株连呀,太让人后怕,数据都没有了。删除学生时,会级联删除和学生有关的班级,班级删除时,又会查看学生表中是否还存在与班级有关联的学生,有,则一刀下去,连根拔起。Hibernate 有点刹不住车,产生了级联连锁反应。针对上面的测试,如果班级表的级联关闭,执行测试代码,请问结果又会怎样?本节课程,讲解了级联删除,级联添加的内容留到下节课继续展开。
- 3. 双向一对多关联映射 需求:查询班级时,想知道班上有多少名学生,又应该如何映射?进入班级类,添加如下属性:private Set<Student> students;使用集合属性 students,描述了一个班有多名学生。为什么使用 Set 集合?因为一个班级内不可能出现两个完全相同的学生对象。这还仅仅只是 OOP 层面上的关系,还需要告诉 Hibernate 应该如何填充数据。添加下面代码:private Set<Student> students;@OneToMany(targetEntity=Student.class,mappedBy="classRoom")public Set<Student> getStudents() { return students;}@OneToMany:很直白的说明了一个班级会有多名学生,指引 Hibernate 在填充数据时,要找到所有学生,别遗漏了;属性 mappedBy=“classRoom”: 告诉 Hibernate,班级和学生之间的关系在学生类中已经说的够明白了,应该不需要再废话了吧。OK!把前面的测试实例改为查询班级信息:HibernateTemplate<ClassRoom> hibernateTemplate = new HibernateTemplate<ClassRoom>(); hibernateTemplate.template(new Notify<ClassRoom>() { @Override public ClassRoom action(Session session) { ClassRoom classRoom=(ClassRoom)session.get(ClassRoom.class, new Integer(1)); System.out.println("班级名称:"+classRoom.getClassRoomName());System.out.println("------我是分隔线------------------------"); System.out.println("班级学生人数:"+classRoom.getStudents().size()); return classRoom; } });查看控制台输出结果:Hibernate: select classroom0_.classRoomId as classRoo1_0_0_, classroom0_.classRoomDesc as classRoo2_0_0_, classroom0_.classRoomName as classRoo3_0_0_ from ClassRoom classroom0_ where classroom0_.classRoomId=?班级名称:c1911------我是分隔线------------------------Hibernate: select students0_.classRoomId as classRoo6_0_1_, students0_.stuId as stuId1_1_1_, students0_.stuId as stuId1_1_0_, students0_.classRoomId as classRoo6_1_0_, students0_.stuName as stuName2_1_0_, students0_.stuPassword as stuPassw3_1_0_, students0_.stuPic as stuPic4_1_0_, students0_.stuSex as stuSex5_1_0_ from Student students0_ where students0_.classRoomId=?班级学生人数:2会发现一个很有意思的地方。Hibernate 查询班级时,构建了两条 SQL。先查询班级,当需要学生信息时,才构建查询学生的 SQL。大家应该也猜出来了,当从学生表查询班级表时,Hibernate 采用的是立即策略。当查询从班级表查询到学生表时,Hibernate 采用的是延迟加载策略。采用延迟加载都只有一个目的,需要时加载,提高响应速度。现在,学生类和班级类的映射配置信息,能让 Hibernate 自动从学生表查询到班级表,也能从班级表查询到学生表。这种 2 个实体类中的映射关系就称为双向一对多关联映射。无论是 @ManyToOne 还是 @OneToMany 注解都有 fetch 属性,可以设置的值有 2 个选择:FetchType.EAGERFetchType.LAZY。所以,在双向一对多关联映射可以选择是否启用延迟加载,这和一对一关联映射中是一样的,就不在此重复复述。是否采用延迟加载,由项目逻辑决定。
- 2. 一对多关联映射 关系型数据库中表与表中的数据存在一对多(或多对一)关系。如学生表、班级表。一个班级有多个学生,多个学生可以在同一个班级。一对多或多对一本质上是一样的,如同一块硬币的正面和反面,只是看待事物的角度不同而已。数据库中有学生表、班级表。使用 Hibernate 进行数据操作时, 程序中就应该有学生类、班级类。同时学生类、班级类应该使用 OOP 语法描述出如同学生表和班级表一样的关系。并且还要让 Hibernate 看得懂。有了前面的基础,直接上代码:创建班级类:@Entitypublic class ClassRoom { private Integer classRoomId; private String classRoomName; private String classRoomDesc; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getClassRoomId() { return classRoomId; }需求:查询学生时,得到学生所在班级信息。进入学生类,添加如下代码,描述学生类和班级类的关系:private ClassRoom classRoom;除此之外,还需要让 Hibernate 知道,这个对象属性的值来自于班级表中的对应数据,进一步修改代码:private ClassRoom classRoom;@ManyToOne(targetEntity=ClassRoom.class)@JoinColumn(name="classRoomId")public ClassRoom getClassRoom() { return classRoom;}@ManyToOne 告诉 Hibernate,从学生的角度来看,学生是多的一边,查询班级表可以得到学生所在班级信息。@JoinColumn 告诉 Hibernate 需要带着指定的字段值到班级表中匹配数据。修改 Hibernate 主配置文件中内容:<property name="hbm2ddl.auto">create</property><mapping class="com.mk.po.Student" /><mapping class="com.mk.po.ClassRoom" />为了让事情变得简单明了,在主配置文件中只保留学生类和班级类的映射关系。学生类中的所有属性描述:private Integer stuId; private String stuName; private String stuSex; private String stuPassword; private Blob stuPic; private ClassRoom classRoom; @ManyToOne(targetEntity=ClassRoom.class) @JoinColumn(name="classRoomId") public ClassRoom getClassRoom() { return classRoom; }使用上一节课的模板对象跑一个空测试实例:@Testpublic void testGetByTemplate() { HibernateTemplate<Student> hibernateTemplate=new HibernateTemplate<Student>(); }目的是让 Hibernate 重新创建学生表、班级表。别忘记啦,自动创建表后,修改回:<property name="hbm2ddl.auto">update</property>进入 MySql,在学生表、班级表中手工添加几条测试数据:到了完成需求的时候,测试下面实例:HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { Student stu=(Student)session.get(Student.class, new Integer(1)); System.out.println("学生姓名:"+stu.getStuName()); System.out.println("学生所在班级:"+stu.getClassRoom().getClassRoomName()); return stu_; } });控制台输出结果:Hibernate: select student0_.stuId as stuId1_1_1_, student0_.classRoomId as classRoo6_1_1_, student0_.stuName as stuName2_1_1_, student0_.stuPassword as stuPassw3_1_1_, student0_.stuPic as stuPic4_1_1_, student0_.stuSex as stuSex5_1_1_, classroom1_.classRoomId as classRoo1_0_0_, classroom1_.classRoomDesc as classRoo2_0_0_, classroom1_.classRoomName as classRoo3_0_0_ from Student student0_ left outer join ClassRoom classroom1_ on student0_.classRoomId=classroom1_.classRoomId where student0_.stuId=?学生姓名:Hibernate学生所在班级:c1911Hibernate 使用 left outer join 构建了一条多表查询语句!
- 2.1 解除级联对象之间的关系 删除方式有两种:第一种解除方案HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { // 查询学生 Student student =(Student)session.get(Student.class, new Integer(1)); // 查询Java课程 Course javaCourse = (Course) session.get(Course.class, new Integer(1)); // 查询C课程 Course ccourse = (Course) session.get(Course.class, new Integer(2)); // 解除关系 student.getCourses().remove(javaCourse); student.getCourses().remove(ccourse); return null; } });查询到 ”Hibernate“ 同学的信息,注意,此时 student 对象处于持久化状态,意味着 student 对象在程序世界的行为可以同步到数据库中。查询 ”Hibernate“ 同学选修的 Java 和 C 两门课程,此时保存这两个课程信息的对象也处于持久化状态。使用如下代码解除学生和课程之间的关系:student.getCourses().remove(javaCourse);student.getCourses().remove(ccourse);因为学生对象、课程对象都处于持久化状态。它们在程序世界中的一言一行都会同步到数据库中。既然在程序世界解除了彼此之间的关系,在数据库中,中间表中的关系描述数据也会自动删除。从控制台上所显示出来的 SQL 语句其实也知道删除已经成功,这个就不贴出来了。进入 MySql 验证一下:中间表中已经不存在和 ”Hibernate“ 同学相关的课程信息。但是,此时你可能会有一个想法,刚刚是以学生对象为主动方,向课程对象提出了分手,那么,能不能以课程方为主动方提出分手呢?试一下便知,测试之前,先恢复原来的内容:执行下面的实例代码:HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { // Hiberante学生 Student student =(Student)session.get(Student.class, new Integer(1)); // 查询Java Course javaCourse = (Course) session.get(Course.class, new Integer(1)); // 查询C Course ccourse = (Course) session.get(Course.class, new Integer(2)); // 解除关系,以课程对象为主动方 javaCourse.getStudents().remove(student); ccourse.getStudents().remove(student); return null; } });可能会让你失望,这次操作对数据库没有任何影响。可见,分手只能是由学生对象提出来。虽然在前面课程中,咱们配置了学生类和课程类的双向多对多关联映射,但是,两者之间只能有一个主动方,这里要了解,所谓主动方,就是关系的维系者。关系的建立和解除只能由主动方提供。是不是有点像霸道总裁的狗血故事。第二种解除方案Ok!一起继续了解第 2 种方案。不管是哪种方案,切记,只能是由主动方提出分手。行事之前,一定要先检查数据是否存在。HibernateTemplate<Student> hibernateTemplate = new HibernateTemplate<Student>(); hibernateTemplate.template(new Notify<Student>() { @Override public Student action(Session session) { // Hibernate学生 Student student =(Student)session.get(Student.class, new Integer(1)); //解除关系 student.getCourses().removeAll(student.getCourses()); return null; } });和第一种方案相比较,不再查询课程信息,由学生对象单方面一次性解除关系。student.getCourses().removeAll(student.getCourses()); return null;执行结果没有什么意外,程序世界中关系的解除操作同步到了数据库中。一起看看控制台上输出的信息:Hibernate: select student0_.stuId as stuId1_1_0_, student0_.stuName as stuName2_1_0_, student0_.stuPassword as stuPassw3_1_0_, student0_.stuPic as stuPic4_1_0_, student0_.stuSex as stuSex5_1_0_ from Student student0_ where student0_.stuId=?Hibernate: select courses0_.stuId as stuId1_1_1_, courses0_.courseId as courseId2_2_1_, course1_.courseId as courseId1_0_0_, course1_.courseDesc as courseDe2_0_0_, course1_.courseName as courseNa3_0_0_ from score courses0_ inner join Course course1_ on courses0_.courseId=course1_.courseId where courses0_.stuId=?Hibernate: delete from score where stuId=?大家可以看到,Hibernate 接收到解除操作后,立即由中间表连接到课程表,把相关课程信息从中间表中抺出。一切进行得简单而有序:记住,持久化对象的行为可以同步到数据库中去;多对多双向关联映射中,有主动方和被动方一说。
hibernate表关联相关搜索
-
h1
h6
hack
hadoop
halt
hana
handler
hanging
hash
hashtable
haskell
hatch
hbase
hbuilder
hdfs
head
header
header php
headers
headerstyle