当前位置: 首页 > 科技观察

面试官:请问MyBatis是怎么关联的?

时间:2023-03-19 01:43:34 科技观察

文完本文转载自微信公众号《程序员千语》,作者程序员千语。转载本文请联系程序员倩语公众号。《GitHub:https://github.com/nateshao/ssm/tree/master/115-mybatis-associated-one-many1.关联关系概述为什么要学习MyBatis关联关系?》在实际开发中,对数据库的操作往往会涉及到多个表,这就涉及到面向对象中对象与对象之间的关系。对于多表之间的操作,MyBatis提供了关联映射,通过关联映射可以很好的处理对象之间的关联关系。因此,这里对MyBatis的关系映射进行详细的讲解。在关系型数据库中,多个表之间存在三种关联关系,分别是一对一、一对多和多对多,如下图所示:一对一:介绍主要关系对方的密钥作为两边的外键;一对多:在“多”端,添加“一”端的主键作为外键;多对多:生成一个中间关系表,引入两个表的主键作为外键,两个主键成为联合主键或使用新字段作为主键。在Java中,关系也可以通过对象来描述,如下图所示:2.一对一在现实生活中,一对一的关系非常普遍。比如一个人只能有一张身份证,一张身份证只能对应一个人。那么MyBatis是如何处理图中的一对一关系的呢?前面解释的元素包含一个子元素,MyBatis通过这个元素来处理一对一的关系。关系。在元素中,通常可以配置如下属性:property:指定映射到的实体类对象的属性,对应表字段column:指定表中对应的字段javaType:指定类型映射到实体对象的属性select:指定引入嵌套查询的子SQL语句。该属性用于关联映射中的嵌套查询fetchType:指定关联查询时是否启用延迟加载。该属性有两个属性值,lazy和eager,默认值为lazy(即默认关联映射延迟加载)。MyBatis加载关联关系对象主要有两种方式:嵌套查询和嵌套结果。第一种:嵌套查询是通过执行另一条SQL映射语句返回期望的复杂类型。嵌套查询就是在查询SQL中嵌入一个子查询SQL;嵌套查询会执行多条SQL语句;嵌套查询SQL语句编写起来比较简单;第二种:嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。嵌套结果为嵌套多表查询SQL;嵌套结果只会执行复杂的SQL语句;嵌套结果SQL语句写起来比较复杂;”虽然嵌套查询比较简单,但是嵌套查询执行多条SQL语句的方式对于大的数据集合和列表展示不是很好,因为可能会导致关联的SQL语句成百上千条被执行,极大地消耗数据库performance,降低查询效率,再学习一个trick:MyBatis懒加载配置使用MyBatis懒加载可以在一定程度上降低运行消耗,提高查询效率,MyBatis默认是不开启懒加载的,需要在<核心配置文件中的settings>元素,具体配置方法如下:在映射文件中,元素和元素中已经默认配置了懒加载属性,即默认属性fetchType="lazy"(attributefetchType="eager"表示立即加载),所以在配置文件中启用延迟加载后,就不需要在映射文件中配置了。使用元素进行一对一非常简单关联映射,参考下面两个示例配置即可。代码实现:类型1:SELECT*fromtb_personwhereid=#{id}其二:SELECTp.*,idcard.codefromtb_ppersonp,tb_idcardidcardwherep.card_id=idcard.idandp.id=#{id}Person.java@DatapublicclassPerson{privateIntegerid;privateStringname;privateIntegerage;privateStringsex;privateIdCardcard;//个人关联证书}IdCard.java@DatapublicclassIdCard{privateIntegerid;privateStringcode;}3.一对多开发者接触到更多一对多(或多对一)的关联。例如,一个用户可以有多个订单,多个订单归一个用户所有。那么MyBatis是如何处理这种一对多关系的呢?上面解释的元素包含一个子元素,MyBatis通过这个元素来处理一对多的关系。子元素的属性大部分与元素相同,但它还包含一个特殊的属性——ofType。ofType:ofType属性对应javaType属性,用于指定实体对象中集合类属性包含的元素类型。代码实现:/***一对多*/@TestpublicvoidfindUserTest(){//1。通过工具类生成SqlSession对象SqlSessionsession=MybatisUtils.getSession();//2.查询id为1的用户信息Useruser=session。selectOne("com.nateshao.mapper."+"UserMapper.findUserWithOrders",1);//3、输出查询结果信息System.out.println(user);//4、关闭SqlSessionsession.close();}UserMapper.xmlSELECTu.*,o.idasorders_id,o.numberfromtb_useru,tb_ordersoWHEREu.id=o.user_idandu.id=#{id}User.java@DatapublicclassUser{privateIntegerid;//用户编号privateStringusername;//用户名privateStringaddress;//用户地址privateListordersList;//与用户关联的订单}Orders.java@DatapublicclassOrders{privateIntegerid;//订单idprivateStringnumber;//订单号//关联商品集合信息privateListproductList;}运行结果:User(id=1,username=James,address=Cleveland,ordersList=[Orders(id=1,number=1000011,productList=null),Orders(id=2,number=1000012,productList=null)])4.多对多在实际的项目开发中,多对多的关系也很常见。以订单和商品为例,一个订单可以包含多个商品,而一个商品可以属于多个订单。在数据库中,多对多关系通常由中间表维护。中间表中的orderid作为外键引用order表的id,productid作为外键引用product表的id。在MyBatis中,也可以使用前面介绍的元素来处理多对多关系查询(其用法与一对多关系查询语句基本相同)。MybatisAssociatedTest.java/***多对多*/@TestpublicvoidfindOrdersTest(){//1.通过工具类SqlSessionsession=MybatisUtils.getSession();//2生成一个SqlSession对象。查询id为1的订单中的商品信息Ordersorders=session.selectOne("com.nateshao.mapper."+"OrdersMapper.findOrdersWithPorduct",1);//3,输出查询结果信息System.out.println(orders);//4、关闭SqlSessionsession.close();}OrdersMapper.xmlselecto.*,p.idaspid,p.name,p.pricefromtb_orderso,tb_productp,tb_ordersitemoiWHEREoi.orders_id=o.idandoi.product_id=p.idando.id=#{id}Orders.java@DatapublicclassOrders{privateIntegerid;//订单idprivateStringnumber;//订单号//关联商品集合信息privateListproductList;}Product.java@DatapublicclassProduct{privateIntegerid;//商品idprivateStringname;//商品名称privateDoubleprice;//商品单价privateListorders;//与订单关联的属性}总结:本文首先简单介绍一下开发中涉及的数据表与对象的关系,由此引出关联关系的处理MyBatis框架;然后通过案例,MyBatis框架详细处理了实体对象之间的三种关联关系,通过本章的学习,我们可以理解涉及到的数据表和对象的三种关联关系,并且可以使用MyBatis框架来处理这三种关联关系的查询。MyBatis中的关联查询操作在实际开发中非常常见,掌握这三种关联查询方式有助于提高项目的开发效率。