19、结果集映射之多对一关联映射

多对一

多个博客对应一个作者
作者

public class Author {
    private Integer id;

    private String username;

    private String password;

    private String email;

    private String bio;

    private String favouriteSection;

}

博客

public class Blog {
    private Integer id;

    private String title;

    private Integer authorId;

    private Author author;
}

省略get和set方法

关联

关联中不同的是你需要告诉 MyBatis 如何加载关联。MyBatis 在这方面会有两种不同的 方式:
- 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。
- 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。首先,然让我们来查看这个元素的属性。所有的你都会看到,它和普通的只由 select 和

resultMap 属性的结果映射不同。

属性描述
property映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的 property JavaBeans 的属性, 那么就会使用。 否则 MyBatis 将会寻找给定名称的字段。 这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射 一 些 东 西 :“ username ”, 或 者 映 射 到 一 些 复 杂 的 东 西 : “address.street.number” 。
javaType一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名的列 表) 。如果你映射到一个 JavaBean,MyBatis 通常可以断定类型。然而,如 javaType 果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证所需的 行为。
jdbcType在这个表格之前的所支持的 JDBC 类型列表中的类型。JDBC 类型是仅仅 需要对插入, 更新和删除操作可能为空的列进行处理。这是 JDBC 的需要, jdbcType 而不是 MyBatis 的。如果你直接使用 JDBC 编程,你需要指定这个类型-但 仅仅对可能为空的值。
typeHandler我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的 typeHandler 类型处理器。 这个属性值是类的完全限定名或者是一个类型处理器的实现, 或者是类型别名。

关联的嵌套查询

属性描述
column来自数据库的类名,或重命名的列标签。这和通常传递给 resultSet.getString(columnName)方法的字符串是相同的。 column 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
select另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面 有一个详细的示例。 select 注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ” {prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起 prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
fetchType可选的。有效值为 lazy和eager。 如果使用了,它将取代全局配置参数lazyLoadingEnabled。

对应的resultMap

<resultMap id="manyToOne2" type="Blog" extends="BaseResultMap">
        <association property="author" javaType="Author" column="author_id" select="selectByPrimaryKey2">
        </association>
    </resultMap>

SQL语句

  <select id="selectByPrimaryKey2" parameterType="java.lang.Integer" resultMap="author">
        SELECT *
        FROM author
        WHERE id = #{id,jdbcType=INTEGER}
    </select>

    <select id="manyToOne2" resultMap="manyToOne2">
        select
        <include refid="Base_Column_List"/>
        from blog
        where id = #{id,jdbcType=INTEGER}
    </select>

我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的 author 属性。

其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单, 但是对于大型数据集合和列表将不会表现很好。

问题就是我们熟知的 “N+1 查询问题”。概括地讲,N+1 查询问题可以是这样引起的:
1. 你执行了一个单独的 SQL 语句来获取结果列表(就是“+1”)。
2. 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。
3. 这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

关联的嵌套结果

属性描述
resultMap这是结果映射的 ID,可以映射关联的嵌套结果到一个合适的对象图中。这 是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到 resultMap 一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分 解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis 让你“链 接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后 面也有一个示例。
columnPrefix当连接多表时,你将不得不使用列别名来避免ResultSet中的重复列名。指定columnPrefix允许你映射列名到一个外部的结果集中。 请看后面的例子。
notNullColumn默认情况下,子对象仅在至少一个列映射到其属性非空时才创建。 通过对这个属性指定非空的列将改变默认行为,这样做之后Mybatis将仅在这些列非空时才创建一个子对象。 可以指定多个列名,使用逗号分隔。默认值:未设置(unset)。
autoMapping如果使用了,当映射结果到当前属性时,Mybatis将启用或者禁用自动映射。 该属性覆盖全局的自动映射行为。 注意它对外部结果集无影响,所以在select or resultMap属性中这个是毫无意义的。 默认值:未设置(unset)。

对应的resultMap

 <resultMap id="BaseResultMap" type="com.lf.entity.Blog">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="title" jdbcType="VARCHAR" property="title"/>
        <result column="author_id" jdbcType="INTEGER" property="authorId"/>
    </resultMap>

    <resultMap id="author" type="com.lf.entity.Author">
        <id column="id" jdbcType="INTEGER" property="id" javaType="int"/>
        <result column="username" jdbcType="VARCHAR" property="username" javaType="string"/>
        <result column="password" jdbcType="VARCHAR" property="password"/>
        <result column="email" jdbcType="VARCHAR" property="email"/>
        <result column="bio" jdbcType="VARCHAR" property="bio"/>
        <result column="favourite_section" jdbcType="VARCHAR" property="favouriteSection"/>
    </resultMap>
    <resultMap id="manyToOne" type="Blog" extends="BaseResultMap">
        <association property="author" javaType="Author" column="author_id" resultMap="author">
        </association>
    </resultMap>

SQL语句

  <select id="manyToOne" resultMap="manyToOne">
        SELECT
            a.id,
            a.username,
            a.email,
            a.bio,
            a.favourite_section,
            b.id,
            b.title,
            b.author_id AS authorId
        FROM author a RIGHT JOIN blog b ON a.id = b.author_id
        WHERE b.id = #{id,jdbcType=INTEGER}
    </select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值