一对一,各种形式的单双向关联
- 格式:doc
- 大小:86.00 KB
- 文档页数:10
理解关系模式了解不同类型的关系模式关系模式是数据库设计中的一个重要概念,用于描述实体之间的联系和关联。
不同类型的关系模式对于数据库设计和查询操作都具有一定的影响。
本文将介绍关系模式的概念以及常见的几种不同类型的关系模式。
关系模式的概念关系模式是一种结构化的数据模型,用于描述实体之间的关系和联系。
在关系数据库中,数据以表格的形式进行存储和组织,每个表格都有一个或多个列,每一列表示一个属性,而每一行则表示一个记录。
不同类型的关系模式1. 一对一关系模式一对一关系模式指的是两个实体之间存在一种对应关系,即一个实体实例只能关联到另一个实体实例。
在数据库设计中,可以通过在两个表格之间添加外键约束来实现一对一关系模式。
2. 一对多关系模式一对多关系模式指的是一个实体实例可以关联到多个另一个实体实例,但是另一个实体实例只能关联到一个实体实例。
在数据库设计中,可以通过在多的一方的表格中添加外键约束来实现一对多关系模式。
3. 多对多关系模式多对多关系模式指的是两个实体之间存在多对多的关联关系,即一个实体实例可以关联到多个另一个实体实例,同样另一个实体实例也可以关联到多个当前实体实例。
在数据库设计中,通常需要创建一个连接表格来实现多对多关系。
4. 继承关系模式继承关系模式是面向对象编程中常见的概念,在数据库设计中也可以应用。
继承关系模式指的是一个实体继承了另一个实体的属性和行为。
在关系数据库中,可以通过创建不同的表格来表示继承关系,其中父实体的属性会被子实体继承,并在子实体的表格中添加额外的属性。
5. 直接关系和间接关系模式直接关系模式指的是两个实体直接相连的关系,而间接关系模式指的是两个实体通过其他实体之间的关联来建立联系。
在数据库设计中,可以通过表格之间的外键关系来实现直接关系模式,而通过中间表格或者多级关联的方式来实现间接关系模式。
总结关系模式是数据库设计中的重要概念,用于描述实体之间的联系和关联。
不同类型的关系模式可以适用于不同的场景和需求,合理选择合适的关系模式对于数据库的性能和查询效率具有重要的影响。
面向对象程序设计关联名词解释下载提示:该文档是本店铺精心编制而成的,希望大家下载后,能够帮助大家解决实际问题。
文档下载后可定制修改,请根据实际需要进行调整和使用,谢谢!本店铺为大家提供各种类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by this editor. I hope that after you download it, it can help you solve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you! In addition, this shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts, other materials and so on, want to know different data formats and writing methods, please pay attention!深入理解面向对象程序设计中的关联关系一、引言在面向对象程序设计中,关联关系是一种重要的概念,它描述了不同类之间的连接和依赖。
产品经理必须懂的关系模型–⼀对⼀,⼀对多以及多对多关系背景:通常会有不同的需求⽅给产品经理提需求,产品经理在设计功能的时候,需要将需求转换成后台可以理解的实体,并且将实体之间的关系描述给后台,因为产品⼤多数不懂技术,所以在描述关系的时候,可能会存在误解,所以,产品经理必须懂⼀些最基础的数据库知识。
数据库模型⼀般有“层次模型”,“⽹状模型”,“关系模型”这三种,⽽“关系模型”因为其简单,理解起来简单,所以逐渐流⾏起来。
“关系模型”中⼀般包括以下三种关系,分别是“⼀对⼀关系”,“⼀对多关系”,“多对多关系”。
正⽂主流关系数据库⽬前,主流的关系数据库主要分为以下⼏类:商⽤数据库,例如:Oracle,SQL Server,DB2等;开源数据库,例如:MySQL,PostgreSQL等;桌⾯数据库,以微软Access为代表,适合桌⾯应⽤程序使⽤;嵌⼊式数据库,以Sqlite为代表,适合⼿机应⽤和桌⾯程序。
我们已经知道,关系数据库是建⽴在关系模型上的。
⽽关系模型本质上就是若⼲个存储数据的⼆维表,可以把它们看作很多Excel表。
表的每⼀⾏称为记录(Record),记录是⼀个逻辑意义上的数据。
表的每⼀列称为字段(Column),同⼀个表的每⼀⾏记录都拥有相同的若⼲字段。
和Excel表(单表)有所不同的是,关系数据库的表和表之间需要建⽴“⼀对多”,“多对⼀”和“⼀对⼀”的关系,这样才能够按照应⽤程序的逻辑来组织和存储数据。
单表单表是数据库⾥⾯最基础的元素。
在产品设计时,如果只需要操作⼀个实体的,并提供curd 等基础操作,那么这个实体就可以⽤单表存储。
如餐厅的门店数据,菜品数据等。
通常情况下,单表的数据以table 的形式展现,操作的按钮也有两种交互⽅式,显式的显⽰或者hover 以后再显⽰对应的操作。
这两种没有明显的优缺点,需要根据业务形态,进⾏选择。
常见产品例⼦:在实际的⼯业化产品中,单表结构的数据实际上是⽐较少的,⽐较常见的是⽤户访问⽇志,系统⽇志等。
数据库-⼀对⼀、⼀对多、多对⼀、多对多关系
⼀对多关系、多对⼀关系和⼀对⼀关系
1. ⾄少都有⼀侧是单个实体,所以记录之间的联系通过外键实现,让外键指向这个实体。
2. 实现这种关系时,要在“多”这⼀侧加⼊⼀个外键,指向“⼀”这⼀侧联接的记录。
多对多关系
1. 解决⽅法是添加第三个表,这个表称为关联表。
2. 多对多关系可以分解成原表和关联表之间的两个⼀对多关系
多对多关系例⼦
查询多对多关系要分成两步。
1. 若想知道某位学⽣选择了哪些课程,要先从学⽣和注册之间的⼀对多关系开始,获取这位学⽣在 registrations 表中的所有记录。
2. 然后再按照多到⼀的⽅向遍历课程和注册之间的⼀对多关系,找到这位学⽣在 registrations 表中各记录所对应的课程。
3. 同样,若想找到选择了某门课程的所有学⽣,你要先从课程表中开始,获取其在 registrations 表中的记录,再获取这些记录联接的学⽣。
⾃引⽤关系也是多对多的⼀种特殊情况
如果关系中的两侧都在同⼀个表中,这种关系称为⾃引⽤关系。
在关注中,关系的左侧是⽤户实体,可以称为“关注者”;关系的右侧也是⽤户实体,但这些是“被关注者”。
举例说明一对一,一对多,多对多关系一对一、一对多和多对多关系是数据库中常见的关系模型,用于描述数据实体之间的关联。
下面将分别以不同领域的实例来说明这三种关系模型。
一对一关系:1. 身份证和个人:一个人只能拥有一个身份证,而一个身份证也只能属于一个人。
2. 学生和班主任:一个学生只能有一个班主任,而一个班主任也只能负责一个学生。
3. 用户和手机号码:一个用户只能绑定一个手机号码,而一个手机号码也只能被一个用户绑定。
4. 员工和档案:一个员工只有一个档案,而一个档案也只能对应一个员工。
5. 作者和书籍:一个作者只能创作一本书籍,而一本书籍也只能由一个作者创作。
一对多关系:1. 学校和学生:一个学校可以有多个学生,但一个学生只能属于一个学校。
2. 部门和员工:一个部门可以有多个员工,但一个员工只能属于一个部门。
3. 班级和学生:一个班级可以有多个学生,但一个学生只能属于一个班级。
4. 作者和书籍:一个作者可以创作多本书籍,但一本书籍只能由一个作者创作。
5. 电视剧和演员:一部电视剧可以有多个演员,但一个演员只能参演一部电视剧。
多对多关系:1. 学生和课程:一个学生可以选择多门课程,一门课程也可以有多个学生选择。
2. 顾客和商品:一个顾客可以购买多个商品,一个商品也可以被多个顾客购买。
3. 音乐家和乐器:一个音乐家可以演奏多种乐器,一个乐器也可以被多个音乐家演奏。
4. 饭店和菜品:一个饭店可以供应多种菜品,一种菜品也可以在多个饭店供应。
5. 作家和书籍:一个作家可以创作多本书籍,一本书籍也可以由多个作家创作。
以上是一对一、一对多和多对多关系的举例,它们在实际应用中具有广泛的应用。
在数据库设计和数据处理中,合理地使用这些关系模型可以更好地组织和管理数据。
双向一对一关联-----基于外键关联的双向一对一关联基于外键的双向一对一关联是一种比较常见的关联。
Hibernate通过<many-to-one>标记和<one-to-one>标记结合起来定义这种关联。
这种关联的映射文件与基于外键关联的单向一对一关联基本一致,区别在已有的<many-to-one>的基础上,在另一方增加<one-to-one>标记进行关联。
映射文件如下<hibernate-mapping><classname="hibernate.wizard.chapter8.Person3"table="C8_Person3"schema="dbo"><idname="personId"type="ng.String"column="personId"><generator class="assigned" /></id><!-- Associations --><many-to-one name="address"column="addressId"class="hibernate.wizard.chapter8.Address3"not-null="true"cascade="all"unique="true"/></class><classname="hibernate.wizard.chapter8.Address3"table="C8_Address3"schema="dbo"><idname="addressId"type="ng.String"column="addressId"><generator class="assigned" /></id><propertyname="addressName"type="ng.String"column="addressName"not-null="false"length="50"></property><!-- Associations --><one-to-onename="person"class="hibernate.wizard.chapter8.Person3"property-ref="address"/></class></hibernate-mapping>持久化类Person3类public class Person3 implements Serializable {private String personId;private String addressId;private Address3 address; //双向一对一关联public Person3(String personId, String addressId) { this.personId = personId;this.addressId = addressId;}public Person3(String personId,Address3 address){ this.personId = personId;this.addressId=address.getAddressId();this.address=address;}public Person3(String personId) {this.personId = personId;}public Person3() {}public String getPersonId() {return this.personId;}public void setPersonId(String personId) { this.personId = personId;}public String getAddressId() {return this.addressId;}public void setAddressId(String addressId) { this.addressId = addressId;}public String toString() {return new ToStringBuilder(this).append("personId", getPersonId()) .toString();}public Address3 getAddress() {return address;}public void setAddress(Address3 address) {this.address = address;}}Address3类public class Address3 implements Serializable {private String addressId;private String addressName;private Person3 person; //双向一对一关联public Address3(String addressId,String addressName) { this.addressId = addressId;this.addressName=addressName;}public Address3() {}public String getAddressId() {return this.addressId;}public void setAddressId(String addressId) {this.addressId = addressId;}public String toString() {return new ToStringBuilder(this).append("addressId", getAddressId()).toString();}public String getAddressName() {return addressName;}public void setAddressName(String addressName) {this.addressName = addressName;}public Person3 getPerson() {return person;}public void setPerson(Person3 person) {this.person = person;}测试类public class OneToOne3Test {Session session;Transaction tx;public static void main(String[] args) {OneToOne3Test util=new OneToOne3Test();util.insert();}public void insert(){try {session = HibernateUtil.getSession();} catch (HibernateException ex) {System.out.println(ex);}tx = session.beginTransaction();//开始事务Address3 addr=new Address3("0001","云山路");Person3 p=new Person3("00001");p.setAddressId(addr.getAddressId());p.setAddress(addr);addr.setPerson(p);session.save(p);session.flush();ArrayList result=(ArrayList)session.createQuery("fromhibernate.wizard.chapter8.Person3 as p" +" where p.personId='00001'").list();for (int i=0;i<result.size();i++){Person3 p1=(Person3)result.get(i);System.out.println("---personId---addressId---addressName---personId from Address3");System.out.println("---"+p1.getPersonId()+"---"+p1.getAddressId()+"---"+p1.getAddress().getAddressName()+"---"+p1.getAddress().getPerson() .getPersonId());}mit();//提交事务session.close();//关闭session}}测试结果如下初始化SessionFactory成功!!!!Hibernate: select address3x_.addressId, address3x_.addressName as addressN2_12_ from dbo.C8_Address3 address3x_ where address3x_.addressId=? Hibernate: insert into dbo.C8_Address3 (addressName, addressId) values (?, ?) Hibernate: insert into dbo.C8_Person3 (addressId, personId) values (?, ?) Hibernate: select person3x0_.personId as personId11_, person3x0_.addressId as addressId11_ from dbo.C8_Person3 person3x0_ whereperson3x0_.personId='00001'---personId---addressId---addressName---personId from Address3---00001---0001---云山路---00001。
一对一关联关系创建POJO对象妻子和丈夫是一对一的关系,基于这种关系,设计类时在妻子类中保存一个丈夫类型的引用,同样在丈夫类中保存一个妻子类型的用。
Wife类:id name Husband类型的属性:husbandHusband类:id name Wife类型的属性:wife不要忘了生成Getter和Setter方法创建映射文件在建立映射的时候可以从一方入手,要么从妻子找到丈夫,要么从丈夫找到妻子,这里采用后者,即丈夫的id来源于妻子的id(夫妻具有相同的id),建立映射文件的时候要注意,需要同时在妻子和丈夫的映射文件中添加one-to-one元素,name属性指定类中定义的引用类型的属性名;还要对丈夫映射文件中的id元素的配置项进行修改,将生成器设为foreign类型,添加一个param子元素,参数名为property,值为类中定义的引用类型的属性名。
在丈夫映射文件的one-to-one元素下配置constrained属性为true,则可将这种外键关联反映到数据库表结构中(即为丈夫表建立外键约束)。
Wife.hbm.xml文件<class name="Wife"><id name="id"><generator class="native"/></id><property name="name"/><one-to-one name="husband"></one-to-one></class>Husband.hbm.xml文件<class name="Husband"><id name="id"><generator class="foreign"><param name="property">wife</param></generator></id><property name="name"/><one-to-one name="wife"constrained="true"></one-to-one> </class>上面的映射文件的配置可以通过丈夫找到妻子,若要保存一条丈夫记录,则必须要为丈夫对象设置妻子类型的属性,这样只需要保存丈夫对象,则其持有的妻子对象中的信息也会与数据库同步,看下面的代码:static void saveHusband() {Session s = null;Transaction tx = null;try {Wife w1 = new Wife();w1.setName("wife1");Husband h1 = new Husband();h1.setName("husband1");h1.setWife(w1);s = HibernateUtil.getSession();tx = s.beginTransaction();s.save(h1);mit();} finally {if (s != null) {s.close();}}}这样的话只插入丈夫的记录,如果关联的妻子的记录不存在,就会添加妻子记录到数据库中。
数据库的表关系图1>:one-to-one(一对一关联)主键关联:一对一关联一般可分为主键关联和外键关联主键关联的意思是说关联的两个实体共享一个主键值,但这个主键可以由两个表产生.现在的问题是:*如何让另一个表引用已经生成的主键值解决办法:*Hibernate映射文件中使用主键的foreign生成机制eg:学生表:<hibernate-mapping><class name="er" table="user" catalog="study"><id name="userid" type="ng.Integer"><column name="userid" /><generator class="native" /></id><property name="username" type="ng.String"><column name="username" length="20" /></property><one-to-one name="card" class="org.wen.beans.Card" cascade="all"></one-to-one></class></hibernate-mapping>添加:<one-to-one name="card"class="org.wen.beans.Card"fetch="join"cascade="all" /><class>元素的lazy属性为true,表示延迟加载,如果lazy设为false,则表示立即加载.以下对这二点进行说明.立即加载:表示在从数据库中取得数据组装好一个对象后,会立即再从数据库取得数据组装此对象所关联的对象延迟加载:表示在从数据库中取得数据组装好一个对象后,不会立即从数据库中取得数据组装此对象所关联的对象,而是等到需要时,才会从数据库取得数据组装此关联对象.<one-to-one>元素的fetch属性可选为select和joinjoin:连接抓取,Hibernate通过在Select语句中使用outer join(外连接)来获得对象的关联实例或者关联集合.select:查询抓取,Hibernate需要另外发送一条select语句抓取当前对象的关联实体或集合.******所以我们一般用连接抓取<join>证件表:<hibernate-mapping><class name="org.wen.beans.Card" table="card" lazy="true" catalog="study"><id name="cardid" type="ng.Integer"><column name="cardid" /><generator class="foreign"><param name="property">user</param></generator></id><!-- id使用外键(foreign)生成机制,引用代号为user的对象的主键作为card表的主键和外键。
数据库表关系是指数据库中各种表之间的连接和对应关系。
在数据库中,表是用于存储数据的基本单位,每个表都包含一组相关的数据字段。
表之间的关系可以通过建立关联字段来实现,这些关联字段在多个表中具有相同的值,从而将它们连接在一起。
数据库中的表关系通常可以分为三种类型:一对一关系、一对多关系和多对多关系。
一对一关系是指两个表之间存在一端对一端的关系,即一个表中的一条记录只能与另一个表中的一条记录相关联。
这种关系通常用于表示两个实体之间的唯一对应关系。
例如,一个客户表和一个订单表之间可能存在一对一关系,因为每个客户只能对应一个订单,而每个订单只能对应一个客户。
一对多关系是指一个表中的记录可以与另一个表中的多条记录相关联。
这种关系通常用于表示一个实体的一组相关属性与另一个实体的单一属性之间的关系。
例如,一个员工表可以与一个工资表建立一对多关系,因为每个员工可以有多个工资记录,而每个工资记录只与一个员工相关联。
多对多关系是指两个表之间存在两个端点之间的多对多的关系。
这种关系通常用于表示两个实体之间的多个属性之间的交叉关系。
例如,一个学生表和一个课程表之间可能存在多对多关系,因为一个学生可以选修多门课程,同时一门课程也可以被多个学生选修。
在这种情况下,可以使用中间表来存储这种关系。
除了上述三种基本的关系类型,数据库中还可能存在其他的关系类型,如共享字段关系、父-子关系等。
这些关系类型的具体应用取决于数据的特性和需求。
理解数据库表之间的关系对于数据库设计和查询非常重要。
通过了解表之间的关系,可以更好地组织数据,提高查询效率,并确保数据的一致性和完整性。
在设计和维护数据库时,需要仔细考虑表之间的关系,并使用适当的索引和关联技术来优化数据访问和检索性能。
总之,数据库表关系是数据库中数据组织和存储的核心概念之一。
通过理解不同类型的表关系,可以更好地管理数据并提高数据库的性能和可靠性。
依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现
关系
依赖关系:表示一个类的变化会影响另一个类,但两个类之间并不存在拥有和共享的关系。
类之间通过参数传递、方法调用等方式产生依赖关系。
关联关系:表示两个类之间的联系,强调的是它们之间的共享。
关联关系可以是单向的或双向的,可以是一对一的、一对多的或多对多的。
聚合关系:表示整体与部分之间的关系,整体对象拥有部分对象,但部分对象不是整体对象的一部分。
聚合关系是一种弱关联关系,两个对象的生命周期可以独立。
组合关系:也表示整体与部分之间的关系,但部分对象是整体对象的一部分,没有它们整体对象就无法存在。
组合关系是一种强关联关系,两个对象的生命周期是相互依赖的。
泛化关系:表示一个类是另一个类的特殊形式,继承关系的表示方式之一。
泛化关系体现了一种继承和特化的关系,子类继承了父类的属性和方法,并可以进行扩展和覆盖。
实现关系:表示一个类实现了一个接口,接口可以定义一组规范,类需要实现这些规范中定义的方法。
实现关系实现了一种接口或协议,在面向对象的编程中强调了一种规范和标准的约定。
数据库表关系(单表、⼀对⼀、⼀对多、多对多) 写在开头: ⼀直搞不清楚数据库表之间的关系,看了很多博客还是有些弥漫,没有具体的例⼦辅助。
所以写了下⾯的内容,此⽂中的案例以学校为例,个⼈理解,可能会有诸多不妥之处,仅供参考。
⼀、两个重要概念: 什么是主键?外键? 1.主键:主键是表的⼀个特殊字段,可以唯⼀地标识表中的每条信息。
⽐如:⾝份证号。
⼀个表中可以有⼀个或多个主键。
作⽤:唯⼀标识、快速查找 2.外键:如果表B的⼀个字段(外键)依赖于表A的主键。
则成表A为⽗表,表B为⼦表。
原则:外键必须依赖于数据库中已经存在的⽗表的主键,外键可以为空 作⽤:建⽴该表与⽗表的关联关系⼆、表关系 包括单表、多表(⼀对⼀、⼀对多、多对多) 1.单表 就是⼀张表,所有的数据都在⼀张表中。
例:下⾯这张表,学习信息都存在⼀张表中。
2.多表 2.1⼀对⼀(不常⽤)A 表中的⼀⾏最多只能匹配于B 表中的⼀⾏ 应⽤场景: 1.单表太⼤,⼀分为⼆ 2.由于安全原因⽽隔离表的⼀部分 例:为了收集学⽣的联系⽅式,⼜建了⼀张学⽣联系表,如下图。
联系表(⼦表)中的外键(学号),必须依赖于信息表(⽗表)中的主键(学号)存在。
2.2⼀对多A 表中的⼀⾏可以匹配B 表中的多⾏,但是 B 表中的⼀⾏只能匹配 A 表中的⼀⾏ 例:学⽣到校后,需要分班,下⾯的两张表就产⽣了。
⼀个班有多个学⽣,⼀个学⽣只能归属⼀个班级, 2.3多对多 多对多就是两个⼀对多A 表中的⼀⾏可以匹配B 表中的多⾏,反之亦然。
要创建这种关系,需要定义第三个表,称为,它的主键由 A 表和 B 表的外键组成。
例:办级分好之后学⽣就该选课了。
我们需要⼀张课程表。
⼀个学⽣可以选择多门科,⼀门课也可以多名同学上。
此时我们通过第三张表来映射这种关系。
课程表: 学⽣分班表: 选课结果(第三张表): 。
⼀对⼀关联查询注解@OneToOne的实例详解 表的关联查询⽐较复杂,应⽤的场景很多,本⽂根据⾃⼰的经验解释@OneToOne注解中的属性在项⽬中的应⽤。
本打算⼀篇博客把增删改查写在⼀起,但是在改的时候遇到了⼀些问题,感觉挺有意思,所以写下第⼆篇专门讲修改。
⼀、单向@OneToOne实例详解假设⼀个场景,⼀个⼈只能领养⼀只宠物,根据⼈能够找到宠物,并且查看宠物的信息,关系是单向的。
创建⼈与宠物的数据表结构。
下载地址:创建实体。
Person.javapackage com.my.model;import java.io.Serializable;import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.ForeignKey;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToOne;import javax.persistence.Table;import org.hibernate.annotations.Cascade;import org.springframework.beans.factory.annotation.Autowired;@Entity@Table(name = "person")public class Person implements Serializable{@Id// id⾃动⽣成@GeneratedValue@Column(name = "id")private Long id;@Column(name = "name")private String name;//cascade:表的级联操作@OneToOne(fetch=ZY,cascade = CascadeType.ALL) //JPA注释:⼀对⼀关系//referencedColumnName:参考列名,默认的情况下是列表的主键//nullable=是否可以为空,//insertable:是否可以插⼊,//updatable:是否可以更新// columnDefinition=列定义,//foreignKey=外键@JoinColumn(name="pet_id",referencedColumnName="id",nullable=false)private Pet pet;@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", pet=" + pet + "]";}}Pet.javapackage com.my.model;import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name = "pet")public class Pet implements Serializable{@Id// id⾃动⽣成@GeneratedValue@Column(name = "id")private Long id;@Column(name = "pet_name")private String petName;@Column(name = "pet_class")private String petClass;//省略set,get⽅法。
关联关系、依赖关系总结⼀、关联关系总结:1.对象和对象之间的连接。
在Java中,关联关系的代码表现形式为⼀个类做为另⼀个类的属性类型存在。
即“有”的关系:”has-a”。
2.关联关系的⽅向:关联关系分为单向关联和双向关联①单向关联: A类关联B类。
②双向关联:A类关联B类,B类关联A类。
3.关联关系的多重性:①⼀对⼀关联:⼀个学⽣,只能在⼀个班级⾥学习。
②⼀对多关联:⼀个学⽣,可以参加多个班级学习。
③解决⼀对多的关联的⽅案:集合和数组。
集合例:public class Classes{}public class Student{private List Classess;}数组例:public class Classes{}public class Student{private Classes[] Classess;}4.关联关系的特殊情况:如果两个互相关联的类中有整体和部分的关系,关联关系分为:聚合和组合,主要区别在于⽣命周期不同。
⼆、依赖关系总结:1.依赖关系的定义:依赖关系(use-a),指⼀个类A使⽤到了另⼀个类B。
2.依赖关系的特性:这种关系是具有偶然性的、临时性的、⾮常弱的,但是类B的变化会影响到类A。
3.依赖具体表现:在代码层⾯,依赖关系表现为类B作为参数被类A在某个method。
4.依赖与关联的区别:关联是“HAS”关系,依赖是“USE”关系:①A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。
②A类依赖B类,指的是B的对象作为A类的⽅法参数存在,称为“use”关系。
⽣命周期不同:①如果A类关联B类,那么创建A类的对象时实例化B类的对象,直到A类对象被销毁,所关联的B类对象也被销毁。
即只要A类对象存在,B类对象就存在。
②如果A类依赖B类,那么只有当A类对象调⽤到相应⽅法时,B类对象才被临时创建,⽅法执⾏结束,B类对象即被回收,A类和B类之间的依赖关系是⼀种瞬时的关系。
数据表的关联关系数据表的关联关系是数据库设计中非常重要的概念之一。
通过合理的关联关系,可以实现数据的一致性、完整性和可靠性,提高数据库的查询效率和数据操作的灵活性。
下面将介绍几种常见的数据表关联关系,并分析它们的应用场景和优缺点。
1. 一对一关联一对一关联是最简单的关联关系之一,指的是两个数据表之间存在唯一的对应关系。
在一对一关联中,每个记录在另一个数据表中都只对应一个记录。
这种关联关系通常用于将一个数据表中的某些字段分离出来,形成一个独立的数据表。
例如,一个人员信息表中的身份证号字段可以作为一个独立的数据表,与人员信息表进行一对一关联。
2. 一对多关联一对多关联是最常见的关联关系之一,指的是一个数据表的每条记录在另一个数据表中都可以对应多条记录。
在一对多关联中,一个数据表的主键作为另一个数据表的外键,用于建立两个数据表之间的联系。
这种关联关系通常用于表示层次关系或者父子关系。
例如,一个部门表与一个员工表之间可以建立一对多关联,一个部门可以有多个员工,而一个员工只能属于一个部门。
3. 多对多关联多对多关联是最复杂的关联关系之一,指的是两个数据表之间存在多对多的对应关系。
在多对多关联中,一个数据表的每条记录可以对应另一个数据表的多条记录,反之亦然。
为了建立多对多关联,通常需要使用一个中间表来存储两个数据表之间的对应关系。
例如,一个学生表与一个课程表之间可以建立多对多关联,一个学生可以选择多门课程,而一门课程也可以被多个学生选择。
4. 自关联自关联是指一个数据表与自身建立关联关系。
自关联通常用于表示层次结构,例如一个组织机构表中的上级部门与下级部门之间的关系。
在自关联中,一个数据表的主键同时也是外键,用于建立记录与记录之间的关联关系。
通过自关联,可以方便地查询一个记录的上级记录或者下级记录。
在实际的数据库设计中,通常会同时使用多种关联关系来满足不同的需求。
例如,一个订单表可以与一个客户表建立一对多关联,表示一个客户可以有多个订单;同时,订单表也可以与一个商品表建立多对多关联,表示一个订单可以包含多种商品。
单向关联与双向关联双向更灵活些。
你只想根据多的⼀⽅存储⼀的⼀⽅,⽽⽤⼀的⼀⽅存储多的⼀⽅⽆效,即便是有数据也不会插⼊到数据库⾥⾯的。
⼀般选择双向毕竟灵活。
@Entitypublic class Classes {private int id;private String name;// ⼀对多通常使⽤Set来映射,Set是不可重复内容。
// 注意使⽤Set这个接⼝,不要使⽤HashSet,因为hibernate有延迟加载,private Set<Student> students = new HashSet<Student>();@OneToMany//进⾏注解为⼀对多的关系@JoinColumn(name="classesId")//注释的是另⼀个表指向本表的外键。
在多的⼀端注解⼀个字段(名为classessid)@JoinColumn(name="classesId")public Set<Student> getStudents() {return students;}(七) 导出⾄数据库(hbm ddl)⽣成的SQL语句:create table t_classes (id integer not null auto_increment, name varchar(255), primary key (id))create table t_student (id integer not null auto_increment, name varchar(255), classesid integer, primary key (id))alter table t_student add index FK4B90757070CFE27A (classesid), add constraint FK4B90757070CFE27A foreign key (classesid) references t_classes (id)(⼋) ⼀对多单向存储实例:session = HibernateUtils.getSession();tx = session.beginTransaction();Student student1 = new Student();student1.setName("10");session.save(student1);//必需先存储,否则在保存classess时出错.Student student2 = new Student();student2.setName("祖⼉");session.save(student2);//必需先存储,否则在保存classess时出错.Set<Student> students = new HashSet<Student>();students.add(student1);students.add(student2);Classes classes = new Classes();classes.setName("wjt276");classes.setStudents(students);session.save(classes);mit();(九) ⽣成的SQL语句:Hibernate: insert into t_student (name) values (?)Hibernate: insert into t_student (name) values (?)Hibernate: insert into t_classes (name) values (?)Hibernate: update t_student set classesid=? where id=?Hibernate: update t_student set classesid=? where id=?双向是加载学⽣时,能够把班级加载上来。
在数据库设计中,一对一关联(One-to-One Relationship)指的是两个表之间的一种关系类型,其中一个表中的每一行数据都与另一个表中的唯一一行数据相关联。
这种关系相对少见,因为通常情况下,如果两个实体之间存在一对一的关系,它们的数据可能会合并到一个表中以简化设计。
一对一关联的实现方式:
1. 共享主键:这是最常见的一对一关系实现方法。
两个表各自有各自的字段集,但其中一个表的主键同时也是另一个表的外键,且这个外键在另一个表中是唯一的(即每个外键值仅对应一个记录)。
例如,假设有一个Employees表和一个EmployeeDetails表,每个员工只有一个详细信息记录。
Employees表有EmployeeID作为主键,而EmployeeDetails表也包含一个EmployeeID字段作为其主键,并且它是Employees表的外键,确保每个员工详情只对应一个员工。
2. 独立主键:即使两个实体间是一对一关系,它们也可以各自拥有不同的主键,然后通过额外的一个唯一标识符来建立关联。
在这种情况下,虽然两个表都有自己的主键,但在关联时,一个表的主键字段会作为另一个表的唯一外键字段。
比如,Users表和UserProfiles表,每个用户在Users表中有一个唯一的UserID,而在UserProfiles表中也有一个独立的ProfileID作为主键,同时还有一个字段UserID_FK作为指向Users表的外键,确保每个用户资料只对应一个用户。
一对一关联表的设计重点在于明确关联条件并保证关联的唯一性,以避免数据冗余和维护数据一致性。
七、⼀对⼀、⼀对多、多对多1、⼀对⼀ 我们以⽤户表 user 和订单表 orders 为例。
设定⼀个订单只能由⼀个⽤户创建,那么由订单到⽤户就是⼀对⼀的关系。
①、创建⽤户表 user 和订单表 orders ⽤户表 user 订单表 orders②、创建项⽬⼯程,导⼊相应的 jar 包③、创建实体类 User.java12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33package com.ys.po;public class User {//⽤户IDprivate int id;//⽤户姓名private String username;//⽤户性别private String sex;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {ername = username;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return"User [id="+ id + ", username="+ username + ", sex="+ sex + "]";}} Orders.java 12 3 4 5 6package com.ys.po; public class Orders { //订单IDprivate int id;6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 private int id;//⽤户IDprivate int userId;//订单数量private String number;//和⽤户表构成⼀对⼀的关系,即⼀个订单只能由⼀个⽤户创建private User user;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getUserId() {return userId;}public void setUserId(int userId) {erId = userId;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public User getUser() {return user;}public void setUser(User user) {er = user;}@Overridepublic String toString() {return"Orders [id="+ id + ", userId="+ userId + ", number="+ number + ", user="+ user + "]";}}④、创建 OrderMapper 接⼝和 OrderMapper.xml ⽂件 由于我们采⽤ Mapper 代理加载 xxxMapper.xml ⽂件,这⾥我们重复⼀下 Mapper 代理所需的条件,接⼝和xml⽂件必须满⾜以下⼏个条件: 1、接⼝必须要和 xml ⽂件同名且在同⼀个包下,也就是说 xml ⽂件中的namespace是接⼝的全类名 2、接⼝中的⽅法名和xml ⽂件中定义的 id ⼀致 3、接⼝输⼊参数类型要和xml 中定义的 parameterType ⼀致 4、接⼝返回数据类型要和xml 中定义的 resultType ⼀致 OrderMapper 接⼝12 3 4 5package one.to.one.mapper; import com.ys.po.Orders;6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28import er;public interface OrdersMapper {/*** ⽅式⼀:嵌套结果* select * from orders o,user u where er_id=u.id and o.id=#{id}* @param orderId* @return*///根据订单ID查询订单和⽤户信息public Orders selectOrderAndUserByOrderID(int orderId);/*** ⽅式⼆:嵌套查询* select * from order WHERE id=1;//得到user_id* select * from user WHERE id=1 //1 是上⼀个查询得到的user_id的值 * @param userID* @return*///根据订单ID得到订单信息(包含user_id)public Orders getOrderByOrderId(int orderId);//根据⽤户ID查询⽤户信息public User getUserByUserId(int userID);} OrderMapper .xml⽂件12345 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="one.to.one.mapper.OrdersMapper"><!--嵌套结果:使⽤嵌套结果映射来处理重复的联合结果的⼦集封装联表查询的数据(去除重复的数据)select * from orders o,user u where er_id=u.id and o.id=#{id}--><select id="selectOrderAndUserByOrderID"resultMap="getOrderAndUser"> select * from orders o,user u where er_id=u.id and o.id=#{id}</select><resultMap type="com.ys.po.Orders"id="getOrderAndUser"><!--id:指定查询列表唯⼀标识,如果有多个唯⼀标识,则配置多个idcolumn:数据库对应的列property:实体类对应的属性名--><id column="id"property="id"/><result column="user_id"property="userId"/><result column="number"property="number"/><!--association:⽤于映射关联查询单个对象的信息property:实体类对应的属性名javaType:实体类对应的全类名--><association property="user"javaType="er"><!--id:指定查询列表唯⼀标识,如果有多个唯⼀标识,则配置多个idcolumn:数据库对应的列property:实体类对应的属性名--><id column="id"property="id"/><result column="username"property="username"/><result column="sex"property="sex"/></association></resultMap><!--⽅式⼆:嵌套查询:通过执⾏另外⼀个SQL映射语句来返回预期的复杂类型 select user_id from order WHERE id=1;//得到user_idselect * from user WHERE id=1//1 是上⼀个查询得到的user_id的值42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 property:别名(属性名) column:列名 --><select id="getOrderByOrderId"resultMap="getOrderMap">select * from order where id=#{id}</select><resultMap type="com.ys.po.Orders"id="getOrderMap"><id column="id"property="id"/><result column="number"property="number"/><association property="userId"column="id"select="getUserByUserId"> </association></resultMap><select id="getUserByUserId"resultType="er">select * from user where id=#{id}</select></mapper>⑤、向 mybatis-configuration.xml 配置⽂件中注册 OrderMapper.xml ⽂件123 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-config.dtd"> <configuration><!-- 加载数据库属性⽂件 --><properties resource="db.properties"></properties><!-- 定义别名 --><typeAliases><!-- mybatis⾃动扫描包中的po类,⾃动定义别名,别名是类名(⾸字母⼤写或⼩写都可以,⼀般⽤⼩写) --><package name="com.ys.po"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><!--dataSource 元素使⽤标准的 JDBC 数据源接⼝来配置 JDBC 连接对象源 --><dataSource type="POOLED"><property name="driver"value="${jdbc.driver}"/><property name="url"value="${jdbc.url}"/><property name="username"value="${ername}"/><property name="password"value="${jdbc.password}"/></dataSource></environment></environments><mappers><!-- 通过OrdersMapper接⼝注册OrdersMapper.xml⽂件,必须保证:接⼝和xml在同⼀个包下,⽽且名字⼀样OrdersMapper接⼝的⽅法名和OrdersMapper.xml⽂件的id⼀样OrdersMapper接⼝的输出输出参数和OrdersMapper.xml⽂件resultType,parameterType类型⼀样--><mapper class="one.to.one.mapper.OrdersMapper"/></mappers></configuration> ⑥、测试1234 5 6 7 8package one.to.one.mapper;import java.io.InputStream;import org.apache.ibatis.session.SqlSession;9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Before;import org.junit.Test;import com.ys.po.Orders;public class OneToOneTest {//定义 SqlSessionSqlSession session =null;@Beforepublic void init(){//定义mybatis全局配置⽂件String resource = "mybatis-configuration.xml";//加载 mybatis 全局配置⽂件InputStream inputStream = OneToOneTest.class.getClassLoader().getResourceAsStream(resource);//构建sqlSession的⼯⼚SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //根据 sqlSessionFactory 产⽣ sessionsession = sessionFactory.openSession();}/*** ⽅式⼀:嵌套结果* select * from orders o,user u where er_id=u.id and o.id=#{id}*/@Testpublic void testSelectOrderAndUserByOrderId(){String statement = "one.to.one.mapper.OrdersMapper.selectOrderAndUserByOrderID"; //创建OrdersMapper对象,mybatis⾃动⽣成mapepr代理对象OrdersMapper orderMapper = session.getMapper(OrdersMapper.class);Orders order = orderMapper.selectOrderAndUserByOrderID(1);System.out.println(order);session.close();}/*** ⽅式⼆:嵌套查询* select * from order WHERE id=1;//得到user_id* select * from user WHERE id=1 //1 是上⼀个查询得到的user_id的值*/@Testpublic void testgetOrderByOrderId(){String statement = "one.to.one.mapper.OrdersMapper.getOrderByOrderId";//创建OrdersMapper对象,mybatis⾃动⽣成mapepr代理对象OrdersMapper orderMapper = session.getMapper(OrdersMapper.class);Orders order = orderMapper.selectOrderAndUserByOrderID(1);System.out.println(order);session.close();}}2、⼀对多 还是以⽤户表 user 和订单表 orders 为例,⼀个⽤户能创建多个订单。
共六种情况,分成两大类,每类有3个第一类: 1对1单向关联一对一,通过外健实现的单向关联是M:1的特例假设一个人只有一个办公室:Person(pid int primary key, pname char(10), office_id int references office(id));Office(oid int primary key, address char(10));CREATE TABLE `person` (`pid` int(11) NOT NULL DEFAULT '0',`pname` char(10) DEFAULT NULL,`office_id` int(11) DEFAULT NULL,PRIMARY KEY (`pid`),KEY `person_office_FK` (`office_id`),CONSTRAINT `person_office_FK` FOREIGN KEY (`office_id`) REFERENCES `office` (`oid`) );CREATE TABLE `office` (`oid` int(11) NOT NULL DEFAULT '0',`address` varchar(20) DEFAULT NULL,PRIMARY KEY (`oid`))对应的类:public class Person {private Integer pid;//主键private String pname;private Office office;//对应的办公室,单向关联public Integer getPid() {return pid;}public void setPid(Integer pid) {this.pid = pid;}public String getPname() {return pname;}public void setPname(String pname) {this.pname = pname;}public Office getOffice() {return office;}public void setOffice(Office office) {this.office = office;}}OFFICE类:public class Office {private Integer oid;//Office id为主键private String address;public Integer getOid() {return oid;}public void setOid(Integer oid) {this.oid = oid;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}}相应的映射文件:Person.hbm.xml<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.po.Person"table="person"><id name="pid"type="ng.Integer"><generator class="increment"></generator></id><property name="pname"type="ng.String"><column name="pname"></column></property><!-- Person类中的office属性对应的列是person表中的office_id,是外键--><!-- unique="true"表示一对一关系 --><many-to-one name="office"column="office_id"unique="true"></many-to-one></class></hibernate-mapping>Office.hbm.xml<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.po.Office"table="office"><id name="oid"type="ng.Integer"><generator class="increment"></generator></id><property name="address" type="ng.String"><column name="address"></column></property></class></hibernate-mapping>测试:public static void main(String[] args) {Session session = HibernateSessionFactory.getSession();Transaction tx = session.beginTransaction();Person p = new Person();p.setPname("张三");Office o = new Office();o.setAddress("北京");p.setOffice(o);//保存的顺序与效率有关session.save(o);session.save(p);mit();session.close();}一对一,通过主健实现的单向关联主健类不能主健生成策略,由关联类负责.假设一个人只有一个办公室:Person(pid int primary key references office(oid), pname char(10));//注意pid既是主健也是外键Office(oid int primary key, address char(10));CREATE TABLE `office` (`oid` int(11) NOT NULL DEFAULT '0',`address` varchar(20) DEFAULT NULL,PRIMARY KEY (`oid`))CREATE TABLE `person` (`pid` int(11) NOT NULL DEFAULT '0',`pname` char(10) DEFAULT NULL,PRIMARY KEY (`pid`),CONSTRAINT `person_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `office` (`oid`))对应的类:与上同。
映射:Person.hbm.xml<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.po.Person"table="person"><!-- 主键生成必须为foreign, 根据关联类生成主键--><id name="pid"type="ng.Integer"><generator class="foreign"><!-- office是Person的属性,表示Person的键值由对应的类Office生成--><param name="property">office</param></generator></id><property name="pname"type="ng.String"><column name="pname"></column></property><!-- Person类中的office属性,1:1关联 --><one-to-one name="office"constrained="true"/></class></hibernate-mapping>Office.hbm.xml无变化<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.po.Office"table="office"><id name="oid"type="ng.Integer"><generator class="increment"></generator></id><property name="address" type="ng.String"><column name="address"></column></property></class></hibernate-mapping>测试:无变化一对一,通过连接表的单向关联这种方案比较少见,设置与通过外健实现的单向关联基本相同数据库表:CREATE TABLE `person` (`pid` int(11) NOT NULL,`pname` char(10) DEFAULT NULL,PRIMARY KEY (`pid`))CREATE TABLE `office` (`oid` int(11) NOT NULL,`address` varchar(20) DEFAULT NULL,PRIMARY KEY (`oid`))关联表CREATE TABLE `person_office` (`oid` int(11) DEFAULT NULL,`pid` int(11) DEFAULT NULL,KEY `FK1` (`pid`),KEY `fk2` (`oid`),CONSTRAINT `fk2` FOREIGN KEY (`oid`) REFERENCES `office` (`oid`),CONSTRAINT `FK1` FOREIGN KEY (`pid`) REFERENCES `person` (`pid`))Person/Office类同上Mapping文件:Person.hbm.xml<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.Person"table="person"><id name="pid"type="ng.Integer"><generator class="increment"></generator></id><property name="pname"type="ng.String"><column name="pname"></column></property><!-- 通过指定关联表映射关系 --><join table="person_office"><key column="pid"></key><many-to-one name="office"column="oid"unique="true"></many-to-one></join></class></hibernate-mapping>Office.hbm.xml<?xml version="1.0"encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.jpioneer.Office"table="office"><id name="oid"type="ng.Integer"><generator class="increment"></generator></id><property name="address"type="ng.String"><column name="address"></column></property></class></hibernate-mapping>测试同上。