1、多表查询概念
多表查询是指在一个 SQL 查询中涉及到两个或多个数据库表的数据操作。这种操作通常用于处理表之间的关系,例如一对一、一对多和多对多的关系。
在实际应用中,数据通常存储在多个相关的表中。例如,一个用户可能有多个订单,一个订单可能包含多个商品。通过多表查询,可以同时获取多个表中的数据,从而方便地进行数据分析和处理。
2、多表查询的类型
1. 一对一(One-to-One)
一对一关系是指一个表中的一条记录与另一个表中的一条记录相关联。例如,用户表和用户详情表之间的一对一关系。
2. 一对多(One-to-Many)
一对多关系是指一个表中的一条记录与另一个表中的多条记录相关联。例如,用户表和订单表之间的关系。
3. 多对多(Many-to-Many)
多对多关系是指一个表中的多条记录与另一个表中的多条记录相关联。这种关系通常通过第三个中间表来实现。例如,学生表和课程表之间的关系。
3、多表查询的实体类
在进行多表查询时,实体类设计至关重要,因为它直接影响到数据的映射、查询的性能以及代码的可维护性。实体类设计需要考虑到数据库表之间的关系,包括一对一、一对多和多对多的关系
多表结果实体类设计小技巧
对一,属性中包含对方对象
对多,属性中包含对方对象集合
举例:现在有两个表,一个订单表,一个客户表
需求1(对一):根据id查询订单信息和订单对应的客户
需求2(对多):查询所有客户信息以及客户对应的订单信息
4、对一查询
以上面第一个需求为例:根据id查询订单信息和订单对应的客户
第一步:准备数据库
CREATE TABLE `t_customer` (`customer_id` INT NOT NULL AUTO_INCREMENT, `customer_name` CHAR(100), PRIMARY KEY (`customer_id`) );
CREATE TABLE `t_order` ( `order_id` INT NOT NULL AUTO_INCREMENT, `order_name` CHAR(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 ('o3', '1');
第二步:准备实体
order
customer
第三步:准备mapper接口和配置文件
OrderMapper接口
public interface OrderMapper {
Order selectOrderWithCustomer(Integer orderId);
}
配置文件
<!-- 创建resultMap实现“对一”关联关系映射 -->
<!-- id属性:通常设置为这个resultMap所服务的那条SQL语句的id加上“ResultMap” -->
<!-- type属性:要设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
<resultMap id="selectOrderWithCustomerResultMap" type="order">
<!-- 先设置Order自身属性和字段的对应关系 -->
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
<!-- 使用association标签配置“对一”关联关系 -->
<!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
<!-- javaType属性:一的一端类的全类名 -->
<association property="customer" javaType="customer">
<!-- 配置Customer类的属性和字段名之间的对应关系 -->
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
</association>
</resultMap>
<!-- Order selectOrderWithCustomer(Integer orderId); -->
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">
SELECT order_id,order_name,c.customer_id,customer_name
FROM t_order o
LEFT JOIN t_customer c
ON o.customer_id=c.customer_id
WHERE o.order_id=#{orderId}
</select>
第四步:Mybatis全局注册Mapper文件
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
<!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
<mapper resource="mappers/OrderMapper.xml"/>
</mappers>
在“对一”关联关系中,我们的配置比较多,但是关键词就只有:association和javaType
5、对多查询
上面第二个需求:查询客户和客户关联的订单信息!
CustomerMapper接口
public interface CustomerMapper {
Customer selectCustomerWithOrderList(Integer customerId);
}
Customer配置文件
<!-- 配置resultMap实现从Customer到OrderList的“对多”关联关系 -->
<resultMap id="selectCustomerWithOrderListResultMap"
type="customer">
<!-- 映射Customer本身的属性 -->
<id column="customer_id" property="customerId"/>
<result column="customer_name" property="customerName"/>
<!-- collection标签:映射“对多”的关联关系 -->
<!-- property属性:在Customer类中,关联“多”的一端的属性名 -->
<!-- ofType属性:集合属性中元素的类型 -->
<collection property="orderList" ofType="order">
<!-- 映射Order的属性 -->
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
</collection>
</resultMap>
<!-- Customer selectCustomerWithOrderList(Integer customerId); -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
FROM t_customer c
LEFT JOIN t_order o
ON c.customer_id=o.customer_id
WHERE c.customer_id=#{customerId}
</select>
Mybatis全局注册Mapper文件
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
<!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
<mapper resource="mappers/OrderMapper.xml"/>
<mapper resource="mappers/CustomerMapper.xml"/>
</mappers>
测试
@Test
public void testRelationshipToMulti() {
CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
// 查询Customer对象同时将关联的Order集合查询出来
Customer customer = customerMapper.selectCustomerWithOrderList(1);
log.info("customer.getCustomerId() = " + customer.getCustomerId());
log.info("customer.getCustomerName() = " + customer.getCustomerName());
List<Order> orderList = customer.getOrderList();
for (Order order : orderList) {
log.info("order = " + order);
}
}