mybatis的动态sql与核心映射

一、resultMap简介

MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库遵循第三范式或BCNF,但实际事与愿违,那么结果集映射就是MyBatis为我们提供这种理想与现实间转换的手段了,而resultMap就是结果集映射的配置标签了。

1.从SQL查询结果到领域模型实体

在深入ResultMap标签前,我们需要了解从SQL查询结果集到JavaBean或POJO实体的过程。

①. 通过JDBC查询得到ResultSet对象

②. 遍历ResultSet对象并将每行数据暂存到HashMap实例中,以结果集的字段名或字段别名为键,以字段值为值

③. 根据ResultMap标签的type属性通过反射实例化领域模型

④. 根据ResultMap标签的type属性和id、result等标签信息将HashMap中的键值对,填充到领域模型实例中并返回

2.使用场景
在项目的实际开发中,有可能会遇到这样两种情况。
第一种 : 当你的数据库的列名跟你的属性名不配置的时候,
第二种:复杂查询(一对一的关系 ,一对多的关系)

id property=""> 只代表id 标签的实体类的属性名, column 代表的是你的数据库列名,其他的不是id的属性就用这个名称result

constructor - 类在实例化时,用来注入结果到构造方法中

result – 注入到字段或 JavaBean 属性的普通结果

association – 一个复杂的类型关联;许多结果将包成这种类型(一对一)
collection – 复杂类型的集(一对多)

discriminator – 使用结果值来决定使用哪个结果映射
case – 基于某些值的结果映射

id、result语句属性配置细节:

<id property="" column=""/>
<result property="" column=""/>
属性 描述
property 需要映射到JavaBean 的属性名称。
column 数据表的列名或者标签别名。
javaType 一个完整的类名,或者是一个类型别名。如果你匹配的是一个JavaBean,那MyBatis 通常会自行检测到。然后,如果你是要映射到一个HashMap,那你需要指定javaType 要达到的目的。
jdbcType 数据表支持的类型列表。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果你是直接针对JDBC 编码,且有允许空的列,而你要指定这项。
typeHandler 使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。

代码(一对一):

 <resultMap id="selectByRoleResult" type="User">
        <id property="id" column="id"></id>
        <result property="userName" column="userName"></result>
        <result property="userRole" column="userRole"></result>
        <!--在mybatis 配置 一对一的关系 ,拿到的是属性名, javaType 代表类型,可以给别名-->
        <association property="role" javaType="Role">
            <id property="id" column="r_id"></id>
            <result property="roleName" column="roleName"></result>
            <result property="roleCode" column="roleCode"></result>
        </association>

    </resultMap>

    <select id="selectByRole" parameterType="User" resultMap="selectByRoleResult">
                 select   u.*,r.id as r_id,r.roleName,r.roleCode from    smbms_user u ,smbms_role r
              where   userName like  concat ('%',#{userName},'%')  and
              userRole =#{userRole} and  u.userRole = r.id

    </select>

代码(一对多)

    <resultMap id="selectAddressByNameResult" type="User">
    <id property="id" column="a_id"></id>
    <result property="userName" column="userName"></result>
    <result property="userRole" column="userRole"></result>
        <!--配置一对多,这里是ofType(必须有的)-->
        <collection property="addressList" ofType="Address">
            <id property="id" column="id"></id>
            <result property="addressDesc" column="addressDesc"></result>
            <result property="contact" column="contact"></result>
        </collection>

    </resultMap>

    <select id="selectAddressByName" parameterType="String" resultMap="selectAddressByNameResult">
       select  u.*  ,a.id as a_id,a.addressDesc ,a.contact from
       smbms_user u inner join smbms_address a on u.id=a.userId and u.userName=#{userName}
    </select>

使用注解的方式注入参数:

public List<User> selectUserByName(@Param("userName") String userName,@Param("userRole") Integer userRole);

二、动态SQL语句
MyBatis中用于实现动态SQL的元素主要有:
①if和where
where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子的,MyBatis会智能的帮你处理。如果所有的条件都不满足那么MyBatis就会查出所有的记录;如果输出后是and这个单词开头的,MyBatis会把第一个单词and忽略,当然如果是or开头的,MyBatis也会把它忽略。此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。
②choose (when, otherwise)
choose元素的作用就相当于JAVA中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。
③trim (where)
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能
④foreach
foreach的主要用在构建in条件中,它可以在SQL语句中迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。
item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束。
collection属性用于指定传入参数的类型。该属性是必须指定的,在不同情况下,该属性的值是不一样的,主要有以下3种情况:
如果传入的是单参数且参数类型是一个List类型的时候,collection属性值为list。
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map。实际上在传入参数的时候,MyBatis也是把它封装成一个Map的,List实例将会以“list”作为键,而数组实例将会以“array”作为键。这个时候collection属性值就是传入的List或array对象在封装自身的map里面中的对应key。

代码①:

    <select id="selectUserByName"  resultType="User">
            select   u.*,r.id  from  smbms_user u ,smbms_role r
              <trim prefix="where" prefixOverrides="and" suffix="and u.userRole = r.id">
              <if test="userRole!=null">
                  and userRole =#{ userRole}
              </if>
              <if test="userName != null and userName !=''">
                  and userName like  concat ('%',#{userName},'%')
              </if>
              </trim>
     </select>

代码②:

    <update id="updateUser" parameterType="User">
        update smbms_user
        <trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
            <if test="userCode != null ">userCode=#{userCode},</if>
            <if test="userName != null">userName=#{userName},</if>
            <if test="userPassword != null">userPassword=#{userPassword},</if>
            <if test="gender != null">gender=#{gender},</if>
            <if test="birthday != null">userName=#{birthday},</if>
        </trim>
    </update>

代码③

    <select id="selecetArrayUser" resultType="User">
        select * from smbms_user where userRole in
        <foreach collection="array" item="uRole" open="(" separator="," close= ")">
            #{uRole}
        </foreach>
    </select>

代码④:

    <select id="selecetListUser" resultType="User">
        select * from smbms_user where userRole in
        <foreach collection="List" item="uRole" open="(" separator="," close=")">
            #{uRole}
        </foreach>
    </select>

你可能感兴趣的:(JAVA框架)