Mybatis多表查询
多表查询涉及到至少两个表,有两种情况:多对一和一对多
以客户表和订单表为例:
一对多:一个订单对应一个客户
多对一:一个客户对应多个订单
那么在设计实体类时,对一的情况是在订单实体类中包括客户的实体类对象
对多的情况是在 客户实体类中包括订单对象的集合
案例:查询1号订单,已经该订单所对应的客户
-
准备数据库表
CREATE TABLE `t_customer`( `customer_id` INT NOT NULL AUTO_INCREMENT, `customer_name` VARCHAR(100), PRIMARY KEY (`customer_id`) ) CREATE TABLE `t_order`( `order_id` INT NOT NULL AUTO_INCREMENT, `order_name` VARCHAR(100), `customer_id` INT, PRIMARY KEY (`order_id`) ) INSERT INTO `t_customer`(`customer_name`) VALUES('c01'); INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1'); INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1'); INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1');
-
准备实体类
这个案例主要是查询订单,其次查询订单对应的客户,也就是一对多,那么在设计实体类时,订单的属性中有客户的实体类对象
@Data public class Order { private Integer orderId; private String orderName; private Integer customerId; private Customer customer; }
@Data public class Customer { private Integer customerId; private String customerName; }
-
查询语句
<mapper namespace="com.ztone.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="queryOrderById" resultMap="orderMap"> select * from t_order tor join t_customer tcu on tor.customer_id = tcu.customer_id where order_id = #{id} </select> </mapper>
public interface OrderMapper { Order queryOrderById(Integer id); }
这里经过sql的查询返回的是 Order对象,而Order对象中还包括 Customer对象
如果还使用 resultType 接收返回值,就没办法把customer的信息接收到,所以使用 resultMap来自定义映射关系。
之前介绍过,resultMap接收主键用 id 标签,接收 其他列用result标签。
如果要映射对象和列的关系,就使用 association 标签
这个标签的属性
-
property 表示对象的属性,也就是在Order类中的 customer属性
-
javaType 表示对象的类型,是类的全限定符,这里用了别名
在这个标签内,可以使用 id 和result 来映射 customer对象的属性
-
上面的案例是一对多,映射时使用 association 标签,当多对一的情况与之类似,使用的标签是 collection
案例:查询所有客户,以及客户对应的所有订单
Customer类修改如下
@Data
public class Customer {
private Integer customerId;
private String customerName;
private List<Order> orderList;
}
添加了Order的集合,用来存放客户对应的多个订单
<mapper namespace="com.ztone.mapper.CustomerMapper">
<resultMap id="customerMap" type="customer">
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<collection property="orderList" ofType="order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<result column="customer_id" property="customerId"/>
</collection>
</resultMap>
<select id="queryAllCustomer" resultMap="customerMap">
select * from t_customer tcu join t_order tor on tcu.customer_id = tor.customer_id
</select>
</mapper>
在resultMap的属性中,虽然返回的是集合,但是 type依然是集合的泛型
在标签中,使用 id 和 result 分别表示 主键和其他列
使用 collection 标签用来映射集合
-
property 客户类中的订单集合属性
-
ofType 客户类中的订单集合属性的泛型的全限定符
在标签中依然是 用id 和 result 进行属性映射
需要注意的是,只映射与该功能相关的属性即可,比如上个案例中,在订单类中有 客户类的属性,这里不需要再collection 标签中映射。
在上面两个案例中,有很多result 标签,有一个设置项可以帮我们自动映射这些result标签的列名属性名
autoMappingBehavior ,他有三个值
-
NONE 关闭自动映射
-
PARTIAL 只会自动映射没有定义嵌套结果映射的字段 【默认值】
-
FULL 自动映射所有结果集
使用自动映射的前提是 属性名和列名相同 或者 开启了驼峰命名映射功能
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="autoMappingBehavior" value="FULL"/>
</settings>