MyBatis-多表查询
多表之间的关系 在数据库中,多表之间存在多个关系:
但在实体类中,多实体类中只看单向的关系,比如:
一个客户对应多个订单,就是对多 的关系
一个订单对应多个客户,就是对一 的关系
在微头条项目中,我们学会了值对象(VO),使用这种对象可以接受数据库多表查询的结果
而现在,我们解决多表查询的方法是,将一个实体类对象作为属性放到另一个实体类中
如果为对一关系,比如上面的例子,就在订单实体类中存放一个客户实体类对象作为属性
如果为对多关系,比如上面的例子,就在客户实体类中存放一个类型为客户实体类的List集合作为属性
在实际开发中,只有在查询所需时才修改实体类,并且修改时只做一个实体类的修改,其对应的不需要考虑
对一映射 pojo 1 2 3 4 5 @Data public class Customer { private int customerId; private String customerName; }
1 2 3 4 5 6 7 @Data public class Order { private Integer orderId; private String orderName; private int customerId; private Customer customer; }
mapper接口 1 2 3 public interface OrderMapper { Order queryOrderById (Integer id) ; }
mapper.xml 使用resultMap标签为查询结果做映射
通过association,即可为对象中的对象属性做映射,在标签中套用子标签即可赋值对象属性的属性
property属性:属性名
javaType:类的全限定符或类别名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?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 1 2 3 4 5 6 public class Customer { private int customerId; private String customerName; private List<Order> orders; }
1 2 3 4 5 6 public class Order { private Integer orderId; private String orderName; private int customerId; private Customer customer; }
mapper接口 1 2 3 public interface CustomerMapper { List<Customer> selectAllCustomer () ; }
mapper.xml 使用resultMap标签为查询结果做映射
通过collection,即可为对象中的List集合属性做映射,在标签中套用子标签即可赋值集合中对象属性的属性
property属性:属性名
ofType:集合的泛型,也就是集合中的对象的数据类型
注:我们在进行两个表的相互映射过程中,只考虑单向的映射关系,比如在这个例子中,我们在List集合中的order对象中也存在customer对象,但不要映射此对象,否则会出现映射循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?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的标签,也就是说,不支持对一和对多映射对象属性(集合属性)
1 2 3 4 5 6 7 8 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="autoMappingBehavior" value ="PARTIAL" /> </settings >
value值更改为FULL,则开启深层次映射
1 2 3 4 5 6 7 8 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="autoMappingBehavior" value ="FULL" /> </settings >
1 2 3 4 5 6 7 8 9 10 <resultMap id ="customerMapper" type ="customer" > <id column ="customer_id" property ="customerId" /> <collection property ="orders" ofType ="order" > <id column ="order_id" property ="orderId" /> </collection > </resultMap >
在进行深层次映射时,我不禁想到一个问题,深层次映射是否会导致映射循环
但仔细阅读代码发现,深层次映射也只是根据collection和association标签来进行映射
在resultMap中,当发现对象属性(集合属性)则不进行自动映射,进而寻找collection(association)标签
一个标签代表着一个对象(一个集合),这样就完美的避免了映射循环的问题
嵌套选择 <association> 标签中的 select 和 column 属性是 MyBatis 提供的一种强大而灵活的功能,它允许你通过指定另一个 Mapper 接口的方法来加载关联对象。这种机制被称为 嵌套选择(Nested Select) ,它是 MyBatis 结果映射的一部分,用于处理复杂的数据关系。
<association> 标签的作用
property :指定要映射到的结果对象的属性名称。
javaType :指定该属性对应的 Java 类型。
column :指定从主查询结果集中提取的列名或别名,作为参数传递给子查询。
select :指定一个查询语句的 ID,通常是另一个 Mapper 接口中的方法名,用来执行子查询并填充关联对象。
1 2 3 4 <resultMap id="NodeVoResult" type="NodeVo" > <association property="region" javaType="Region" column="regionId" select="com.dkd.manage.mapper.RegionMapper.selectRegionById" /> <association property="partner" javaType="Partner" column="partnerId" select="com.dkd.manage.mapper.PartnerMapper.selectPartnerById" /> </resultMap>
在这里,mybatis会通过外键regionId和partnerId分别调用两个mapper的方法单独发送请求查询,并通过resultmap进行对象的映射
这种方式很相似在Service层调用多个Dao查询多个表,然后在Service层组织Vo返回,这里只不过是将组织Vo这一步骤放在Dao层,利用Mybatis的特性来解决