Mybatis第三部分

Posted by Cfeng on April 16, 2019

学习视频来自黑马程序员,感谢!

Mybatis输入映射

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型

传递pojo的包装对象

1.需求
完成用户信息的综合查询,需要传入查询条件很复杂(可能包括用户信息、其它信息,比如商品、订单的)
2.定义包装类型pojo
针对上边需求,建议使用自定义的包装类型的pojo。
在包装类型的pojo中将复杂的查询条件包装进去。
定义拓展类

public class UserCustom extends User {
    //这里添加扩展字段
    private Date birthday_start;//起始日期
    private Date birthday_end;//截止日期
}

定义包装类型

public class QueryVo {
    private UserCustom userCustom;

    public UserCustom getUserCustom() {
        return userCustom;
    }

    public void setUserCustom(UserCustom userCustom) {
        this.userCustom = userCustom;
    }
}

3.定义映射文件 在UserMapper.xml中定义用户信息综合查询(查询条件复杂)

<!--#{userCustom.sex}:取出pojo包装对象中性别值-->
<!--${userCustom.username}:取出pojo包装对象中用户名称-->
<select id="findUser" parameterType="QueryVo" resultType="UserCustom">
    SELECT * FROM USER WHERE user.sex = #{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>

4.Mapper接口

List<UserCustom> findUser(QueryVo queryVo) throws Exception;

Mybatis输出映射

resultType

使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,不会 创建pojo对象。
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

1.需求
用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。 2.mapper.xml

<select id="findUserCount" parameterType="QueryVo" resultType="int">
SELECT COUNT(*) FROM USER WHERE user.sex = #{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>

3.mapper.java

int findUserCount(QueryVo queryVo) throws Exception;

4.小结
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

5.输出pojo对象和pojo列表
不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。
在mapper.java指定的方法返回值类型不一样:

  1. 输出单个pojo对象,方法返回值是单个对象类型
  2. 输出pojo对象list,方法返回值是List 生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).

resultMap

mybatis中使用resultMap完成高级输出结果映射
1.resultMap使用方法
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

  1. 定义resultMap
  2. 使用resultMap作为statement的输出映射类型

3.将下边的sql使用User完成映射

SELECT id id_,username username_ FROM USER WHERE id=#{value}

User类中属性名和上边查询列名不一致。

4.mapper.xml

<!-- 定义resultMap
将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系
type:resultMap最终映射的java对象类型,可以使用别名
id:对resultMap的唯一标识
-->
<resultMap type="user" id="userResultMap">

    <!-- id表示查询结果集中唯一标识
    column:查询出来的列名
    property:type指定的pojo类型中的属性名
    最终resultMap对column和property作一个映射关系 (对应关系)
    -->
    <id column="id_" property="id"/>
    <!--
    result:对普通名映射定义
    column:查询出来的列名
    property:type指定的pojo类型中的属性名
    最终resultMap对column和property作一个映射关系 (对应关系)
    -->
    <result column="username_" property="username"/>

</resultMap>

<!-- 使用resultMap进行输出映射
resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_ FROM USER WHERE id=#{value}
</select>

5.小结
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

Mybatis对动态sql

什么是动态sql

mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接、组装。

需求1

用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql。

对查询条件进行判断,如果输入参数不为空才进行查询条件拼接

mapper.xml

<select id="findUser" parameterType="QueryVo" resultType="UserCustom">
    SELECT * FROM USER 
    <where>
        <if test="userCustom!=null">
            <if test="userCustom.sex!=null and userCustom.sex!=''">
                and user.sex = #{userCustom.sex}
            </if>
            <if test="userCustom.username!=null and userCustom.username!=''">
                and user.username LIKE '%${userCustom.username}%'
            </if>
    </if>
    </where>
</select>

需求2

将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。
方便程序员进行开发。

1.定义sql

<!-- 定义sql片段
id:sql片段的唯 一标识

经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高
在sql片段中不要包括 where
-->
<sql id="query_user_where">
    <if test="userCustom!=null">
        <if test="userCustom.sex!=null and userCustom.sex!=''">
            and user.sex = #{userCustom.sex}
        </if>
        <if test="userCustom.username!=null and userCustom.username!=''">
            and user.username LIKE '%${userCustom.username}%'
        </if>
    </if>
</sql>

2.引用sql

<!-- 
where可以自动去掉条件中的第一个and
-->
<where>
    <!-- 引用sql片段的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->
    <include refid="query_user_where"></include>
    <!-- 在这里还可以引用其它的sql片段  -->
</where>

需求3

在用户查询列表和查询总数的statement中增加多个id输入查询。
sql语句如下:
SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)

使用foreach
向sql传递数组或List,mybatis使用foreach解析

1.在输入参数类型中添加List ids传入多个id

private List<Integer> ids;

2.修改mapper.xml WHERE id=1 OR id=10 OR id=16
在查询条件中,查询条件定义成一个sql片段,需要修改sql片段。

<if test="ids!=null">
    <!-- 使用 foreach遍历传入ids
    collection:指定输入 对象中集合属性
    item:每个遍历生成对象中
    open:开始遍历时拼接的串
    close:结束遍历时拼接的串
    separator:遍历的两个对象中需要拼接的串
    -->
    <!-- 使用实现下边的sql拼接:
    AND (id=1 OR id=10 OR id=16) 
    -->
    
    <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
        <!-- 每个遍历需要拼接的串 -->
        id=#{user_id}
    </foreach>

    <!-- 实现  “ and id IN(1,10,16)”拼接 -->
    <!-- <foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=",">
    每个遍历需要拼接的串
    #{user_id}
    </foreach> -->

</if>