MyBatis-多表查询
MyBatis-多表查询
-
多表查询的sql语句仍然需要我们自己编写(连接查询)
-
自己设计存储数据的实体类,承接多个表的查询结果
-
使用自定义结果集映射(resultMap)
多表之间的关系
在数据库中,多表之间存在多个关系:
- 一对一
- 一对多
- 多对多
但在实体类中,多实体类中只看单向的关系,比如:
一个客户对应多个订单,就是对多的关系
一个订单对应多个客户,就是对一的关系
在微头条项目中,我们学会了值对象(VO),使用这种对象可以接受数据库多表查询的结果
而现在,我们解决多表查询的方法是,将一个实体类对象作为属性放到另一个实体类中
如果为对一关系,比如上面的例子,就在订单实体类中存放一个客户实体类对象作为属性
如果为对多关系,比如上面的例子,就在客户实体类中存放一个类型为客户实体类的List集合作为属性
在实际开发中,只有在查询所需时才修改实体类,并且修改时只做一个实体类的修改,其对应的不需要考虑
对一映射
pojo
@Data
public class Customer {
private int customerId;
private String customerName;
}
@Data
public class Order {
private Integer orderId;
private String orderName;
private int customerId;
private Customer customer;
}
mapper接口
public interface OrderMapper {
Order queryOrderById(Integer id);
}
mapper.xml
使用resultMap标签为查询结果做映射
通过association,即可为对象中的对象属性做映射,在标签中套用子标签即可赋值对象属性的属性
- property属性:属性名
- javaType:类的全限定符或类别名
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaobai.mapper.OrderMapper">
<resultMap id="orderMap" type="order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
<!--给对象赋值-->
<association property="customer" javaType="customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
</association>
</resultMap>
<select id="queryIdby" resultMap="orderMap">
select * from t_order tor join t_customer tur
on tor.customer_id = tur.customer_id
where tor.order_id = #{id}
</select>
</mapper>
对多映射
pojo
public class Customer {
private int customerId;
private String customerName;
private List<Order> orders;
}
public class Order {
private Integer orderId;
private String orderName;
private int customerId;
private Customer customer;
}
mapper接口
public interface CustomerMapper {
List<Customer> selectAllCustomer();
}
mapper.xml
使用resultMap标签为查询结果做映射
通过collection,即可为对象中的List集合属性做映射,在标签中套用子标签即可赋值集合中对象属性的属性
- property属性:属性名
- ofType:集合的泛型,也就是集合中的对象的数据类型
注:我们在进行两个表的相互映射过程中,只考虑单向的映射关系,比如在这个例子中,我们在List集合中的order对象中也存在customer对象,但不要映射此对象,否则会出现映射循环
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaobai.mapper.CustomerMapper">
<resultMap id="customerMapper" type="customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<!--映射集合对象-->
<collection property="orders" ofType="order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
</collection>
</resultMap>
<select id="selectAllCustomer" resultMap="customerMapper">
select *
from t_order tor join t_customer tur
on tor.customer_id = tur.customer_id
</select>
</mapper>
autoMapppingBehavior
配置mybatis-config.xml的setting标签,开启此功能,指定 MyBatis 应如何自动映射列到字段或属性
注:仅仅映射result也就是常规列的内容,主键列不会自动映射
value属性有三个选项值:
- NONE:关闭自动映射
- PARTIAL:部分映射
- FULL:深度映射
默认情况下,resultMap只会映射一层result的标签,也就是说,不支持对一和对多映射对象属性(集合属性)
<settings>
<!-- 开启MyBaits日志输出 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启MyBaits驼峰式映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启MyBatis自动映射列到字段或属性(单一层次)-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
value值更改为FULL,则开启深层次映射
<settings>
<!-- 开启MyBaits日志输出 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启MyBaits驼峰式映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启MyBatis自动映射列到字段或属性(单一层次)-->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
<resultMap id="customerMapper" type="customer">
<id column="customer_id" property="customerId"/>
<!-- <result column="customer_name" property="customerName"/>-->
<!--映射集合对象-->
<collection property="orders" ofType="order">
<id column="order_id" property="orderId"/>
<!-- <result column="order_name" property="orderName"/>-->
<!-- <result column="customer_id" property="customerId"/>-->
</collection>
</resultMap>
在进行深层次映射时,我不禁想到一个问题,深层次映射是否会导致映射循环
但仔细阅读代码发现,深层次映射也只是根据collection和association标签来进行映射
在resultMap中,当发现对象属性(集合属性)则不进行自动映射,进而寻找collection(association)标签
一个标签代表着一个对象(一个集合),这样就完美的避免了映射循环的问题