场景模型:

订单用户模型,暂且从查询订单信息出发,认为是一对一模型

关键解析:

一对一关联查询主要用到了mybatis提供的标签
association标签表示一对一关联查询映射
该标签主要有如下属性:

  1. property(常用):映射到列结果的字段或属性。
  2. column:数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。 注意:在使用复合主键的时候,你可以使用 column="{prop1=col1,prop2=col2}" 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
  3. javaType(常用):一个 Java 类的完全限定名,或一个类型别名。 如果你映射到一个 JavaBeanMyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
  4. jdbcTypeJDBC 类型,所支持的 JDBC 类型参见这个表格之前的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能存在空值的列指定这个类型。
  5. select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句。 具体请参考下面的例子。注意:在使用复合主键的时候,你可以使用 column="{prop1=col1,prop2=col2}" 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
  6. resultMap(常用):结果映射的 ID,可以将嵌套的结果集映射到一个合适的对象树中。 它可以作为使用额外 select 语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。这样的 ResultSet 将会将包含重复或部分数据重复的结果集。为了将结果集正确地映射到嵌套的对象树中,MyBatis 允许你 “串联”结果映射,以便解决嵌套结果集的问题。
  7. typeHandler:类型处理器。使用这个属性,你可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。
  8. notNullColumn:默认情况下,在至少一个被映射到属性的列不为空时,子对象才会被创建。 你可以在这个属性上指定非空的列来改变默认行为,指定后,Mybatis 将只在这些列非空时才创建一个子对象。可以使用逗号分隔来指定多个列。默认值:未设置(unset)。
  9. columnPrefix(常用):当连接多个表时,你可能会不得不使用列别名来避免在 ResultSet 中产生重复的列名。指定 columnPrefix 列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中。
  10. resultSet:这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
  11. foreignColumn:指定外键对应的列名,指定的列将与父类型中 column 的给出的列进行匹配。
  12. autoMapping:如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。注意,本属性对外部的结果映射无效,所以不能搭配 select resultMap 元素使用。默认值:未设置(unset)。
  13. fetchType:可选的。有效值为 lazy eager 指定属性后,将在映射中忽略全局配置参数 lazyLoadingEnabled,使用属性的值。

注:常用字段已经标注
部分内容来自mybatis官方文档之XML解析器篇https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

代码案例:

订单pojo

  1. @Data
  2. public class Order {
  3. private Integer id;
  4. private Integer userId;
  5. private String desc;
  6. }

用户pojo

  1. @Data
  2. public class User {
  3. private Integer id;
  4. private String name;
  5. }

订单扩展pojo

  1. @Data
  2. public class OrderExt extends Order{
  3. private User user;
  4. @Override
  5. public String toString() {
  6. return "OrderExt{" +
  7. "user=" + user +
  8. "} " + super.toString();
  9. }
  10. }

订单Mapper

  1. @Mapper
  2. public interface OrderMapper {
  3. OrderExt query(Integer id);
  4. }

订单mapper.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.kkbstudy.mapper.OrderMapper">
  4. <resultMap id="orderMap" type="com.example.kkbstudy.pojo.Order">
  5. <result property="id" column="id" jdbcType="INTEGER"/>
  6. <result property="userId" column="user_id" jdbcType="INTEGER"/>
  7. <result property="desc" column="desc" jdbcType="VARCHAR"/>
  8. </resultMap>
  9. <resultMap id="userMap" type="com.example.kkbstudy.pojo.User">
  10. <result property="id" column="user_id" jdbcType="INTEGER"/>
  11. <result property="name" column="name" jdbcType="VARCHAR"/>
  12. </resultMap>
  13. <resultMap id="orderExtMap" type="com.example.kkbstudy.pojo.OrderExt" extends="orderMap">
  14. <association property="user" columnPrefix="user" resultMap="userMap">
  15. </association>
  16. </resultMap>
  17. <select id="query" resultMap="orderExtMap">
  18. select `order`.id,user_id,`desc`,`user`.id as userid,`name` as username from `order`
  19. left join `user` on `order`.user_id = `user`.id
  20. where `order`.id = #{id}
  21. </select>
  22. </mapper>

编写单元测试

  1. @SpringBootTest
  2. class KkbStudyApplicationTests {
  3. @Autowired
  4. private OrderMapper orderMapper;
  5. @Autowired
  6. private UserMapper userMapper;
  7. @Test
  8. void test1() {
  9. OrderExt query = orderMapper.query(1);
  10. System.err.println(query);
  11. }
  12. }

输出

  1. OrderExt{user=User(id=2, name=李四)} Order(id=1, userId=2, desc=第一笔订单)

可以看到用户对象和订单对象已经自动封装至订单扩展pojo里。