Nhibernate一对多级联保存_双向映射
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_关联关系(多对一和一对多)理论
关联关系
类与类之间最普遍的关系就是关联关系
单向的关联 双向的关联
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核心,一对多,多对多映射讲解,看了就完全搞明白了
在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中双向关联在级联情况下save对象讨论
hibernate中双向关联在级联情况下save对象讨论一般在双向关联的情况下,都要在一方设置mappedBy(name="xxx"),由对方主导映射关系。
在多对一的情况下,一般在多的一方设置主导映射的关系(为了方便叙述,就这么叫它了,呵呵)。
所谓主导这种映射关系,如group,user,就是由多的一方(user)里面产生一个外键参考一的一方(group)的主键,这时候user就是主导的一方,写mappedBy是被主导的一方。
在多对多的情况下,随便由那方主导,在数据库表的结构上都是一样的,都会产生一个中间表,中间表有两个字段的联合主键,分别作为外键参考两个多的一方。
在一对多和多对多的双向关联的情况下,并且在cascade=CascadeType.ALL情况下,save 不同方面(如主导关系一方或被主导的一方)在级联的具体表现上是不同的。
分别来讨论一下。
先看一对多的双向关联关系,这里就拿group和user举例。
Group类如下:[java]view plain copy1.package com.chen.hibernate.ormapping;2.3.import java.util.HashSet;4.import java.util.Set;5.6.import javax.persistence.CascadeType;7.import javax.persistence.Entity;8.import javax.persistence.FetchType;9.import javax.persistence.GeneratedValue;10.import javax.persistence.Id;11.import javax.persistence.OneToMany;12.import javax.persistence.Table;13.14.@Entity15.@Table(name = "t_group")16.public class Group {17.private int id;18.private String name;19.private Set<User> users = new HashSet<User>();20.21.@Id22.@GeneratedValue23.public int getId() {24.return id;25. }26.27.public void setId(int id) {28.this.id = id;29. }30.31.public String getName() {32.return name;33. }34.35.public void setName(String name) { = name;37. }38.39.// 设置mappedBy是被主导的一方40.@OneToMany(mappedBy = "group", cascade = { CascadeType.ALL }, fetch = FeZY)41.public Set<User> getUsers() {42.return users;43. }44.45.public void setUsers(Set<User> users) {ers = users;47. }48.}User类如下:[java]view plain copy1.package com.chen.hibernate.ormapping;2.3.import javax.persistence.CascadeType;4.import javax.persistence.Entity;5.import javax.persistence.FetchType;6.import javax.persistence.GeneratedValue;7.import javax.persistence.Id;8.import javax.persistence.JoinColumn;9.import javax.persistence.ManyToOne;10.import javax.persistence.Table;11.12.@Entity13.@Table(name = "t_user")14.public class User {15.private int id;16.private String name;17.private Group group;18.19.@Id20.@GeneratedValue21.public int getId() {22.return id;23. }24.25.public void setId(int id) {26.this.id = id;27. }28.29.public String getName() {30.return name;31. }32.33.public void setName(String name) { = name;35. }36.37.//设置fetch为lazy,多的一方默认问eager38.@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)39.@JoinColumn(name = "groupId")40.public Group getGroup() {41.return group;42. }43.44.public void setGroup(Group group) {45.this.group = group;46. }47.}junit测试类[java]view plain copy1.package com.chen.hibernate.ormapping;2.3.import org.hibernate.Session;4.import org.hibernate.SessionFactory;5.import org.hibernate.cfg.AnnotationConfiguration;6.import org.hibernate.tool.hbm2ddl.SchemaExport;7.import org.junit.AfterClass;8.import org.junit.BeforeClass;9.import org.junit.Test;10.11.public class CRUDTest {12.private static SessionFactory sessionFactory = null;13.14.@BeforeClass15.public static void beforeClass() {16.new SchemaExport(new AnnotationConfiguration().configure()).create(17.false, true);18. sessionFactory = new AnnotationConfiguration().configure()19. .buildSessionFactory();20. }21.22.@Test23.public void testSaveUser() {24. User user = new User();25. user.setName("u1");26. Group group = new Group();27. group.setName("g1");28.29.// 这里仅仅把group加到user中,而不需要group.getUsers().add(user);把当前的对象加入到group的set里30. user.setGroup(group);31.32. Session session = sessionFactory.getCurrentSession();33. session.beginTransaction();34. session.save(user);35. session.getTransaction().commit();36. }37.38.// 再看看save被主导的一方会如何。
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知识点总结
日期作业: 2011年12月8日Hibernate课堂讲课知识点总结:一.hibernate基础知识二.hibernate一对一映射三.hibernate一对多(多对一)映射四.hibernate多对多映射五.hibernate的HQL检索学习一.Hibernate基础知识1.hibernate:hibernate就是一个可以自动的根据xml或annotation完成对象关系映射(orm),并持久化到数据库的开源框架。
是连接java应用程序和关系数据库的中间件,这是对JDBC的封装,主要负责java对象的持久化。
2.ORM(Object Relation Mapping)对象关系映射是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
3.hibernate映射文件:它的作用是描述持久层对象以及让他们的属性和数据库中的表和表的字段之间的对应关系。
没有映射文件,Hibernate系统无法完成Java对象和数据库表中的数据的相互转化。
只有通过映射文件,Hibernate才能知道所操作的对象与哪个表相关联。
4.hibernate.cfg.xml文件中包含了hibernate与数据库的基本连接信息。
在Hibernate工作的初始阶段,由Configuration的对象开启hibernate框架,然后将信息加载到SessionFactory实例中。
5.SessionFactory是Hibernate中的一个类,这个类主要负责保存Hibernate的配置信息,以及对Session的操作。
6.手动创建hibernate框架的步骤:a)拷贝所需Jar包到lib目录下,基本包含(antlr.jar,cglib.jsr,asm.jar,commons-collections.jar,commons-logging.jar,jta.jar,dom4j.jar,hibernate3.jar,hibernate-annotations.jar)b)在src目录下创建一个hibernate.cfg.xml文件,该文件包含了hibernate与数据库连接的基本连接信息。
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的关系。
【转】NHibernate入门教程
【转】NHibernate⼊门教程摘要: 热衷于开源框架探索的我发现 MVC与jQuery easyUI的组合很给⼒。
由于原先⼀直受Ext JS框架的licence所苦恼,于是痛下决⼼寻找⼀个完全免费的js框架——easyUI。
它有完整的demo和强⼤AIP⼿册,使我在开发过程中得⼼应⼿。
以下是这篇博⽂Demo程序的演⽰效果: 解决⽅案如图1所⽰图1 Domain:领域模型 Dao:持久层 Service:服务层 ...posted @ 刘冬.NET 阅读(40176) |摘要: 内容摘要单向多对多关联映射双向多对多关联映射⼀、单向多对多关联映射 1.1 多对多关联映射描述众所周知,持久化类的有三种对应关系:“⼀对⼀”、“⼀对多(多对⼀)”和“多对多”。
在项⽬开发过程中,我们接触过权限系统。
⽽权限系统中,“⽤户”和“⾓⾊”的对应关系往往就是“多对多”。
让我们看⼀下“多对多”的数据,如图1.1.1所⽰:图1.1.1 从数据中,我们能够观察到:多个⽤户(User)对应多个⾓⾊(Role)。
构造“多对多”的关联关系,我们不仅需要⽤户(User)表和⾓⾊(Role)表,还需要⽤户和⾓⾊的关系表。
通过这三张表的关系构造了“多对多”的关联关系。
让我们看⼀下代码: pu.posted @ 刘冬.NET 阅读(8042) |摘要: 内容摘要单向关联映射双向关联映射⼀、单向关联映射 1.1 单向关联映射的描述让我们回顾⼀下之前讲的《多对⼀关联映射》,如图1.1.1所⽰,其实“⼀对多”关联映射就是“多对⼀”关联映射相反的映射。
图1.1.1 ⾄于“⼀对多”单向关联映射的代码如下:publicclassStudent{publicvirtualint?ID{get;set;}publicvirtualstringName{get;set;}}publicclassClass{publicvirtualint? ID{get;set;}publicvirtualstringName{get;set;}publicvirt.posted @ 刘冬.NET 阅读(6675) |摘要: 内容摘要单向主键关联映射双向主键关联映射唯⼀外键关联映射 NHibernate的⼀对⼀关联映射有三种,单向主键关联映射、双向主键关联映射、唯⼀外键关联映射。
hibernate4.3.7双向一对多关系
(蔡庐总结)hibernate4.3.7双向一对多关系hibernate4.3.7双向一对多关系Parent,Child 一对多的关系。
做一个简单的插入操作。
直接上项目1、项目结构2、Child类package com.cailu.hibernate.Entity;public class Child {private String uuid;private String address;private String postCode;private Parent parent;public String getUuid() {return uuid;}public void setUuid(String uuid) {this.uuid = uuid;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getPostCode() {return postCode;}public void setPostCode(String postCode) {this.postCode = postCode;}public Parent getParent() {return parent;}public void setParent(Parent parent) {this.parent = parent;}}3、Parent类package com.cailu.hibernate.Client;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import com.cailu.hibernate.Entity.Child;import com.cailu.hibernate.Entity.Parent;public class Main {public static void main(String[] args) {SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();Session session = sessionFactory.getCurrentSession();session.beginTransaction();Parent parent = new Parent();parent.setName("父亲");Child child = new Child();child.setPostCode("1111111");child.setAddress("江西");Child child1 = new Child();child1.setPostCode("22222222");child1.setAddress("湖南");child.setParent(parent);child1.setParent(parent);parent.getChildren().add(child);parent.getChildren().add(child1);session.save(parent);session.getTransaction().commit();sessionFactory.close();}}8、插入得到的结果为:。
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属性。
hibernate-一对多,多对多关系
一对多关系配置和级联操作1.1一对多关系的XML配置文件以客户和联系人表为例:首先在持久化类一的一方中添加多的一方的对象的Set集合(Set集合在XML中配置比较简单);在多的一方添加一的一方对象的引用。
一的一方:Customer的配置文件:Customer.hbm.xml如下:多的一方:LinkMan.hbm.xml文件的配置注意的一个问题:在一对多的关系中,如果两张表都对外键维护的话会造成发送多余的SQL 语句,所以一般是让一的一方放弃对外键的维护。
还有别忘了在hibernate.cfg.xml文件中添加这俩文件的映射在set中添加属性inverse=“true”(cascade是级联属性)1.2一对多关系的级联保存级联是有方向性的:也就是说在一对多的关系中有两种级联保存的方式:1.通过一的一方保存多的一方(重点);2.通过多的一方级联保存一的一方(了解)1.2.1 一到多的级联保存方向的操作操作后的效果:例如客户和联系人的表关系,在保存客户后就相应把该客户的联系人全部保存。
只用保存客户对象就可以了。
操作的配置:在set集合中添加属性cascade=”true”具体操作如下:1.2.2多方到一方的级联保存操作操作的效果:用客户和联系人表举例,就是在保存联系人的时候保存其客户,这有点违背开发的需求,所以不是很常用。
具体的操作如下:操作设置:在多的一方添加属性cascade=”true”属性只需要将联系人与客户对象相关联就可以了1.3级联删除1.3.1 一方到多方的级联删除一到多的级联删除举例:删除客户的时候一并删除其所有的联系人操作设置:在一的一方的xml文件set标签中添加cascade=”delete”属性(cascade=”save-update,delete”表示级联保存和级联删除)1.3.2 多方到一方的级联删除举例:删除联系人的时候一并删除该客户(不符合需求,很少用)操作设置:在多的一方<many-to-one>标签中添加cascade=”delete”或者还需要级联保存时(cascade=”save-update,delete”)二多对多关系的XML配置和级联操作2.1 XML文件的配置以用户表和角色表举例:一个用户有多个角色,一个角色可以有多个人。
hibernate关系映射注解配置
1. Hibernate Annotation关系映射有下面几种类型:1)一对一外键关联映射(单向)2)一对一外键关联映射(双向)3)一对一主键关联映射(不重要,有需要看下文档即可)在实际中很少用,使用注解@PrimaryKeyJoinColumn意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试使用注解一对一主键关联映射,在生成表的时候,数据库中并没有生成关联,使用XML映射可以生成。
Annotation注解一对一主键关联映,有些bug。
不过没空去研究它。
因为在实际开发中一对一很少用。
在实际开发中我机会没有用过,主键关联就更少了4)多对一关联映射(单向)5)一对多关联映射(单向)6)一对多关联映射(双向)7)多对多关联映射(单向)8)多对多关联映射(双向)2.介绍各种映射用法1)一对一外键关联映射(单向)Husband ---> Wifepublic class Husband{private Wife wife;@OneToOne(cascade=CascadeType.ALL)@JoinColumn(name="wife_id",unique=true)public Wife getWife(){…}…}public class Wife{}一对一外键关联,使用@OneToOne,并设置了级联操作@JoinColum设置了外键的名称为wife_id(数据库字段名),如果不设置,则默认为另一类的属性名+ _id外键的值是唯一的(unique),不可重复,与另一类的主键一致2)一对一外键关联映射(双向)Husband <---> Wifepublic class Husband{private Wife wife;@OneToOne(cascade=CascadeType.ALL)@JoinColumn(name="wife_id",unique=true)public Wife getWife(){…}...}public class Wife{private Husband husband;@OneToOne(mappedBy="wife",cascade=CascadeType.ALL)public Husband getHusband(){…}...}一对一双向关联关系,使用@OneToOne注意:需要加上mappedBy="wife",如果不加上的话,Wife也会生成一个外键(husband_id)。
Hibernate中用注解配置一对多双向关联和多对一单向关联
Hibernate中⽤注解配置⼀对多双向关联和多对⼀单向关联Hibernate中⽤注解配置⼀对多双向关联和多对⼀单向关联Hibernate提供了Hibernate Annotations扩展包,使⽤注解完成映射。
在Hibernate3.3之前,需单独下载注解开发包配置持久化类配置关联关系下⾯我们先从多对⼀单向关联关系讲起,多对⼀单向关联就是在多的⼀⽅植⼊⼀的⼀⽅的主键作为外键,下⾯我们先进⾏初始配置,在配置的过程中我们会遇到⼀个问题就是⽆论⽤load还是get都不会出现延迟加载,那么我们应该如何设置为要延迟加载,这样做的好处是可以在⽤的时候才加载对应的信息,节约内存中,延迟加载⼤致可以分为两类,⼀类是延迟属性加载,另⼀类是延迟关联实体加载。
普通属性:分两种情况,⼀种是集合属性,⼀种是⾮集合属性(如String、Integer......)集合属性的延迟加载通过PersistentSet、 PersistentList、PersistentBag、PersistentMap、PersistentSortedMap、 PersistentSortedSet作为代理类来实现,代理类中保存了session以及owner属性,owner属性表⽰了集合属性所属的one 侧的实体。
⾮集合类属性的延迟加载相对⽐较复杂。
仅通过@Basic(fetch = ZY)注解是⽆法实现延迟加载的。
需要让实体实现FieldHandled接⼝,声明FieldHandler属性,通过拦截器原理注⼊对应的FieldHandler属性,起到类似于上述代理类的作⽤,FieldHandler 同样也保持了session,以及需要延迟加载的属性。
我们发现对⾮集合属性即时设置了@Basic(fetch = ZY)仍⽆法实现延迟加载,可以看⽣成的sql语句接下来我们会对⼀对多单向关联进⾏测试,验证对集合类属性,是否可以起到延迟加载的功能注意:不可以对有关联关系的属性设置@Transient配置多对⼀的单向关联关系⽰例1 package cn.happy.entity;23 import javax.persistence.Basic;4 import javax.persistence.Column;5 import javax.persistence.Entity;6 import javax.persistence.FetchType;7 import javax.persistence.GeneratedValue;8 import javax.persistence.GenerationType;9 import javax.persistence.Id;10 import javax.persistence.JoinColumn;11 import javax.persistence.ManyToOne;12 import javax.persistence.SequenceGenerator;13 import javax.persistence.Table;14 import javax.persistence.Transient;1516 @Entity17 @Table(name = "EMP")18public class Emp {19 @Id20 @Column(name = "EMPNO")21 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "emp_num")22 @SequenceGenerator(name = "emp_num", sequenceName = "emp_num_id", allocationSize = 1, initialValue = 1)23private Integer empNo;2425 @Column(name = "EMPNAME")26private String empName;2728 @ManyToOne()29 @JoinColumn(name = "DEPTNO")30/*@Basic(fetch=ZY)*/31private Dept dept;323334public Emp() {35 super();36 }3738public Emp(Integer empNo, String empName) {39 super();40this.empNo = empNo;41this.empName = empName;42 }4344public Integer getEmpNo() {45return empNo;46 }4748public void setEmpNo(Integer empNo) {49this.empNo = empNo;50 }5152public String getEmpName() {5556public void setEmpName(String empName) {57this.empName = empName;58 }5960public Dept getDept() {61return dept;62 }6364public void setDept(Dept dept) {65this.dept = dept;66 }67 }1package cn.happy.entity;23import java.util.HashSet;4import java.util.Set;56import javax.persistence.CascadeType;7import javax.persistence.Column;8import javax.persistence.Entity;9import javax.persistence.GeneratedValue;10import javax.persistence.GenerationType;11import javax.persistence.Id;12import javax.persistence.JoinColumn;13import javax.persistence.OneToMany;14import javax.persistence.SequenceGenerator;15import javax.persistence.Table;16import javax.persistence.Transient;1718import org.hibernate.annotations.Cascade;1920 @Entity21 @Table(name = "DEPT")22public class Dept {23 @Id24 @Column(name = "DEPTNO")25 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")26 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 27private Integer deptNo;2829 @Column(name = "DEPTNAME")30private String deptName;313233public Integer getDeptNo() {34return deptNo;35 }3637public void setDeptNo(Integer deptNo) {38this.deptNo = deptNo;39 }4041public String getDeptName() {42return deptName;43 }4445public void setDeptName(String deptName) {46this.deptName = deptName;47 }48 }1/**2 * 注解测试多对⼀映射员⼯表(多)对应部门表(⼀)的映射,即只在员⼯表中植⼊部门表的信息3 * */4 @Test5public void manytooneSingle(){67/**8 * 查询操作9 * **/10/*SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory();11 Session session = sf.openSession();1213 Emp emp=(Emp)session.load(Emp.class, 4);1415 System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());*/1617/**20 SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory();21 Session session = sf.openSession();22 Transaction tx = session.beginTransaction();23 Dept dept = (Dept)session.load(Dept.class, 3);2425 Emp emp=new Emp();26 emp.setEmpName("户梦艳");27 emp.setEmpNo(001);28 emp.setDept(dept);2930 Emp emp2=new Emp();31 emp2.setEmpName("户梦艳2");32 emp2.setEmpNo(002);33 emp2.setDept(dept);3435 session.save(emp);36 session.save(emp2);37 mit();38 session.close();394041 }⼀对多双单向配置1 package cn.happy.entity;23 import java.util.HashSet;4 import java.util.Set;56 import javax.persistence.CascadeType;7 import javax.persistence.Column;8 import javax.persistence.Entity;9 import javax.persistence.GeneratedValue;10 import javax.persistence.GenerationType;11 import javax.persistence.Id;12 import javax.persistence.JoinColumn;13 import javax.persistence.OneToMany;14 import javax.persistence.SequenceGenerator;15 import javax.persistence.Table;16 import javax.persistence.Transient;171819 @Entity20 @Table(name="Dept")21public class Dept {22 @Id23 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")24 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 25private Integer deptNo;26 @Column27private String deptName;282930 @OneToMany(cascade={CascadeType.ALL})31 @JoinColumn(name="deptno")32private Set<Emp> emps=new HashSet<Emp>();3334public Set<Emp> getEmps() {35return emps;36 }3738public void setEmps(Set<Emp> emps) {39this.emps = emps;40 }4142public Integer getDeptNo() {43return deptNo;44 }4546public void setDeptNo(Integer deptNo) {47this.deptNo = deptNo;48 }4950public String getDeptName() {51return deptName;52 }5354public void setDeptName(String deptName) {55this.deptName = deptName;57 }1 package cn.happy.entity;23 import javax.persistence.Basic;4 import javax.persistence.Column;5 import javax.persistence.Entity;6 import javax.persistence.FetchType;7 import javax.persistence.GeneratedValue;8 import javax.persistence.GenerationType;9 import javax.persistence.Id;10 import javax.persistence.JoinColumn;11 import javax.persistence.ManyToOne;12 import javax.persistence.SequenceGenerator;13 import javax.persistence.Table;14 import javax.persistence.Transient;1516 import org.hibernate.bytecode.javassist.FieldHandled;17 import org.hibernate.bytecode.javassist.FieldHandler;181920 @Entity21 @Table(name = "EMP")22public class Emp {23242526 @Id27 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num")28 @SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9) 29private Integer empNo;3031 @Column32private String empName;333435// @ManyToOne36// @JoinColumn(name="deptno")37// @Basic(fetch=ZY)38// private Dept dept;39//40// public Dept getDept() {41// return dept;42// }43//44// public void setDept(Dept dept) {45// this.dept = dept;46// }4748public Emp() {49 super();50 }5152public Emp(Integer empNo, String empName) {53 super();54this.empNo = empNo;55this.empName = empName;56 }5758public Integer getEmpNo() {59return empNo;60 }6162public void setEmpNo(Integer empNo) {63this.empNo = empNo;64 }6566public String getEmpName() {67return empName;68 }6970public void setEmpName(String empName) {71this.empName = empName;72 }737475 }2 * 测试⼀对多单向添加操作3 * */4 @Test5public void insertOneToManySingle(){6 Emp emp=new Emp();7 emp.setEmpName("李⼩鹏");89 Emp emp2=new Emp();10 emp2.setEmpName("王想想");1112 Dept dept=new Dept();13 dept.setDeptName("教务部");14//设置级联操作15 dept.getEmps().add(emp);16 dept.getEmps().add(emp2);1718 session.save(dept);19 mit();20 System.out.println("insert ok");2122 }1/**2 * 测试⼀对多单向查询操作3 * */4 @Test5public void selectOneToManySingle(){6 Dept dept = (Dept)session.load(Dept.class, 1);7 System.out.println("======================");8 System.out.println("部门名称:"+dept.getDeptName());9 System.out.println("=======================");10//体现了延迟加载11for (Emp emp : dept.getEmps()) {12 System.out.println("雇员名称:"+emp.getEmpName());13 }14//Emp emp = (Emp)session.load(Emp.class, 1);151617 }⼀对多双向配置1 package cn.happy.entity;23 import java.util.HashSet;4 import java.util.Set;56 import javax.persistence.CascadeType;7 import javax.persistence.Column;8 import javax.persistence.Entity;9 import javax.persistence.GeneratedValue;10 import javax.persistence.GenerationType;11 import javax.persistence.Id;12 import javax.persistence.JoinColumn;13 import javax.persistence.OneToMany;14 import javax.persistence.SequenceGenerator;15 import javax.persistence.Table;16 import javax.persistence.Transient;171819 @Entity20 @Table(name="Dept")21public class Dept {22 @Id23 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="dept_num")24 @SequenceGenerator(name="dept_num",sequenceName="dept_num_no",allocationSize=1,initialValue=1) 25private Integer deptNo;26 @Column27private String deptName;282930 @OneToMany(mappedBy="dept",cascade={CascadeType.ALL})3132private Set<Emp> emps=new HashSet<Emp>();3340 }4142public Integer getDeptNo() {43return deptNo;44 }4546public void setDeptNo(Integer deptNo) {47this.deptNo = deptNo;48 }4950public String getDeptName() {51return deptName;52 }5354public void setDeptName(String deptName) {55this.deptName = deptName;56 }57 }1 package cn.happy.entity;23 import javax.persistence.Basic;4 import javax.persistence.Column;5 import javax.persistence.Entity;6 import javax.persistence.FetchType;7 import javax.persistence.GeneratedValue;8 import javax.persistence.GenerationType;9 import javax.persistence.Id;10 import javax.persistence.JoinColumn;11 import javax.persistence.ManyToOne;12 import javax.persistence.SequenceGenerator;13 import javax.persistence.Table;14 import javax.persistence.Transient;1516 import org.hibernate.bytecode.javassist.FieldHandled;17 import org.hibernate.bytecode.javassist.FieldHandler;181920 @Entity21 @Table(name = "EMP")22public class Emp {23242526 @Id27 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="emp_num")28 @SequenceGenerator(name="emp_num",sequenceName="emp_num_no",allocationSize=1,initialValue=9) 29private Integer empNo;3031 @Column32private String empName;333435 @ManyToOne36 @JoinColumn(name="deptno")37 @Basic(fetch=ZY)38private Dept dept;3940public Dept getDept() {41return dept;42 }4344public void setDept(Dept dept) {45this.dept = dept;46 }4748public Emp() {49 super();50 }5152public Emp(Integer empNo, String empName) {53 super();54this.empNo = empNo;55this.empName = empName;56 }5764 }6566public String getEmpName() {67return empName;68 }6970public void setEmpName(String empName) {71this.empName = empName;72 }737475 }1/**2 * 双向⼀对多的添加操作3 * */4 @Test5public void oneToManyDouble(){6 Dept dept=new Dept();7 dept.setDeptName("财务部");89 Emp emp=new Emp();10 emp.setEmpName("邹乐");11 emp.setDept(dept);1213 Emp emp2=new Emp();14 emp2.setEmpName("范⼦阳");15 emp2.setDept(dept);161718 dept.getEmps().add(emp);19 dept.getEmps().add(emp2);2021 session.save(dept);22 mit();23 }241/**2 * 双向⼀对多的查询操作3 * */4 @Test5public void selectOneToManyDouble(){67 Dept dept = (Dept)session.load(Dept.class, 1);8 System.out.println("部门名称:"+dept.getDeptName());9for (Emp emp : dept.getEmps()) {10 System.out.println("职⼯姓名:"+emp.getEmpName());11 }1213 System.out.println("==================================================");1415 Emp emp = (Emp)session.load(Emp.class, 1);16 System.out.println("职⼯姓名:"+emp.getEmpName()+"\t部门名称:"+emp.getDept().getDeptName());17 }18。
A14多对一(一对多)关联映射
set在hibernate中的一对多的单向或者双向关联的情况下我们可以将一方控制权交给多方称为控制反转inverse在数据库中表与表之间不是孤立存在存在着各种关联关系而本章就主要讲解了如何在hibernate中代码:
课程介绍
目的:掌握Hibernate中一对多、多对一的单向与双向 映射,Hibernate的级联和控制反转。 内容:讲解Hibernate中一对多、多对一的单向与双向 映射,Hibernate的级联设置,和控制反转的设置。 重点:Hibernate中一对多、多对一的单向与双向映射。 难点:控制反转。
Product -id: Integer -name: String -price: Double -description: String
级联(cascade)
主动方对象执行操作时,被关联对象(被动方)是否同 步执行同一操作
<set name="products" cascade="save-update"> <key column="category_id"></key> <one-to-many class="com.vken.examples.Product" /> </set>
0..*
1
多对一单向关联
product id <pk> name price description category_id <fk> category id <pk> name description
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一对多关系示例,Base_Order和Base_OrderDetail是一对多的关系,通过Base_Order.OrderId和Base_O rderDetail.OrderId关联:实体Order代码:[Class(Table = "BASE_Order")]public class Order : Common.BaseEntity{private IList _childList;public Order(){_childList = new ArrayList();}/// <summary>/// 主键/// </summary>[Id(0, Name = "OrderId", Column = "OrderId", TypeType = typeof(int),UnsavedValue="0")][Generator(1, Class = "native")]public virtual int? OrderId { get; set; }/// <summary>/// 订单编号/// </summary>[Property(Name = "OrderCode", Column = "OrderCode", TypeType = typeof(String), Length = 128)]public virtual string OrderCode { get; set; }//订单明细物料,返回一个ArrayList对象[Bag(0, Cascade = "all", Name = "Cascade_OrderDetail",Inverse=true,Lazy=CollectionLazy.False)][Key(1,Column="OrderId")][OneToMany(1, ClassType = typeof(OrderDetail))]public virtual IList Cascade_OrderDetail {get{return _childList;}set{this._childList = value;}}}注意:OrderDetail类中的[KeyManyToOne(1, Column = "OrderId")]声明,是对应Order类中的[Key(1,Column="OrderId")]声明,这两个属性必须成对出现,否则Nhibernate.Mapping.Attributes生成的xml会缺key属性Nhibernate.Mapping.Attributes对应生成的Xml文件:<class table="BASE_Order" name="anization.Domain.Order, anization"><id name="OrderId" column="OrderId" type="Int32" unsaved-value="0"><generator class="native" /></id><property name="OrderCode" type="String" column="OrderCode" length="128" /><bag name="Cascade_OrderDetail" lazy="false" inverse="true" cascade="all"><key column="OrderId" /><one-to-many class="anization.Domain.OrderDetail, anization" /></bag></class>实体OrderDetail代码:[Class(Table = "BASE_OrderDetail")]public class OrderDetail : Common.BaseEntity{/// <summary>/// 主键/// </summary>[Id(0, Name = "OrderDetailId", Column = "OrderDetailId", TypeType = typeof(int), UnsavedValue = "0")][Generator(1, Class = "native")]public virtual int? OrderDetailId { get; set; }/// <summary>/// 物料编号/// </summary>[Property(Name = "ClassCode", Column = "ClassCode", TypeType = typeof(String), Length = 128)]public virtual string ClassCode { get; set; }[ManyToOne(0,Cascade = "all", Name = "Cascade_Order", Column = "OrderId", ClassType = typeof(Order))][KeyManyToOne(1, Column = "OrderId")]public virtual Order Cascade_Order {get;set;}}注意:OrderDetail类中的[KeyManyToOne(1, Column = "OrderId")]声明,是对应Order类中的[Key(1,Column="OrderId")]声明,这两个属性必须成对出现,否则Nhibernate.Mapping.Attributes生成的xml会缺key属性Nhibernate.Mapping.Attributes对应生成的Xml文件:<class table="BASE_OrderDetail" name="anization.Domain.OrderDetail, anization"> <id name="OrderDetailId" column="OrderDetailId" type="Int32" unsaved-value="0"><generator class="native" /></id><property name="ClassCode" type="String" column="ClassCode" length="128" /><many-to-one name="Cascade_Order" class="anization.Domain.Order, anization" col umn="OrderId" cascade="all" /></class>相关业务逻辑:添加Order的同时,向OrderDetail添加一条数据:Order parentObj = new Order();parentObj.OrderCode = "orderCode1523";OrderDetail child1 = new OrderDetail();child1.ClassCode = "classCode1523_1";child1.Cascade_Order = parentObj;parentObj.Cascade_OrderDetail.Add(child1);OrderDetail child2 = new OrderDetail();child2.ClassCode = "classCode1523_2";child2.Cascade_Order = parentObj;parentObj.Cascade_OrderDetail.Add(child2);this.entityBLO.Save(parentObj);Nhibernate自动生成的sql语句:exec sp_executesql N'INSERT INTO BASE_Order (OrderCode) V ALUES (@p0); select SCOPE_IDENTITY()', N'@p0 n varchar(128)', @p0 = N'orderCode1523' goexec sp_executesql N'INSERT INTO BASE_OrderDetail (ClassCode, OrderId) VALUES (@p0, @p1); select SCOPE_ID ENTITY()', N'@p0 nvarchar(128),@p1 int', @p0 = N'classCode1523_1', @p1 = 2 goexec sp_executesql N'INSERT INTO BASE_OrderDetail (ClassCode, OrderId) VALUES (@p0, @p1); select SCOPE_ID ENTITY()', N'@p0 nvarchar(128),@p1 int', @p0 = N'classCode1523_2', @p1 = 2 go修改Order的同时,修改OrderDetail的数据,并且添加一条OrderDetail的数据:Order parentObj = (Order)this.entityBLO.Get(1, typeof(Order));parentObj.OrderCode = "orderCode1523"; //如果新赋值与原值相同,那么Nhibernate不会产生Update语句OrderDetail childObj = (OrderDetail)parentObj.Cascade_OrderDetail[0];childObj.ClassCode = "classCode1523_1"; //直接修改第一个物料,如果新赋值与原值相同,那么Nhibernate不会产生Up date语句OrderDetail childObj3 = new OrderDetail();childObj3 = new OrderDetail();childObj3.ClassCode = "classCode1523_3";childObj3.Cascade_Order = parentObj; //如果不加这句,那么插入的OrderDetail数据的OrderId为NullparentObj.Cascade_OrderDetail.Add(childObj3); //如果不加这句,则无法插入OrderDetail对象this.entityBLO.MergeUpdate(parentObj); //如果是级联保存,则不能用Update方法,Nhibernate会报错:Illegal attempt to associate a collection with two open sessionsNhibernate自动生成的sql语句:INSERT INTO BASE_OrderDetail (ClassCode, OrderId) VALUES (@p0, @p1); select SCOPE_IDENTITY();@p0 = 'cla ssCode1523_3' [Type: String (128)], @p1 = 1 [Type: Int32 (0)]UPDATE BASE_Order SET OrderCode = @p0 WHERE OrderId = @p1;@p0 = 'orderCode1523' [Type: String (128)], @p1 = 1 [Type: Int32 (0)]UPDATE BASE_OrderDetail SET ClassCode = @p0, OrderId = @p1 WHERE OrderDetailId = @p2;@p0 = 'classCode 1523_1' [Type: String (128)], @p1 = 1 [Type: Int32 (0)], @p2 = 1 [Type: Int32 (0)]删除Organization的同时,删除Department的数据:Order parentObj = (Order)this.entityBLO.Get(1, typeof(Order));this.entityBLO.MergeDelete(parentObj);//如果是级联删除,则不能用Delete方法,Nhibernate会报错:Illegal atte mpt to associate a collection with two open sessionsNhibernate自动生成的sql语句:exec sp_executesql N'DELETE FROM BASE_OrderDetail WHERE OrderDetailId = @p0', N'@p0 int', @p0 = 1 go exec sp_executesql N'DELETE FROM BASE_OrderDetail WHERE OrderDetailId = @p0', N'@p0 int', @p0 = 2 go exec sp_executesql N'DELETE FROM BASE_OrderDetail WHERE OrderDetailId = @p0', N'@p0 int', @p0 = 3 go exec sp_executesql N'DELETE FROM BASE_Order WHERE OrderId = @p0', N'@p0 int', @p0 = 1 go注意事项:如果Xml的配置属性Cascade = “all”,表示Order和OrderDetail的数据同时删除如果Xml的配置属性Cascade = “save-update”,表示仅删除Order的数据在NHibernate配置文件中使用<set>, <list>, <map>, <bag>, <array> 和<primitive-array>等元素来定义集合。