场景模型:
订单用户模型,暂且从查询订单信息出发,认为是一对一模型
关键解析:
一对一关联查询主要用到了mybatis提供的
association标签表示一对一关联查询映射
该标签主要有如下属性:
property(常用):映射到列结果的字段或属性。
column:数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。 注意:在使用复合主键的时候,你可以使用 column="{prop1=col1,prop2=col2}" 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
javaType(常用):一个 Java 类的完全限定名,或一个类型别名。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
jdbcType:JDBC 类型,所支持的 JDBC 类型参见这个表格之前的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能存在空值的列指定这个类型。
select:用于加载复杂类型属性的映射语句的 ID,它会从 column 属性指定的列中检索数据,作为参数传递给目标 select 语句。 具体请参考下面的例子。注意:在使用复合主键的时候,你可以使用 column="{prop1=col1,prop2=col2}" 这样的语法来指定多个传递给嵌套 Select 查询语句的列名。这会使得 prop1 和 prop2 作为参数对象,被设置为对应嵌套 Select 语句的参数。
resultMap(常用):结果映射的 ID,可以将嵌套的结果集映射到一个合适的对象树中。 它可以作为使用额外 select 语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。这样的 ResultSet 将会将包含重复或部分数据重复的结果集。为了将结果集正确地映射到嵌套的对象树中,MyBatis 允许你 “串联”结果映射,以便解决嵌套结果集的问题。
typeHandler:类型处理器。使用这个属性,你可以覆盖默认的类型处理器。 这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。
notNullColumn:默认情况下,在至少一个被映射到属性的列不为空时,子对象才会被创建。 你可以在这个属性上指定非空的列来改变默认行为,指定后,Mybatis 将只在这些列非空时才创建一个子对象。可以使用逗号分隔来指定多个列。默认值:未设置(unset)。
columnPrefix(常用):当连接多个表时,你可能会不得不使用列别名来避免在 ResultSet 中产生重复的列名。指定 columnPrefix 列名前缀允许你将带有这些前缀的列映射到一个外部的结果映射中。
resultSet:这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔。
foreignColumn:指定外键对应的列名,指定的列将与父类型中 column 的给出的列进行匹配。
autoMapping:如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。注意,本属性对外部的结果映射无效,所以不能搭配 select 或 resultMap 元素使用。默认值:未设置(unset)。
fetchType:可选的。有效值为 lazy 和 eager。 指定属性后,将在映射中忽略全局配置参数 lazyLoadingEnabled,使用属性的值。
注:常用字段已经标注
部分内容来自mybatis官方文档之XML解析器篇https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
代码案例:
订单pojo
@Data
public class Order {
private Integer id;
private Integer userId;
private String desc;
}
用户pojo
@Data
public class User {
private Integer id;
private String name;
}
订单扩展pojo
@Data
public class OrderExt extends Order{
private User user;
@Override
public String toString() {
return "OrderExt{" +
"user=" + user +
"} " + super.toString();
}
}
订单Mapper
@Mapper
public interface OrderMapper {
OrderExt query(Integer id);
}
订单mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.kkbstudy.mapper.OrderMapper">
<resultMap id="orderMap" type="com.example.kkbstudy.pojo.Order">
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
<result property="desc" column="desc" jdbcType="VARCHAR"/>
</resultMap>
<resultMap id="userMap" type="com.example.kkbstudy.pojo.User">
<result property="id" column="user_id" jdbcType="INTEGER"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
</resultMap>
<resultMap id="orderExtMap" type="com.example.kkbstudy.pojo.OrderExt" extends="orderMap">
<association property="user" columnPrefix="user" resultMap="userMap">
</association>
</resultMap>
<select id="query" resultMap="orderExtMap">
select `order`.id,user_id,`desc`,`user`.id as userid,`name` as username from `order`
left join `user` on `order`.user_id = `user`.id
where `order`.id = #{id}
</select>
</mapper>
编写单元测试
@SpringBootTest
class KkbStudyApplicationTests {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserMapper userMapper;
@Test
void test1() {
OrderExt query = orderMapper.query(1);
System.err.println(query);
}
}
输出
OrderExt{user=User(id=2, name=李四)} Order(id=1, userId=2, desc=第一笔订单)
可以看到用户对象和订单对象已经自动封装至订单扩展pojo里。