zoukankan      html  css  js  c++  java
  • MyBatis框架之SQL映射和动态SQL

    使用MyBatis实现条件查询

    1.SQL映射文件:

    MyBatis真正的强大之处就在于SQL映射语句,MyBatis专注于SQL,对于开发人员来说也是极大限度的进行SQL调优,以保证性能。下面是SQL映射文件的几个顶级元素的配置:

      1.mapper:映射文件的根节点,只有一个属性namespace(命名空间),作用如下:

        (1)用于区分不同的mapper,全局唯一。

        (2)绑定DAO接口,即面向接口编程,当绑定一个接口,就不用写此接口的实现类,会通过接口的完全限定名找到对应的mapper配置来执行SQL语句,所以,namespace的命名必须要写接口的完全限定名。

      2.cache:配置给定命名空间的缓存。

      3.cache-ref:从其他命名空间引用缓存配置。

      4.resultMap:用来描述数据库结果集和对象的对应关系。

      5.sql:可以重用的SQL块,也可以被其他语句引用。

      6.insert:映射插入语句。

      7.update:更新映射语句。

      8.delete:删除映射语句。

      9.select:映射查询语句。

    2.使用select完成单条件查询

      <select id = "GetUserByName" resultType = "User" parameterType = "string">

        select * from user where name like concat('%',#{name},'%')    //按照姓名模糊查询。

      </select>

    这是一个id为GetUserByName的映射语句,参数类型为string,返回类型为User。

    #{参数名}:告诉MyBatis生成的PreparedStatement参数,相对于JDBC,改参数被标识为‘?’。

      id:命名空间的唯一标识符,可以被用来引用这条语句。

      parameterType:表示查询语句传入参数的类型和完全限定名或别名。支持基础数据类型和复杂数据类型。上述实例中传入的参数是一个别名,代表String。

                     别名与Java类型映射

    别名       映射的类型     别名     映射的类型    
    string   String double Double
    byte Byte float Float
    long  Long boolean Boolean
    short Short date Date
    int Integer map Map
    integer Integer hashmap HashMap
    arraylist ArrayList list List

      resultType:查询语句返回结果类型的完全限定名或别名。别名使用方式和parameterType是一样的。

    2.使用select完成多条件查询

      使用复杂数据类型,把条件参数封装为对象、Map进行入参。

      不管什么类型的参数,或者多少个参数,都可以封装为一个Map进行入参,通过Map的key进行获取传入的值

    1     <select id="GetUserByNameAndRoleId" resultType="User"
    2         parameterType="map">
    3         select * from smbms_user where userName like
    4         CONCAT('%',#{userName},'%')
    5         and userRole = #{userRole}
    6     </select>

    3.使用resultMap完成查询结果的展现

    resultMap:做自定义映射,实体类属性名和数据库列名不一致的情况下,并且可以指定要显示的列,使用灵活 应用广泛。

    1   <resultMap type="User" id="userMap">
    2        <id column="id" property="id"/>
    3        <result column="userName" property="Name"/> //字段名和属性名不一致的情况下。
    4   </resultMap>

    属性和子节点:

       id:唯一标识,此id值用于select元素resultMap属性的引用。

         type:标识该resultMap的映射结果类型。

         result子节点:标识一些简单属性,其中column属性代表数据库的字段名,property代表查询出来的字段名映射到pojo类的某个属性。   

         id子节点:与result子节点作用一样,一般表示数据库的主键列。

    -------------------------------------------------------------------------------------------------------

    resultType和resultMap的对比如下 :

    1.resultType:直接表示返回类型, 包括基本数据类型和复杂数据类型。

    2.resultMap:外部resultMap定义的引用,通过对应的外部resultMap的id,表示结果映射到哪个resultMap上,一般用于字段名和属性名不一致的情况,或者需要做复杂的联合查询以便自由控制映射结果。

    3.两者的关联

    当进行查询时,查询出来的每个字段都会放在一个Map里,当查询元素返回属性是resultType的时候,会将键值对取出赋所指定的属性。其实MyBatis的每个查询映射的返回类型都是resultMap,只是当我们使用resultType的时候,会自动把对应的值赋给所指定的对象属性,当使用resultMap时候,因为map不是很好的表示领域,我们就进一步的转化为对应的实体对象。resultMap主要作用于复杂的联合查询上。

    注意:resultType和resultMap本质是一样的,都是Map数据结构,但是二者不能同时存在。

    4.resultMap的自动映射级别:默认级别为PARTIAL,也可以在settings更改值。

    1   <settings>
    2         <!-- 设置resultMap的自动映射级别为NONE(禁止自动匹配) -->
    3         <setting name = "autoMappingBehavior" value = "NONE">
    4   </settings>

    4.使用MyBatis实现增删改操作

      1.使用insert完成增加操作

    <insert id="add" parameterType="User">
        INSERT INTO user(userName,userCode) VALUES(#{userName},#{userCode})
    </insert>

      2.使用update完成修改操作

        <update id="update" parameterType="User">
            UPDATE user SET userName= #{userName},userCode= #{userCode} WHERE id = #{id}
        </update>

      3.使用delete完成删除操作

    <delete id="User" parameterType="integer">
            delete from user
            where id = #{id}
    </delete>

      元素中的属性:

        id:与select元素id一样,命名空间的唯一标识符。

        parameterType:传入参数的类型的完全限定名或者别名。

    对于增删改操作的注意事项:

    (1)该类型的操作本身默认返回执行SQL影响的行数,所以DAO层的接口方法返回值一般为int类型,最好不要boolean类型。

    (2)insert、update、delete元素中均没有resultType属性,只有查询操作需要对返回结果类型(resultType/resultMap)进行相应的指定。

     5.使用@param注解实现多参数入参

       使用注解用来传入多个参数,相当于给该参数重命名,在SQL映射文件中需要使用#{注解名称}来传入参数。 

        public user GetUserByIdAndName(@Param("id") Integer id,@Param("Name") String Name);

    当参数为基础类型时,无论是多参数还是单参数,都使用@param注解进行参数的传递为好!

    使用resultMap实现高级结果映射

    1.association:

       映射到JavaBean的某个复杂的”数据类型”属性,仅处理一对一的关联关系。

      <resultMap type="SMS_USER" id="userMap">
            <id column="id" property="id" />
            <result column="userName" property="userName" />
            <result column="phone" property="phone" />
            <association property="role" javaType="SMS_Role">
                <id column="id" property="id" />
                <result column="roleName" property="roleName" />
            </association>
        </resultMap>

       association的属性节点:

        property:映射数据库列的实体对象属性名。

        javaType:完整的java类名和限定名。propert所映射的属性的类型。

        子元素:id:一般为映射主键,可以提高性能。

            result:

              column:映射的数据库的字段名。

              property:映射的数据列对应的实体对象属性。
    2.collection:

       映射到JavaBean的某个复杂的”数据类型”属性,这个属性是一个集合列表,处理一对多的关联关系。

        <resultMap type="SMS_USER" id="userMapAddress">
            <id column="id" property="id"/>
            <result column="userName" property="userName"/>
            <collection property="lists" ofType="SMS_Address">
           <id column = "id" property = "id"> <result column="addressDesc" property="addressDesc"/> </collection> </resultMap>

      ofType:完整的java类名和限定名。propert所映射的属性的类型。

      其余和association基本一致。

    MyBatis缓存

    1.一级缓存:基于PerpetualCache(MyBatis自带)的HashMap本地缓存。作用域在Session域内,当session flush或者close之后,该缓存被清空。

    2.二级缓存:global Cache,超出session范围之外,可以被所有SqlSession共享。开启它只需在MyBatis的核心配置文件 settings 设置即可。

      补充:一级缓存缓存的是SQL语句,二级缓存缓存的是结果对象。

    3.二级缓存配置:

      (1)开启二级缓存;

    <settings>
            <setting name="cacheEnabled" value = "true"/>
    <settings>

      (2)mapper文件中设置缓存,默认是没有开启缓存的。作用域是针对namespace而言的,只在namespace内的查询才能共享这个cache。

      (3)对个别查询进行缓存,单独设置cache:

    <select id = "getUser" resultType = "User" useCache = "true">
        ...........
    </select>

    补充:对MyBatis的缓存了解就可以了,对结果集做缓存并不是MyBatis所擅长的,而且性能也不是很好,它专心做的应该是SQL映射。

    ------------------------------------------------------------------------------------------------------------------------------------

    动态SQL

    一、使用动态SQL完成多条件查询。

    动态SQL基于OGNL的表达式,我们可以方便的在SQL语句中实现某些逻辑,用于实现动态SQL元素如下:

      if:利用if实现简单的条件选择。

      choose(when,otherwise):相当于java中的switch语句,通常与when和otherwise搭配。

      set:解决动态更新语句。

      trim:灵活的去除多余的关键字。

      foreach:迭代一个集合,通常用于in条件。

    二、if+where实现多条件查询

        <select id="ShowUser" parameterType="Map" resultType="SMS_USER">
            select * from smbms_user
                <where>
                    <if test="userRole != null and userRole != 0">
                        userRole = #{userRole}
                    </if>
                    <if test="userName != null and userName != ''">
                        and userName like CONCAT('%',#{userName},'%')
                    </if>
                </where>
        </select>

    where元素可以智能的处理and 和 or 的多余问题, 不需担心多余关键字导致语法错误。

    if元素的test用于判断表达式是否符合,符合则继续拼接SQL语句。

    三、if+trim+foreach实现多条件查询

     1  <select id="listsByInAndGender" resultType="SMS_USER">
     2           select * from smbms_user
     3         <trim prefix="where" prefixOverrides="and | or">
     4             <if test="userIds!=null">
     5                 id in
     6                 <foreach collection="userIds" item="ids" open="(" close=")" separator=",">
     7                     #{ids}
     8                 </foreach>
     9             </if>
    10             <if test="gender != null and gender != 0">
    11                 and gender = #{gender}
    12             </if>
    13         </trim>
    14  </select>

    (1)trim的属性:

      prefix:前缀: 作用是通过自动识别是否有返回值后,在trim包含的内容上加上前缀,如上述示例的where。

      suffix:后缀: 作用是在trim包含的内容上加上后缀。

      prefixOverrides: 对于trim包含内容的首部进行指定内容,(如上述示例的 and | or) 的忽略(去余);

      suffixOverrides: 对于trim包含内容的首位部进行指定内容的忽略。

    (2)foreach的属性:

      item:表示集合中每一个元素进行迭代时的别名。

      index: 指定一个名称,表示在迭代的过程中,每次迭代到的位置。

      open:表示该语句以什么开始(既然是in条件语句,必然是 ' ( ' 开始)

      separator: 表示每次进行迭代的时候以什么符号作为分隔符(既然是in条件语句,必然是 ' , ' 分隔)

      close: 表示该语句以什么结束(既然是in条件语句,必然是 ' ) ' 结束)

      collection:最关键,并且最容易出错的属性。需注意,该属性必须指定,不同情况下,该属性值是不同的,主要有三种情况:

        若传入的参数是单参数且类型为一个List的时候,属性值为list;

        若传入的参数是单参数且类型为一个数组的时候,属性值为array;

        若传入的参数为多参数时,就需要封装为一个map集合进行处理。属性值为Map的key;

    使用set更新操作,类似于上述示例使用方法:

     1     <update id="UpdateUser" parameterType="SMS_USER">
     2          update smbms_user
     3          <trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
     4              <if test="userName != null and userName != ''">
     5                  userName = #{userName},
     6              </if>
     7              <if test="gender != null and gender != 0">
     8                  gender = #{gender},
     9              </if>
    10              <if test="address != null and address != ''">
    11                  address = #{address},
    12              </if>
    13          </trim>
    14     </update>

    三、choose(when、otherwise)

     1     <select id="QueryAllByChoose" resultType="SMS_provider">
     2         select * from smbms_provider where 1 = 1
     3         <choose>
     4             <when test="proCode != null and proCode != ''">
     5                 and proCode like CONCAT('%',#{proCode},'%')
     6             </when>
     7             <when test="proName != null and proName != ''">
     8                 and proName like CONCAT('%',#{proName},'%')
     9             </when>
    10             <when test="proContact != null and proContact != ''">
    11                 and proContact like CONCAT('%',#{proContact},'%')
    12             </when>
    13             <otherwise>
    14                 and YEAR(creationDate) = 2016
    15             </otherwise>
    16         </choose>
    17     </select>

      when元素:当test属性中的条件满足时,就会输出when元素中的内容,并且当when中一旦有条件满足时,就会跳出choose,所以只有一个条件会被输出。

      otherwise元素:当when中的所有条件都不满足时,则会输出此元素的内容。

    四、MyBatis实现分页功能

      1.使用聚合函数获得总记录数-

      2.实现分页通过limit(起始位置,页面显示量)

    补充:起始位置的下标  = (当前页码 - 1 ) * 页面显示量

     1       <!-- 多条件筛选分页 -->
     2     <select id="UserPage" parameterType="map" resultType="SMS_USER">
     3         select * from smbms_user
     4         <trim prefix="where" prefixOverrides="and | or">
     5             <if test="userName != null and userName != ''">
     6                 userName like concat('%',#{userName},'%')
     7             </if>
     8             <if test="userRole != null and userRole != 0">
     9                 and userRole = #{userRole}
    10             </if>
    11         </trim>
    12         limit #{startRow},#{pageSize}
    13     </select>
  • 相关阅读:
    操作系统基本原理
    String.StartsWith 方法
    桥接模式
    there is no default constructor available in ... | interface extends interface
    JAVA,获取手机屏幕大小
    JAVA,读写properties文件
    JAVA,执行cmd命令控制台输出内容乱码问题解决
    JAVA自动化,使用UIAutomator2加快Appium运行速度
    JAVA自动化,真机打开APP,弹出权限弹窗问题解决
    揭秘TDSQL-A分布式执行框架:解放OLAP关联分析查询性能瓶颈
  • 原文地址:https://www.cnblogs.com/hujunhui/p/9199681.html
Copyright © 2011-2022 走看看