MyBatis的关联映射

一、概述

在关系型数据库中,多表之间存在着三种关联关系,分别为一对一、一对多和多对多。

这三种关联关系的具体说明如下。

●一对一:在任意一方引入对方主键作为外键。

●一对多:在"多"的一方,添加"一"的一方的主键作为外键。

●多对多:产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新

的字段作为主键。

通过数据库中的表可以描述数据之间的关系,同样,在Java中,通过对象也可以进行关系

描述,如图所示。

在图中,关系的描述:

  • 一对一的关系:就是在本类中定义对方类型的对象,如A类中定义B类类型的属性b,B类中定义A类类型的属性a。
  • 一对多的关系:就是一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a。
  • 多对多的关系:在A类中定义B类类型的集合,在B类中定义A类类型的集合。

二、一对多

与一对一的关联关系相比,开发人员接触更多的关联关系是一对多( 或多对一)。例如一个用户可以有多个订单,同时多个订单归一个用户所有。用户和订单的关联关系如图所示。那么使用MyBatis 是怎么处理这种一对多关联关系的呢?我们需要借助<resultMap>元素,它包含了一个<collection>子元素, MyBatis就是通过该元素来处理一对多关联关系的。<collection> 子元素的属性大部分与<association>元素相同,但其还包含一个特殊属性一ofType。ofType 属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型。

<collection>元素的使用也非常简单,同样可以参考如下两种示例进行配置,具体代码如下。

复制代码
<!--方式一:嵌套查询-->
<collection property="ordersList" column="id" ofType="com. itheima. po. Orders "
   select="com. itheima.mapper.OrdersMapper. selectOrders"/>
<!--方式二:嵌套结果-->
<collection property="ordersList" ofType=" com.itheima.po.Orders">
   <id property="id" column="orders id" />
   <result property= " number" column=" number" />
</collection>

三、例子

现有商品表和商品类别表,如图所示。

我们先在数据库中创建两张表,接着创建他们的持久化类(set,get,toString)。然后我们创建映射文件,最后编写测试类。

映射文件:

复制代码
  <!-- namespace表示命名空间-->
  <mapper namespace="com.qcby.mapper.ProductMapper">
  
  <!--一对多:查看某一商品及其关联的类别信息。注意:当关联查询出的列名相同,则需要使用别名区分-->
	<select id="findProductWithCategory" parameterType="String"  resultMap="ProductWithCategoryResult">
		select product.* 
		from product,category 
		where product.typeid=category.id 
		and category.typename =#{typename}
	</select>
	<resultMap type="com.qcby.po.Product" id="ProductWithCategoryResult">
		<id property="id" column="id"/>
		<result property="goodsname" column= "goodsname"/>
		<result property="price" column="price"/>
		<result property="typeid" column="typeid"/>
		<!--一对多关联映射: collectionofType表示属性集合中元素的类型,List<Category>属性即Category类-->
		<collection property="cList" ofType ="com.qcby.po.Category">
			<id property="id" column="id"/>
			<result property="typename" column="typename"/>
		</collection>
    </resultMap>
   </mapper>

在映射文件中,我们使用了MyBatis嵌套结果的方式定义了一个根据商品类别查询商品信息的select语句。因为返回的用户对象中,包含Category集合对象属性,所以需要手动编写结果映射信息。

测试类:

复制代码
@Test
	public void findProductTest() {
		//1、生成sqlsession对象
		SqlSession sqlSession = MybatisUtils.getSession();
		//2、查询类别为白色家电的商品
		String typename = "黑色家电";
		List<Product> product = sqlSession.selectList("com.qcby.mapper.ProductMapper.findProductWithCategory", typename);
		//3、输出查询结果
		for (Product product2 : product) {
			  System.out.println("商品ID: " + product2.getId());
			  System.out.println("商品名称: " + product2.getGoodsname());
			  System.out.println("商品价格: " + product2.getPrice());
			  System.out.println("商品类别ID: " + product2.getTypeid());
		}
		//4、提交事务
		sqlSession.commit();
		//5、关闭sqlsession
		sqlSession.close();
	}
相关推荐
独泪了无痕4 小时前
探索Pinyin4j-Java中的拼音转换利器
java·后端
道尔柯南5 小时前
C++ string 类详解:从常用接口到深拷贝,彻底掌握字符串处理
android·java·c++
kingx36 小时前
Bugku 3122 谷歌小恐龙题解:纯离线逆向 Vault 的 AES-GCM 加密资源(附 Python 解密器)
java·逆向·ctf·bugku·aes-gcm
DevOpenClub8 小时前
职教高考控制线 API:招生类别枚举、筛选与空分数含义
java·数据库·高考
露天赏雪9 小时前
第3篇:Sentinel熔断降级实战:大模型接口抖动时的服务兜底方案
java·开发语言·人工智能·spring boot·spring·servlet·sentinel
天天被压力10 小时前
【A股分钟级高频数据完全手册 #06】北交所分钟级数据接口:京市股票Pro版最新分时
java·人工智能·python
天天被压力10 小时前
【A股分钟级高频数据完全手册 #05】指数历史分钟数据接口:Pro版沪深指数分时回放
java·人工智能·python
captain37610 小时前
▲统一功能——DispatcherServlet源码分析
java·spring·java-ee·log4j·maven
金銀銅鐵10 小时前
JDK 21 中 List.of 的实现细节:从 List12 到 ListN
java·后端·ai编程
yeccheng12 小时前
MySQL 索引超详解:从底层 B+ 树到面试高频考点
java·开发语言·jvm·mysql·面试