Hibernate一对多映射
Hibernate(6)—— 一对多和多对多关联关系映射(xml和注解)总结
Hibernate(6)——一对多和多对多关联关系映射(xml和注解)总结涉及的知识点总结如下:∙One to Many 映射关系o多对一单向外键关联(XML/Annotation)o一对多单向外键关联(XML/Annotation)o懒加载和积极加载o一对多双向外键关联(XML/Annotation)∙Many to Many 映射关系o多对多单向外键关联(XML/Annotation)o多对多双向外键关联(XML/Annotation)o set的inverse元素详解∙问题小结∙关联关系的优缺点多对一单向外键关联关系注意多对一关联是多方持有一方的引用。
看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示:多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。
对应数据库就是:还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现:基于注解的多对一单向外键关联:单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name="cid"),而一方(教室类)无需做任何多方的定义。
注意;多方必须保留一个不带参数的构造器!importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;//班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有@Entitypublic class ClassRoom {private intcid;//班级编号private String cname;//班级名称// 自动增长的主键@Id@GeneratedValuepublicintgetCid() {returncid;}public void setCid(intcid) {this.cid = cid;}public String getCname() {returncname;}public void setCname(String cname) {ame = cname;}}View Code一方——班级类无需做多余的定义,下面是多方——学生实体和配置:importjavax.persistence.CascadeType;importjavax.persistence.Entity;importjavax.persistence.FetchType;importjavax.persistence.GeneratedValue;importjavax.persistence.Id;importjavax.persistence.JoinColumn;importjavax.persistence.ManyToOne;//学生实体类,属于多对一的多方,持有班级(一方)的引用@Entitypublic class Students {private intsid; //编号private String sname; //姓名private ClassRoom classroom;//学生班级//注意:多方一定要显式的定义不带参数的构造方法public Students() {}public Students(String sname){this.sname = sname;}// 多方使用注解:@ManyToOne// fetch=FetchType.EAGER,急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。
hibernate一对多关联映射
hibernate一对多关联映射一对多关联映射映射原理一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。
关联关系都是由多端维护,只是在写映射时发生了变化。
多对一和一对多的区别多对一和一对多的区别在于维护的关系不同:(1)多对一:多端维护一端的关系,在加载多端时,可以将一端加载上来。
(2)一对多:一端维护多端的关系,在加载一端时,可以将多端加载上来。
分类一对多单向关联映射对象模型从对象模型中,我们可以看出,Group持有User的一个引用。
由于是单向关联,所以数据在加载Group时,会把User 加载上来,但是User并不知道Group的存在。
我们先看一下Group和User的实体,以及映射文件。
GroupUserUser.hbm.xmlGroup.hbm.xml生成的表结构和测试数据缺点1)因为多端User不知道Group的存在(也就是User不维护与Group的关系),所以在保存User时,关系字段groupId 为null,如果该字段设置为非空,则将无法保存数据。
2)因为User不维护关系,而Group维护关系,Group就会发出多余的update语句,保证Group和User有关系,这样加载Group时才把该Users对应的用户加载上来。
一对多双向关联映射对象模型双向关联映射对比单向关联映射,对象的加载方向由单向变成了双向。
我们看一下Group和User的实体,映射文件GroupUserGroup.hbm.xmlUser.hbm.xml生成的表和测试数据一对多双向关联的映射方式:1)在一的一端的集合上采用<key>标签,在多的一端加入一个外键2)在多的一端采用<many-to-one>标签注意:<key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱。
inverse属性:inverse属性可以用在一对多和多对多双向关联上,inverse属性默认为false,为false表示本端维护关系,如果inverse 为true,则本端不能维护关系,会交给另一端维护关系,本端失效。
Hibernate关联映射(多对一和一对多)
共性问题集中讲解
常见问题及解决办法 代码规范问题 调试技巧
共性问题集中讲解
映射一对一关联关系的方法:
按照外键映射 按照主键映射。
Session管理缓存的方法:
evict() clear()方法。
批量处理的方法:
通过HQL进行批量操作 通过JDBC API进行批量操作 通过Session进行批量操作。
提示:
需要搭建openSessionInView模式 按步骤配置二级缓存和查询缓存
完成时间:20分钟
共性问题集中讲解
常见问题及解决办法 代码规范问题 调试技巧
共性问题集中讲解
HQL的连接查询
和SQL查询一样,HQL也支持各种各样的连接 查询,如内连接、外连接。
连接类型 内连接 迫切内连接 左外连接 迫切左外连接 右外连接
<generator class="afosrseigignne"d>" />
</id><param name="property">resume2</param>
<p<ro/gpeenrteyrantaomr>e="resname" type="ng.String">
</<idc>olumn name="RESNAME" length="40">
<p<rocopleurmtynnnaammee==""uRseESrnCaAmRDe"NtOy"pele=n"gjathva=."l4an0"g>.String">
Hibernate一对多映射
hibernate一对多关联映射—单向一、简述一对多关联映射(one-to-many)1、在对象模型中,一对多的关联关系,使用集合表示比如Classes(班级)和Student(学生)之间是一对多的关系public class Classes{private String id;private String name;private Set students;}public class Student{public String id;public String name;}2、我们以前学过学生对班级是多对一,返过来,班级对学生就是一对多。
3、我们多对一的关系是用户和组。
返过来看,从组这边来看,就是一对多了。
下面学生的示例是班级和学生。
和用户和组是一样的。
一个班级有多个学生,这是一对多的关系;返过来,多个学生属于一个班级,这就是多对一了。
4、建立对象模型5、这两个对象模型之间是有关系的。
我们现在讲的是一对多。
一的一端是班级。
多的一端是学生。
那么怎么样能体现出这种关系呢?我们在学习多对一时,是在多的一端加上一个字段。
这个字段做为外键关联一的一端。
多对一,就是我们在看到学生的时候,能够知道这个学生是哪个班级的。
或者是当我们看到用户的时候,知道这个用户是哪个组的。
所以在用户里面持有组的引用。
6、那么一对多,就是一个组里面有多少个用户。
所以要维护这种关系,必须在组里面持有用户的集合。
班级和学生也是一样的。
一个班级有多少学生,所以在班级里面要持有相应的学生的集合。
如下图我们用Set,通常用户Set做映射。
箭头表示两者之间是有关系的。
7、上面的是对象模型,那么这种模型要映射成什么样呢?当我们定义多对一的关系时,在加载多的一端时,能够把1的一端加载上来。
因为两者之间是有关系的。
同理,一对多也是一样的,它要维护这种关系。
这种关系就是一对多。
一的一端要指向多。
在维护这种关系时,在加载一的时候,就会把一的一端加载上来。
Hibernate_关联关系(多对一和一对多)理论
关联关系
类与类之间最普遍的关系就是关联关系
单向的关联 双向的关联
6/29
多对一单向关联关系
配置从Emp到Dept的多对一单向关联
Dept持久化类 Emp持久化类
Dept.hbm.xml
Emp.hbm.xml
<clapsusbnlicamclea=s"scDn.ejbpitt.ihmibpelermnaetnetdseSmeor.ieanlitziatyb.lDEeme{ppt" table="edmeppt"">> <pidrivnaatme eB=y"tdeemedppetNpotN"oc;olumn="EDMEPTNNOO" "tytpypee=="j"ajavava.l.alanngg.I.nBteygtee"r>"> pr<igvaetneeSrattroinrgcldaespst=N"aamssei;gned"/> <p/irdiv>ate String location;
13/29
共性问题集中讲解
常见问题及解决办法 代码规范问题 调试技巧
共性问题集中讲解
14/29
学员操作——配置一对多双向关联
需求说明
配置区县到街道的双向的一对多 添加区县级联添加该区县下的两个街道 设置区县的inverse属性值为true,修改某区县, 从该区县中移走某一街道。 设置区县的<set>元素的order-by属性为:按照街 道编号倒叙排序
更新所有关联的游离状态的对象。
delete
当通过Session的delete()方法删除当前对象时,会 级联删除所有关联的对象。
Hibernate映射---多对多----将多对多拆分成两个一对多
Hibernate映射---多对多----将多对多拆分成两个一对多订单和商品的关系就是多对多,一个订单包含多个商品,一个商品可以生成多个订单.如果要想将订单和商品关联起来,还需要一张中间表,来表示二者的关联关系.那么当你需要查询某个订单下的商品时,需要关联查询三张表,这样的查询效率就比较低,所以使用时也要谨慎下面以订单和商品为例,学习多对多关联关系多对多双向关联拆分成两个一对多关联---查询订单下所有的产品Myeclipse在开发上对双向关联提供了支持.在表中设置好主键和外键关系在之前多对多双向关联中,只是一个订单对应产品数量为1,并且价格就是产品定价.那么如何实现下面的变化呢?第一:商品数量有变化,不是一个,而是10个或100个第二:商品价格的变化,早上和晚上是不一样的那么如何实现呢?在中间表中添加两个字段,分别是产品数量quantity,商品售出价格purchasePrice;下面我们来实现这个功能第一步:创建数据库.并建立好主外键关系第二步:选择三张表,生成映射文件和持久化类将多对多关联关系拆分成两个一对多关联关系.在生成映射文件和持久化类时,不要选择many-to-many实时监测选项,如下图;生成映射文件和持久化类如下图:第三步:修改Orders.java类和持久化文件,通常我们根据订单查找其下的产品,很少会根据产品查询该产品在哪个订单下.因此我们没有必要为product添加关联,修改后的文件如下:第四步:修改OrderItem.java文件和OrderItem.hbm.xml文件删除OrderItemId.java持久化类文件,然后修改OrderItem.java 文件,具体如下:第五步:编写测试类package com.entity;import java.util.Set;import org.hibernate.Session;import com.util.HibernateSessionFactory;public class HibernateTest {/*** @param args*/public static void main(String[] args) {HibernateTest hibernateTest = new HibernateTest();hibernateTest.get();}/*** 添加订单和产品*/public void add(){Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession( );session.beginTransaction();Orders order = new Orders();order.setRealname("刘备");order.setAddress("武汉");order.setPhone("999");order.setPostcode("4567");Product product1 = (Product) session.get(Product.class, 1);Product product2 = (Product) session.get(Product.class, 2);OrderItem item1 = new OrderItem(order,product1,100,195.00);OrderItem item2 = new OrderItem(order,product2,200,98.00);double total = 100*195.00+200*98.00;order.getOrderItems().add(item1);order.getOrderItems().add(item2);order.setTotal(total);session.save(order);session.beginTransaction().commit();}/*** 查询订单下的产品*/public void get(){Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession( );session.beginTransaction();Orders order = (Orders) session.get(Orders.class, 3);System.out.println(order.getRealname());System.out.println(order.getTotal());Set<OrderItem> items = order.getOrderItems();System.out.println("===================订单下的产品=======================");for(OrderItem i:items){System.out.println("产品名称:"+i.getProduct().getName());System.out.println("实际价格:"+i.getProduct().getPrice());System.out.println("购买价格:"+i.getPurchaseprice());System.out.println("购买数量:"+i.getQuantity());}session.beginTransaction().commit();}}----------------------------------------新增数据结果:。
hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了
在many一方删除数据1
• 删除“五四大道”
inverse设为true,由many一方删除 从one一方去“删除”, Hibernate只是执行了 问题出在配置文件上 update语句。还是未删 没有配置set节点的inverse属性 除成功! 根本没有执行 Delete语句,数据 没有被删除!
– 配置Hibernate多对多关联,实现某OA系统项 目和人员对照关系的管理
本章目标
• 掌握单向many-to-one关联 • 掌握双向one-to-many关联 • 掌握many-to-many关联
实体间的关联
• 单向多对一
tblJd.getQx().getQxname();
• 单向一对多
TblJd jd = (TblJd)tblQx.getJds().get(0); jd.getJdname(); tblQx.getJds.add(jd);
小结
• 在租房系统中,房屋信息(Fwxx)与用户 (User)间也是多对一关系。如何配置映 射文件,使之可以通过下面的代码输出房 屋信息和发布该信息的用户名称? Fwxx fwxx = (Fwxx)super.get(Fwxx.class,1);
System.out.println( fwxx.getTitle() + "," + fwxx.getUser.getUname());
inverse是“反转”的意思,表示关联关系的控制权。 为true,表示由对方负责关联关系的添加和删除; 执行了delete语句, 为false,表示由自己负责维护关联关系。 删除成功
• 在many一方删除数据的正确做法:
Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结
Hibernate(6)——一对多和多对多关联关系映射(xml和注解)总结涉及的知识点总结如下:∙One to Many 映射关系o多对一单向外键关联(XML/Annotation)o一对多单向外键关联(XML/Annotation)o懒加载和积极加载o一对多双向外键关联(XML/Annotation)∙Many to Many 映射关系o多对多单向外键关联(XML/Annotation)o多对多双向外键关联(XML/Annotation)o set的inverse元素详解∙问题小结∙关联关系的优缺点多对一单向外键关联关系注意多对一关联是多方持有一方的引用。
看一个例子,去淘宝购物,那么一个淘宝用户可以对应多个购物订单,如图所示:多的一方是Orders,持有一方的引用,也就是Users,而在Users中无需作任何定义,从订单到用户的关系是单向多对一关联。
对应数据库就是:还有比如说学生和班级的关系,多个学生可以属于同一个班级,这就是从学生到班级也是典型的单向多对一关系,看代码实现:基于注解的多对一单向外键关联:单向多对一关联中,多方需要持有一方的引用,那么多方(学生类)需要额外配置,需要对持有的一方引用使用注解@ManyToOne (cascade={CascadeType.ALL}, fetch=FetchType.EAGER),设置为级联操作和饥渴的抓取策略,@JoinColumn(name="cid"),而一方(教室类)无需做任何多方的定义。
注意;多方必须保留一个不带参数的构造器!import ;import ;import ;//班级类,在多对一关系中属于一的方,不持有其他多余的配置,反而是被多方持有public class ClassRoom {private int cid;//班级编号private String cname;//班级名称// 自动增长的主键@Id@GeneratedValuepublic int getCid() {return cid;}public void setCid(int cid) {this.cid = cid;}public String getCname() {return cname;}public void setCname(String cname) {ame = cname;}}View Code一方——班级类无需做多余的定义,下面是多方——学生实体和配置:import ;import ;import ;import ;import ;import ;import ;//学生实体类,属于多对一的多方,持有班级(一方)的引用@Entitypublic class Students {private int sid; //编号private String sname; //姓名private ClassRoom classroom;//学生班级//注意:多方一定要显式的定义不带参数的构造方法public Students() {public Students(String sname){this.sname = sname;}// 多方使用注解:@ManyToOne// fetch=FetchType.EAGER,急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。
Hibernate注解(一对一、一对多、多对多)
Hibernate注解(⼀对⼀、⼀对多、多对多)JPA(Java Persistence API)通过注解或XML描述对象与关系表的映射关系,并将运⾏期的实体对象持久化到数据库中。
JPA是⼀个规范,是⼀个标准,Hibernate是实现了这个标准的开源框架。
1、引⼊hibernate-jpa-2.0-api-1.0.0.Final.jar JPA规范对应的hibernate的jar包2、修改配置⽂件hibernate.cfg.xml 的映射关系<Mapping class=""><?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-configurationPUBLIC "-//Hibernate/Hibernate Configuration DTD//EN""/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- thread:⼀个线程中使⽤⼀个。
获取session会话时使⽤--><property name="current_session_context_class">thread</property><!-- 是否显⽰SQL语句,值为布尔型,默认false --><property name="hibernate.show_sql">true</property><!-- 是否格式化显⽰sql语句,让显⽰更美观,值为布尔型,默认false --><property name="hibernate.format_sql">false </property><!-- ⾃动建表update:每次执⾏时,⽆表则建表,⽆列则建列,只增不减create:每次启动的时候,删除原表,再次创建create-drop:每次启动时创建新表,当显式关闭sessionFactory时,删除表--><property name="hibernate.hbm2ddl.auto">update</property><!-- 连接数据库 --><property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/zxd_db</property><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><property name="ername">zxd</property><property name="hibernate.connection.password">123456</property><property name="dialect">org.hibernate.dialect.MySQLDialect</property><!-- 读取注解 --><mapping class="demo.entity.Book"/></session-factory></hibernate-configuration>3、实体配置package demo.entity;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import org.hibernate.annotations.GenericGenerator;/*** 注解实体配置* JPA通过注解或XML描述对象与关系表的映射关系,并将运⾏期的实体对象持久化到数据库中。
一对多关联映射学习总结——hibernate
一对多关联映射(one-to-many单向)一、对象模型在对象模型中一对多关联映射,通常在一的一端要使用集合来表示关联关系。
比如班级-->学生就是一个典型的一对多的关系。
说明:之所以在一的一端需要持有对多的一端集合引用,是为了方便在加载班级的时候同时加载对应班级下面的学生。
二、原理【实现原理】先有班级[one]后有学生[many],实现一对多需要在多的一端建立外键指向一的端one-to-many单向:就是能从Cleasses中访问到对应的学生,反之无效.三、面试题【面试题】多对一与一对多的区别与联系?一对多关联映射利用了多对一关联映射原理多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一(Person---Group)一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多(Classes---Students)总结:也就是说一对多和多对一的映射策略是一样的,只是角度不同四、业务模型(实体类)ClassesPOJO.javaprivate int id;private String name;private Set students;//一指向多StudentPOJO.javaprivate int id;private String name;五、配置文件(1)一的一端(Classes.hbm.xml)的配置:需要加入<set>标签<set name="students(Classes实体类中Set接口类型的变量名)"><key column="classid(对应于多的一端在数据库中的外键)"/><one-to-many class="多的一端实体类的路径"></set><hibernate-mapping package="com.tarena.hibernate"><class name="Classes"table="t_classes"><id name="id"><generator class="native"/></id><property name="name"/><set name="students"><key column="classesid"/><one-to-many class="Student"/></set></class></hibernate-mapping>(2)多的一端(Student.hbm.xml)的配置:<hibernate-mapping><class name="com.bjsxt.tarena.Student"table="t_student"><id name="id"><generator class="native"/>//ID自动增长</id><property name="name"/></class></hibernate-mapping>六、代码测试(1)save操作()存储策略:因为在Classes实体类(One)中存在一个对Student实体类的Set集合引用,所以要先存Student 对象,然后在为Student分配班级。
Java程序员从笨鸟到菜鸟之(五十四)细谈Hibernate(五)Hibernate一对多关系映射
Java程序员从笨鸟到菜鸟之(五十四)细谈Hibernate(五)Hibernate一对多关系映射前几篇系列博客:细谈Hibernate(一)hibernate基本概念和体系结构细谈Hibernate(二)开发第一个hibernate基本详解细谈Hibernate(三)Hibernate常用API详解及源码分析细谈Hibernate(四)Hibernate常用配置文件详解在前几篇博客,我们初步对Hibernate有了一定的基础性的认知了,也能够简单的用hibernate进行增删改查,但hibernate真正的难度和精髓我们都还没接触到,其中最主要的关联映射就是其中一个,这篇博客,我们就一起来看一下这个hibernate关联映射。
我们大家都知道,在域模型(实体域)中,关联关系是类与类之间最普遍的关系,他是指通过一个对象持有另一个对象的实例根据UML语言,关系是有方向的。
实质上关联映射的本质:将关联关系映射到数据库,所谓的关联关系是对象模型在内存中的一个或多个引用。
搞清关联映射的的关键就在于搞清实体之间的关系。
下面我们首先来看一下具体什么事关联关系:一:关联关系1.关联关系的方向可分为单向关联和双向关联。
单向关联:假设存在两张表person表和address表,如果在应用的业务逻辑中,仅需要每个person实例能够查询得到其对应的Address实例,而Address实例并不需要查询得到其对应的person 实例;或者反之。
双向关联:既需要每个person实例能够查询得到其对应的Address实例,Address实例也需要查询得到其对应的person实例。
2.关联的数量,根据拥有被关联对象的个数确定多对一(many to one):如用户和组学生和班级一对多(one to many):如用户和电子邮件多对多(many to many):如学生选课一对一(one to one):如用户和身份证下面我们就开始讲第一种关联关系:一对多,一对多总共分为:单向一对多,单向多对一,双向一对多。
hibernate关联映射详解
hibernate关联映射详解一对多关系 1.一对多关系(单向):在一端映射文件中加入:name= student keyumn= classes / one-to-many > /set 2.一对多关系(双向):(1).在一端映射文件中加入: setname= student keycolumn= classesid / one-to-many > /set (2).在多的一端加入: many-to-onename= classes column=classesid /many-to-one 多对一关系在多的一端加入:many-to-one name= classes column= classesid / 一对一关系 1. 一对一外键关联单向:(它其实就是一个多对一映射的一个特例,只是设置ue=”ue”)在维护关系一端的映射文件中加入:many-to-onename= card unique= true cascade= all /many-to-one 双向:在维护关系一端的映射文件中加入: many-to-onename= card unique= true cascade= all /many-to-one 在另一段的映射文件中加入: one-to-onename= users property-ref= card /one-to-one 因为 one-to-one name 标签默认是找关联主键,所以在这里需要property-ref= card 配置关联属性。
Cascade属性是级联的意思。
2. 一对一主键关联 a) 单向在维持关系一端的代码: classname= er_pk idname= id generator > paramname= property card_pk /param /generator /id propertyname= name unique= true /property one-to-onename= card_pk constrain= true /one-to-one /class 设置generator > constrained= true 设置该实体的主键是card_p的外键。
Hibernate一对多、一对一、多对多映射
一、一对多/多对一1.确定谁是一方,谁是多方。
某表的主键在另一表中为外键,则某表为一方。
如学生和班级的对应关系,一个班级对应多个学生,所以班级为一方,学生为多方。
2.一方和多方po中部分代码的书写ClassInfo一方:set<多方类型> 的属性代码如:private Set<Student> stuSet;Student多方:一方类型的属性注意:不写外键字段。
代码如:private ClassInfo classInfo;3、配置ClassInfo一方:<set name="student" > 子元素:<key column="哪个字段是别人的外键(class_id)" /> <one-to-many class=”Student”></set>Student多方:<many-to-one name="classInfo" class="ClassInfo"column="class_id" >4、测试添加记录时的dao一部分代码ClassInfo c=new ClassInfo();c.setCname("aaa");Student s=new Student();s.setStuName("gsc");s.setAge(12);s.setEmail("gsc@");Set<Student> stuSet=new HashSet<Student>();stuSet.add(s);c.setStuSet(stuSet);Session session = HibUtil.getSession();Transaction tx = session.beginTransaction();session.save(c);mit();session.close();二一对一1.外键关联:一对多的基础上在外键字段上加个唯一约束构成1对1的关系。
Hibernate用注解方式实现一对多、多对多关系
Hibernate⽤注解⽅式实现⼀对多、多对多关系⼀、⼀对多关系 1、在上⼀篇⽇志中⽤.xml配置⽂件项⽬基础上,再往lib⽬录先添加⼀个包-hibernate-jpa-2.0-api-1.0.0.Final.jar 2、新建⼀个com.st.bean4 包,往包⾥⾯添加两个含有注解的类: a)、DeptBean2类:1 package com.st.bean4;23 import java.util.HashSet;4 import java.util.Set;567 import javax.persistence.Column;8 import javax.persistence.Entity;9 import javax.persistence.GeneratedValue;10 import javax.persistence.Id;11 import javax.persistence.JoinColumn;12 import javax.persistence.OneToMany;13 import javax.persistence.Table;1415 import org.hibernate.annotations.Cascade;16 import org.hibernate.annotations.CascadeType;17 import org.hibernate.annotations.GenericGenerator;1819 @Entity //指定实体类20 @Table(name="DEPT") //对应表的名称21 @GenericGenerator(name="genID", strategy="increment") //声明主键⽣成策略22 public class DeptBean2 {23 @Id //指定主键24 @GeneratedValue(generator="genID") //设定主键⽣成策略25 @Column(name="ID") //指定类中的属性与表中的列的对应关系26 private long id;27 @Column(name="NAME") //指定类中的属性与表中的列的对应关系28 private String name;2930 @OneToMany //指定⼀对多关系31 @Cascade(value={CascadeType.SAVE_UPDATE}) //设定级联关系32 @JoinColumn(name="dept_id") //指定与本类主键所对应的外表的外键33 private Set<EmployeeBean2> emp = new HashSet<EmployeeBean2>();34 @Override35 public String toString() {36 return "DeptBean [id=" + id + ", name=" + name +"]";37 }38 public long getId() {39 return id;40 }41 public void setId(long id) {42 this.id = id;43 }44 public String getName() {45 return name;46 }47 public void setName(String name) {48 = name;49 }50 public Set<EmployeeBean2> getEmp() {51 return emp;52 }53 public void setEmp(Set<EmployeeBean2> emp) {54 this.emp = emp;55 }56 } b)、EmployeeBean类:1 package com.st.bean4;23 import javax.persistence.Column;4 import javax.persistence.Entity;5 import javax.persistence.GeneratedValue;6 import javax.persistence.Id;7 import javax.persistence.JoinColumn;8 import javax.persistence.ManyToOne;9 import javax.persistence.Table;11 import org.hibernate.annotations.GenericGenerator;1213 @Entity //指定⼀个实体14 @Table(name="employee") //指定表的名称15 @GenericGenerator(name="genID", strategy="increment") //声明主键⽣成策略16 public class EmployeeBean2 {17 @Id //指定主键18 @GeneratedValue(generator="genID") //设定主键⽣成策略19 @Column(name="ID") //类中的属性和表中的列名的对应关系20 private long id;21 @Column(name="NAME")22 private String name;23 @Column(name="SEX")24 private String sex;25 @Column(name="JOB")26 private String job;27 @ManyToOne// 指定多对⼀关系 //指定多对⼀关系28 @JoinColumn(name="DEPT_ID")29 //⼀个员⼯对应于⼀个部门号,所以这⾥不⽤集合30 private DeptBean2 dept ; //注意这个地⽅不要new对象,否则会⽆法运⾏31 public long getId() {32 return id;33 }34 public void setId(long id) {35 this.id = id;36 }37 public String getName() {38 return name;39 }40 public void setName(String name) {41 = name;42 }43 public String getSex() {44 return sex;45 }46 public void setSex(String sex) {47 this.sex = sex;48 }49 public String getJob() {50 return job;51 }52 public void setJob(String job) {53 this.job = job;54 }55 public DeptBean2 getDept() {56 return dept;57 }58 public void setDept(DeptBean2 dept) {59 this.dept = dept;60 }61 @Override62 public String toString() {63 return "EmployeeBean [id=" + id + ", name=" + name + ", sex=" + sex64 + ", job=" + job + ", dept=" + dept65 + "]";66 }67 } 3、在hibernate.cfg.xml⽂件中引⼊上⾯两个类的映射1 <mapping class="erBean2" />2 <mapping class="com.st.bean5.RoleBean2" /> 4、在BeanTest中添加相应的测试⽅法:1 @Test2 public void bean4test1(){3 Session session = HibernateTools.openSession();4 Transaction tran = session.beginTransaction();5 //⾸先在dept中新增⼀条数据,再关联的在employee中新增⼀条数据6 //DeptBean2 dept = new DeptBean2();7 //先读去dept中的数据,再在读取的基础上关联的在employee中新增⼀条数据8 DeptBean2 dept = (DeptBean2) session.get(DeptBean2.class,1L); //1L代表主键9 EmployeeBean2 emp = new EmployeeBean2();10 //dept.setName("技术部");11 emp.setName("陈泽俊");12 emp.setSex("男");13 emp.setJob("STM32");14 dept.getEmp().add(emp);15 session.save(dept);16 //确认提交事物17 mit();⼆、多对多关系 1、新建⼀个com.st.bean4 包,往包⾥⾯添加两个含有注解的类 a)、UserBean2:1 package com.st.bean5;2 import java.util.HashSet;3 import java.util.Set;45 import javax.persistence.Column;6 import javax.persistence.Entity;7 import javax.persistence.GeneratedValue;8 import javax.persistence.Id;9 import javax.persistence.JoinColumn;10 import javax.persistence.JoinTable;11 import javax.persistence.ManyToMany;12 import javax.persistence.Table;1314 import org.hibernate.annotations.Cascade;15 import org.hibernate.annotations.CascadeType;16 import org.hibernate.annotations.GenericGenerator;1718 @Entity //实体19 @Table(name="T_USER") //表名20 @GenericGenerator(name="genID", strategy="increment") //声明主键⽣成策略21 public class UserBean2 {22 @Id //指定主键23 @GeneratedValue(generator="genID") //设定主键⽣成策略24 @Column(name="ID") //指定类的属性和表的字段的对应关系25 private long id;26 @Column(name="NAME")27 private String name;28 @Column(name="SEX")29 private String sex;30 @ManyToMany //指定多对多关系31 @Cascade(value={CascadeType.SAVE_UPDATE}) //设置级联关系32 @JoinTable(name="USER_ROLE", //指定第三张表33 joinColumns={@JoinColumn(name="USER_ID")}, //本表与中间表的外键对应34 inverseJoinColumns={@JoinColumn(name="ROLE_ID")}) //另⼀张表与第三张表的外键的对应关系35 private Set<RoleBean2> role = new HashSet<RoleBean2>();36 public long getId() {37 return id;38 }39 public void setId(long id) {40 this.id = id;41 }42 public String getName() {43 return name;44 }45 public void setName(String name) {46 = name;47 }48 public String getSex() {49 return sex;50 }51 public void setSex(String sex) {52 this.sex = sex;53 }54 public Set<RoleBean2> getRole() {55 return role;56 }57 public void setRole(Set<RoleBean2> role) {58 this.role = role;59 }60 @Override61 public String toString() {62 return "UserBean [id=" + id + ", name=" + name + ", sex=" + sex63 + ", role=" + role + "]";64 }65 } b)、RoleBean类:1 package com.st.bean5;2 import java.util.HashSet;34 import java.util.Set;56 import javax.persistence.Column;7 import javax.persistence.Entity;8 import javax.persistence.GeneratedValue;9 import javax.persistence.Id;10 import javax.persistence.JoinColumn;11 import javax.persistence.JoinTable;12 import javax.persistence.ManyToMany;13 import javax.persistence.Table;1415 import org.hibernate.annotations.Cascade;16 import org.hibernate.annotations.CascadeType;17 import org.hibernate.annotations.GenericGenerator;1819 @Entity //实体20 @Table(name="T_ROLE") //表名21 @GenericGenerator(name="genID", strategy="increment")//声明主键⽣成策略22 public class RoleBean2 {23 @Id //主键24 @GeneratedValue(generator="genID") //设置主键⽣成策略25 @Column(name="ID") //类中的属性与表的字段的对应关系26 private long id;27 @Column(name="POST")28 private String post;//职位29 @Column(name="PAY")30 private int pay; //薪资31 @ManyToMany //多对多关系32 @Cascade(value={CascadeType.SAVE_UPDATE}) //级联关系33 @JoinTable(name="USER_ROLE", //中间表的名称34 joinColumns={@JoinColumn(name="ROLE_ID")}, //本表与中间表的外键对应关系35 inverseJoinColumns={@JoinColumn(name="USER_ID")}) //另⼀张表与中间表的外键的对应关系36 private Set<UserBean2> user = new HashSet<UserBean2>();3738 public long getId() {39 return id;40 }41 public void setId(long id) {42 this.id = id;43 }44 public String getPost() {45 return post;46 }47 public void setPost(String post) {48 this.post = post;49 }50 public int getPay() {51 return pay;52 }53 public void setPay(int pay) {54 this.pay = pay;55 }56 public Set<UserBean2> getUser() {57 return user;58 }59 public void setUser(Set<UserBean2> user) {60 er = user;61 }62 @Override63 public String toString() {64 return "RoleBean [id=" + id + ", post=" + post + ", pay=" + pay + "]";65 }66 } 2、在hibernate.cfg.xml中引⼊UserBean2和RoleBean2这两个类的映射:1 <mapping class="erBean2" />2 <mapping class="com.st.bean5.RoleBean2" /> 3、在BeanTest类中添加测试⽅法:1 @Test2 public void bean5test1(){3 // 获取⼀个会话4 Session session = HibernateTools.openSession();5 //开启⼀次事物6 Transaction tran = session.beginTransaction();7 UserBean2 user = new UserBean2();8 // RoleBean2 role = (RoleBean2) session.get(RoleBean2.class,1L);9 RoleBean2 role = new RoleBean2();1011 user.setName("汪⽂仕");12 user.setSex("男");1314 role.setPost("博⼠");15 role.setPay(10000);1617 role.getUser().add(user);18 session.save(role);19 //确认提交事物20 mit();21 }22 @Test23 public void bean5test2(){24 // 获取⼀个会话25 Session session = HibernateTools.openSession();26 /* List<UserBean> list = session.createCriteria(UserBean.class).list();27 for(UserBean user : list)28 System.out.println(user);*/29 String hql = "select new Map( as name,u.sex as sex,r.post as post,r.pay as pay) from UserBean2 u join u.role r";30 List<Map<String,Object>> list = session.createQuery(hql).list();31 for(Map<String,Object> data : list)32 System.out.println(data);33 }三、注意: 1、引⼊了注解需要的jar包后要先删除Java EE 5 Library这个库,否则会两个jar包中的类产⽣冲突 2、在多表操作时最好设置级联关系,不然对表操作时要先读取⼀个类的数据,再将新建的⼀个类的数据添加到这个类上才成功对三张表同时操作。
Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结
Hibernate(V)——一对多与多对多关联关系映射(xml与注解)总结引言简要介绍Hibernate框架以及关联关系映射在数据库设计中的重要性。
Hibernate关联关系映射概述关联关系的重要性讨论在现实世界中对象间关系的重要性以及如何在数据库中表示这些关系。
Hibernate关联关系类型列举Hibernate支持的关联关系类型,包括一对一、一对多、多对一和多对多。
一对多关联关系映射概念解释解释一对多关联关系的概念,例如一个部门拥有多个员工。
XML映射方式详细描述如何在XML映射文件中配置一对多关联关系。
实体类定义展示一对多关系中实体类的Java代码示例。
XML映射文件提供一对多关系映射的XML配置示例。
注解映射方式详细描述如何使用注解配置一对多关联关系。
实体类定义展示使用注解的一对多关系中实体类的Java代码示例。
注解配置提供一对多关系映射的注解配置示例。
多对多关联关系映射概念解释解释多对多关联关系的概念,例如学生和课程之间的关联。
XML映射方式详细描述如何在XML映射文件中配置多对多关联关系。
实体类定义展示多对多关系中实体类的Java代码示例。
XML映射文件提供多对多关系映射的XML配置示例。
注解映射方式详细描述如何使用注解配置多对多关联关系。
实体类定义展示使用注解的多对多关系中实体类的Java代码示例。
注解配置提供多对多关系映射的注解配置示例。
关联关系映射的高级特性级联操作讨论级联保存、更新和删除的概念及其配置。
双向关系管理解释如何管理双向关联关系,确保数据的一致性。
延迟加载与即时加载讨论延迟加载和即时加载的概念及其在关联关系中的应用。
实践案例分析一对多关联关系案例通过一个具体的一对多关联关系案例,展示映射配置和数据操作。
多对多关联关系案例通过一个具体的多对多关联关系案例,展示映射配置和数据操作。
常见问题与解决方案一对多关联关系常见问题列举一对多关联关系映射中可能遇到的问题及其解决方案。
黑马程序员hibernate框架开发教程第三天:(2)Hibernate的一对多操作
Hibernate的一对多操作(重点)一对多映射配置(重点)以客户和联系人为例:客户是一,联系人是多第一步创建两个实体类,客户和联系人第二步让两个实体类之间互相表示(1)在客户实体类里面表示多个联系人- 一个客户里面有多个联系人(2)在联系人实体类里面表示所属客户- 一个联系人只能属于一个客户第三步配置映射关系(1)一般一个实体类对应一个映射文件(2)把映射最基本配置完成(3)在映射文件中,配置一对多关系- 在客户映射文件中,表示所有联系人- 在联系人映射文件中,表示所属客户第四步创建核心配置文件,把映射文件引入到核心配置文件中测试:一对多级联操作级联操作1 级联保存(1)添加一个客户,为这个客户添加多个联系人2 级联删除(1)删除某一个客户,这个客户里面的所有的联系人也删除一对多级联保存1 添加客户,为这个客户添加一个联系人(1)复杂写法://演示一对多级联保存@Testpublicvoid testAddDemo1() {SessionFactory sessionFactory = null;Session session = null;Transaction tx = null;try {//得到sessionFactorysessionFactory = HibernateUtils.getSessionFactory();//得到sessionsession = sessionFactory.openSession();//开启事务tx = session.beginTransaction();// 添加一个客户,为这个客户添加一个联系人//1 创建客户和联系人对象Customer customer = new Customer();customer.setCustName("传智播客");customer.setCustLevel("vip");customer.setCustSource("网络");customer.setCustPhone("110");customer.setCustMobile("999");LinkMan linkman = new LinkMan();linkman.setLkm_name("lucy");linkman.setLkm_gender("男");linkman.setLkm_phone("911");//2 在客户表示所有联系人,在联系人表示客户// 建立客户对象和联系人对象关系//2.1 把联系人对象放到客户对象的set集合里面customer.getSetLinkMan().add(linkman);//2.2 把客户对象放到联系人里面linkman.setCustomer(customer);//3 保存到数据库session.save(customer);session.save(linkman);//提交事务mit();}catch(Exception e) {tx.rollback();}finally {session.close();//sessionFactory不需要关闭sessionFactory.close();}}(2)简化写法- 一般根据客户添加联系人第一步在客户映射文件中进行配置- 在客户映射文件里面set标签进行配置第二步创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存客户就可以了//演示一对多级联保存@Testpublicvoid testAddDemo2() {SessionFactory sessionFactory = null;Session session = null;Transaction tx = null;try {//得到sessionFactorysessionFactory = HibernateUtils.getSessionFactory();//得到sessionsession = sessionFactory.openSession();//开启事务tx = session.beginTransaction();// 添加一个客户,为这个客户添加一个联系人//1 创建客户和联系人对象Customer customer = new Customer();customer.setCustName("百度");customer.setCustLevel("普通客户");customer.setCustSource("网络");customer.setCustPhone("110");customer.setCustMobile("999");LinkMan linkman = new LinkMan();linkman.setLkm_name("小宏");linkman.setLkm_gender("男");linkman.setLkm_phone("911");//2 把联系人放到客户里面customer.getSetLinkMan().add(linkman);//3 保存客户session.save(customer);//提交事务mit();}catch(Exception e) {tx.rollback();}finally {session.close();//sessionFactory不需要关闭sessionFactory.close();}}一对多级联删除1 删除某个客户,把客户里面所有的联系人删除2 具体实现第一步在客户映射文件set标签,进行配置(1)使用属性cascade属性值 delete第二步在代码中直接删除客户(1)根据id查询对象,调用session里面delete方法删除3 执行过程:(1)根据id查询客户(2)根据外键id值查询联系人(3)把联系人外键设置为null(4)删除联系人和客户一对多修改操作(inverse属性)1 让lucy联系人所属客户不是传智播客,而是百度2 inverse属性(1)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题(2)解决方式:让其中的一方不维护外键- 一对多里面,让其中一方放弃外键维护- 一个国家有总统,国家有很多人,总统不能认识国家所有人,国家所有人可以认识总统(3)具体实现:在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
<!--接下来,采用one-to-many这个标签,采用这个标签,一方面是一对多,
另一方面,要用class这个属性来指定Classes.java类中的students这个集合里面
到底是什么元素。我们这个实例里面是Student对象集合。
一定要指定集合中的元素是什么类型的对象。-->
<hibernate-mapping>
<class name="com.bjsxt.hibernate.Student" table="t_student">
<id name="id">
<!--主键的生成方式不能是uuid。因为这种生成方式是生成32位16进制的字符串
而我们的实体类中id的类型为int.所以要修改主键的生成方式为native.就是以数字形式自增-->
<class name="Classes" table="t_classes">
<id name="d">
<generator class="native"></generator>
</id>
<property name="name"/>
<!--上面为简单属性
下面要看一下集合要如何映射
答:集合要用set标签来映射
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
}
四、对象模型建立好之后,就开始写映射文件,这是hibernate开发的正确思路。
1、在写映射文件时,先从简单的写起。
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
一个班级有多个学生,这是一对多的关系;返过来,多个学生属于一个班级,这就是多对一了。
4、建立对象模型
5、这两个对象模型之间是有关系的。我们现在讲的是一对多。一的一端是班级。多的一端是学生。那么怎么样能体现出这种关系呢?
我们在学习多对一时,是在多的一端加上一个字段。这个字段做为外键关联一的一端。多对一,就是我们在看到学生的时候,能够知道这个学生是哪个班级的。或者是当我们看到用户的时候,知道这个用户是哪个组的。所以在用户里面持有组的引用。
</session-factory>
</hibernate-configuration>
六、打MySql,创建数据库
这样就可以把classid加到表t_student里面,而且做为外键指向t_classes表的主键id. -->
</set>
</class>
</hibernate-mapping>
五、到hibernate.cfg.xml文件中,修改数据库,并把我们的两个实体类加到配置文件中
文件内容为:
<!DOCTYPE hibernate-configuration PUBLIC
所以要把这个字段加过来,加过来之后,还要做为外键指向t_classes这张表的主键
我们用key标签来实现-->
<!--在key标签里面要使用的属性是列,就是给定在t_student表中的加上的列的名字。
加了key这个标签后,就会把classid这个字段加入到t_student这张表里面了,
它做为外键指向t_class表的id字段。-->
6、那么一对多,就是一个组里面有多少个用户。所以要维护这种关系,必须在组里面持有用户的集合。
班级和学生也是一样的。一个班级有多少学生,所以在班级里面要持有相应的学生的集合。
如下图
我们用Set,通常用户Set做映射。
箭头表示两者之间是有关系的。
7、上面的是对象模型,那么这种模型要映射成什么样呢?
当我们定义多对一的关系时,在加载多的一端时,能够把1的一端加载上来。因为两者之间是有关系的。
<!--数据库改成hibernate_session -->
<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_one2many_1</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<generator class="native"></generator>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
2、再映射难一点的,Classes.hbm.xml文件如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bjsxt.hibernate">
写Students.hmb.xml文件。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"/hibernate-mapping-3.0.dtd">
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory >
我的理解:对于要相关联的表来说,如果一个表想要看到对方的表内容,则就要在自己的实体类中持有对方的引用。
如果只有一方看到另一方,就是单向的。
如果要双方都看到,就要在实体模型中彼此都持有对方的引用。
二、新建项目hibernate_one2many_1(拷贝hibernate_session)这个项目就O了。:我们这个实例还是单向的。只能在加载班级时,把所有的学生加载上来。但是当把学生拿上来的时候,看不到这个学生所在的班级。
<property name="ername">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
所以要用Set接口。因为hibernate对Set有相应的实现,对Set进行了扩展。
2、我们的Set里面就是Student对象的集合。这样就构成了一对多的关系。
2.1 Classes.java
package com.bjsxt.hibernate;
import java.util.Set;
public class Classes {
同理,一对多也是一样的,它要维护这种关系。这种关系就是一对多。一的一端要指向多。
在维护这种关系时,在加载一的时候,就会把一的一端加载上来。
也就是说,在我在加载班级时,这个班级有多少个学生,它会把所有的学生自动查询上来,放到Set集合里面。这就是维护这个关系的目的。
8、我们知道,实体类要映射成表。所在下面画两个表。
}
}
2.2Student.java
package com.bjsxt.hibernate;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
hibernate一对多关联映射—单向
一、简述
一对多关联映射(one-to-many)
1、在对象模型中,一对多的关联关系,使用集合表示
比如Classes(班级)和Student(学生)之间是一对多的关系
public class Classes{