1. 关联关系概述
在关系型数据库中,多表之间存在着三种关联关系,分别为一对一、一对多和多对多
关系 | 说明 |
---|---|
一对一 | 在任意一方引入对方主键作为外键 |
一对多 | 在“多”的一方,添加“一”的一方的主键作为外键 |
多对多 | 产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新的字段作为主键 |
在Java中,通过对象也可以进行关系描述
关系 | 说明 |
---|---|
一对一的关系 | 就是在本类中定义对方类型的对象,如A类中定义B类类型的属性b, B类中定义A类类型的属性a |
一对多的关系 | 就是一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a |
多对多的关系 | 在A类中定义B类类型的集合,在B类中定义A类类型的集合 |
2. 一对一关系
在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人。
在07. MyBatis的核心配置所讲解的< resultMap>元素中,包含了一个< association>子元素,MyBatis就是通过该元素来处理一对一关联关系的。
在< association>元素中的属性
属性 | 作用 |
---|---|
property | 指定映射到的实体类对象属性,与表字段一一对应 |
column | 指定表中对应的字段 |
javaType | 指定映射到实体对象属性的类型 |
select | 定引入嵌套查询的子SQL语句,该属性用于关联映射中的嵌套查询 |
1.两种使用方式
<!-- 方式1:嵌套查询 -->
<association property="card" column="card_id"
javaType="IdCard"
select="com.clarence.mapper.IdCardMapper.findCodeById">
</association>
<!-- 方式2:嵌套结果 -->
<association property="card"
javaType="com.clarence.po.IdCard" >
<id property="id" column="card_id"></id>
<result property="code" column="code" />
</association>
1.嵌套查询
示例代码
1.持久化类
public class IdCard {
private Integer id;
private String code;
//省略getter和setter
}
public class Person {
private Integer id;
private String name;
private String age;
private String sex;
private IdCard Card;
//省略getter和setter
}
2.IdCardMapper.xml文件配置
<mapper namespace="com.clarence.mapper.IdCardMapper">
<select id="findCodeById" parameterType="Integer"
resultType="IdCard">
SELECT * from tb_idcard where id=#{id}
</select>
</mapper>
3.PersonMapper.xml文件配置
<mapper namespace="com.clarence.mapper.PersonMapper">
<select id="findPersonById" parameterType="Integer"
resultMap="IdCardWithPersonResult">
select * from tb_person where id=#{id}
</select>
<resultMap type="Person" id="IdCardWithPersonResult">
<id property="id" column="id" />
<result property="name" column="name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<!-- 方式1:嵌套查询 -->
<!-- 一对一关系:association使用select属性引入另一条SQL -->
<association property="card" column="card_id"
javaType="IdCard"
select="com.clarence.mapper.IdCardMapper.findCodeById">
</association>
</resultMap>
</mapper>
4.MyBatis-config.xml配置无特别变化,只需引入两个mapper
5.测试类
@Test
public void findPersonByIdTest() {
// 1.生产SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 2.嵌套查询id为1的人的信息
Person person = sqlSession.selectOne(
"com.clarence.mapper.PersonMapper.findPersonById", 1);
System.out.println(person);
sqlSession.close();
}
运行结果
2.嵌套结果
1.只需更改PersonMapper的查询语句和映射结果
1.1 sql改写
select p.*,idcard.code from tb_person p,tb_idcard idcard
where p.card_id = idcard.id and p.id= #{id}
1.2 association改写
<association property="card"
javaType="IdCard" >
<id property="id" column="card_id"></id>
<result property="code" column="code" />
</association>
运行结果
在使用MyBatis嵌套查询方式进行MyBatis关联查询映射时,使用MyBatis的延迟加载在一定程度上可以降低运行消耗并提高查询效率。MyBatis默认没有开启延迟加载,需要在核心配置文件mybatis-config.xml中的< settings>元素内进行配置
<settings>
<!-- 打开延迟加载 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 将积极加载改为消息加载,即按需加载 -->
<setting name="aggressiveLazyLoading" value="false" />
</settings>
在映射文件中,MyBatis关联映射的< association>元素和< collection>元素中都已默认配置了延迟加载属性,即默认属性fetchType=“lazy”(属性fetchType="eager"表示立即加载),所以在配置文件中开启延迟加载后,无须在映射文件中再做配置
3. 一对多关系
与一对一的关联关系相比,开发人员接触更多的关联关系是一对多(或多对一)
例如一个用户可以有多个订单,同时多个订单归一个用户所有
在07. MyBatis的核心配置所讲解的< resultMap>元素中,包含了一个< collection>子元素,MyBatis就是通过该元素来处理一对多关联关系的。< collection>子元素的属性大部分与< association>元素相同,但其还包含一个特殊属性——ofType。ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型
示例代码
1.持久化类
public class User {
private Integer id;
private String username;
private String address;
private List<Orders> ordersList;
}
public class Orders {
private Integer id;
private String number;
}
2.UserMapper.xml配置
<mapper namespace="com.clarence.mapper.UserMapper">
<select id="findUserWithOrders" parameterType="Integer"
resultMap="UserWithOrdersResult">
select u.*,o.id as orders_id,o.number
from tb_user u, tb_orders o
where u.id = o.user_id
and u.id = #{id}
</select>
<resultMap type="User" id="UserWithOrdersResult">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
<!-- 一对多关系
ofType 表示属性集合中元素的类型,List<Orders>属性即Orders类
-->
<collection property="ordersList" ofType="Orders">
<id property="id" column="orders_id"/>
<result property="number" column="number"/>
</collection>
</resultMap>
</mapper>
3.测试类
@Test
public void findUserTest() {
// 1.生产SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 2.嵌套查询id为1的用户信息
User user = sqlSession.selectOne(
"com.clarence.mapper.UserMapper.findUserWithOrders", 1);
System.out.println(user);
sqlSession.close();
}
运行结果
4. 多对多关系
在实际项目开发中,多对多的关联关系也是非常常见的。以订单和商品为例,一个订单可以包含多种商品,而一种商品又可以属于多个订单,订单和商品就属于多对多的关联关系
在数据库中,多对多的关联关系通常使用一个中间表来维护,中间表中的订单id作为外键参照订单表的id,商品id作为外键参照商品表的id
示例代码
1.持久化类
public class Product {
private Integer id;
private String name;
private Double price;
private List<Orders> orders;
}
Orders类中添加
private List<Product> productList;
2.OrderMapper.xml文件配置
<mapper namespace="com.clarence.mapper.OrdersMapper">
<!-- 多对多嵌套查询 -->
<select id="findOrderWithProduct" parameterType="Integer"
resultMap="OrdersWithProductResult">
select * from tb_orders where id=#{id}
</select>
<resultMap type="Orders" id="OrdersWithProductResult">
<id property="id" column="id" />
<result property="number" column="number" />
<collection property="productList" column="id"
ofType="Product"
select="com.clarence.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
</mapper>
3.ProductMapper.xml文件配置
<mapper namespace="com.clarence.mapper.OrdersMapper">
<!-- 多对多嵌套查询 -->
<select id="findOrderWithProduct" parameterType="Integer"
resultMap="OrdersWithProductResult">
select * from tb_orders where id=#{id}
</select>
<resultMap type="Orders" id="OrdersWithProductResult">
<id property="id" column="id" />
<result property="number" column="number" />
<collection property="productList" column="id"
ofType="Product"
select="com.clarence.mapper.ProductMapper.findProductById">
</collection>
</resultMap>
</mapper>
4. 测试类
@Test
public void findOrdersTest() {
// 1.生产SqlSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 2.嵌套查询id为1的用户信息
Orders orders = sqlSession.selectOne(
"com.clarence.mapper.OrdersMapper.findOrderWithProduct", 1);
System.out.println(orders);
sqlSession.close();
}
运行结果
当然多对多也可以使用嵌套结果方式 ~,但我不熟练嵌套查询语句 ~,所以就放弃了 ~
来源:CSDN
作者:Caris.
链接:https://blog.csdn.net/qq_39666910/article/details/104392339