SSM之Mybatis(二)Mapper映射文件

介绍

Mapper映射文件,作用是用来配置SQL映射语句,根据不同的SQL语句性质,使用不同的标签,mapper文件中常用的标签有<select>、<insert>、<update>、<delete>

增删改查的实现

一个简单的Mapper映射文件案例

<?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">
<!-- namespace:此处使用包名+文件名 的形式 -->
<mapper namespace="com.sl.mapper.ProductMapper">

    <!--select – 映射查询语句
       id:唯一标识 parameterType:参数类型,此处是根据id查询,类型为int resultType:返回值类型, 
        #{id}: 参数 -->
    <select id="selectProduct" parameterType="int" resultType="com.sl.po.Product">
        select * from products where id = #{id}
    </select>
    
    <!-- insert – 映射插入语句
      注: sql中参数最好和po中属性命名一致   
     -->
    <insert id="insertProduct" parameterType="com.sl.po.Product">
        insert into products(name,description,UnitPrice,IsNew)
        values(#{name},#{description},#{UnitPrice},#{IsNew})
    </insert>
    
    <!-- update – 映射更新语句 -->
    <update id="updateProduct" parameterType="com.sl.po.Product">
        update products set UnitPrice = #{UnitPrice},IsNew=#{IsNew} where id=#{id}
    </update>
    
    <!-- delete – 映射删除语句-->
    <delete id="deleteProduct" parameterType="int">
        delete from products where id=#{id}
    </delete>
</mapper>

Mapper 输入参数映射配置

Mybatis中parameterType为输入参数类型,可以配置为基本数据类型、基本数据包装类型、或自定义数据类型(JavaBean),Sql语句中使用#{}或${}传入参数。

#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符,使用占位符#{}可以防止sql注入,使用时不需要关心参数值的类型,mybatis将自动进行java类型和jdbc类型的转换。

可 以 将 参 数 拼 接 在 s q l 中 且 不 进 行 j d b c 类 型 转 换 , {}可以将参数拼接在sql中且不进行jdbc类型转换, sqljdbc{}可以接收简单类型值或pojo属性值,如果传入的是个简单类型,括号中只能是value,即:${value}:

注:parameterType为非必填属性,下面的情况中parameterType省略不写也不会报错。

使用示例:

<!-- ${} sql拼接 -->
<select id="selectProductByName" parameterType="string" resultType="com.sl.po.Product">
	select * from products where name like '%${value}%'
</select>
<!-- #{} 参数化 -->
<select id="selectProductByName2" parameterType="string" resultType="com.sl.po.Product">
	select * from products where name like #{value}
</select>
映射基本数据类型

映射基本数据类型时,参数名也可用value代替,#{value} 即: select * from products where id = #{value}

使用示例

<select id="selectProduct" parameterType="int" resultType="com.sl.po.Product">
        select * from products where id = #{id}
</select>
映射pojo对象

参数名必须与pojo对象属性一致,此处UnitPrice 与 IsNew为Product属性。

<!-- pojo -->
<select id="selectProductByPoJo" parameterType="com.sl.po.Product" resultType="com.sl.po.Product">
  select * from products where unitprice>#{UnitPrice} and isnew =#{IsNew} 
</select>
映射pojo封装对象

参数名必须与pojo对象属性一致,这种方法不经常使用,直接使用上面映射pojo对象的方法就可以了。

使用示例

 <!-- pojo包装对象 -->
<select id="selectProductByVo" parameterType="com.sl.po.ProductVo" resultType="com.sl.po.Product">
  select * from products where citycode=#{product.cityCode} and isnew =#{product.isNew} 
</select>
映射hashmap

参数名必须与map中的key一致
使用示例

<!-- hashmap -->
<select id="selectProductByHashMap" parameterType="hashmap" resultType="com.sl.po.Product">
	select * from products where citycode=#{cityCode} and isnew =#{isNew} 
</select>

Mapper 结果集映射配置

MyBatis的mapper映射文件中,resultType为输出结果集类型,同样支持基本数据类型及自定义数据类型。SQL语句查询后返回的结果集会映射到配置标签的输出映射属性对应的Java类型上。Mapper的输出映射有两种配置,分别是resultType和resultMap,注意两者不能同时使用

映射基本数据类型

返回结果只有一行一列时可以使用基本数据类型

使用示例

<select id="countProducts" resultType="int">
   select count(1) from products 
</select>
映射pojo对象或对象列表

返回自定义实体类类型 , 返回List<PoJo>的话,注意: resultType配置也是为PoJo类型,而不是List。查询的结果列名必须和实体类属性名一致。

使用示例

<select id="selectProductById" parameterType="int" resultType="com.sl.po.Product">
   select * from products where id = #{id}
</select>
映射hashmap或hashmap列表

返回自定义HashMap类型,与实体类的差别在于它不在乎查询的列名是什么。

使用示例

<!-- 返回hashmap -->
<select id="selectProductById2" parameterType="int" resultType="hashmap">
    select * from products where id = #{id}
</select>
<!-- 返回List<hashmap> -->
<select id="selectAllProduct2" resultType="hashmap">
    select * from products
</select>
使用resultMap映射结果集

使用resultType可以映射结果集时需要pojo的属性名和sql查询结果的列名一致才可以映射成功。如果sql查询结果集字段名和pojo的属性名不一致,则需要通过resultMap将字段名和属性名作一个对应关系(sql 查询取别名与pojo属性一致也可以) ,resultMap实质上还需要将查询结果映射到pojo对象中。resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

使用示例

<!-- 使用resultMap映射结果集   -->
<select id="selectProductInfo" resultMap="productInfoResultMap">
    select p.`Name` pName,p.Description,c.citycode,c.`name` cName 
    from products  p
    join city c
    on p.citycode = c.citycode
</select>
<resultMap id="productInfoResultMap" type="com.sl.po.ProductInfo">
      <result property="ProductName" column="pName"/>
      <result property="CityName" column="cName"/>
</resultMap>

动态SQL

在mapper配置文件中,有时需要根据查询条件选择不同的SQL语句,或者将一些使用频率高的SQL语句单独配置,在需要使用的地方引用。Mybatis的一个特性:动态SQL,来解决这个问题。

mybatis动态sql语句是基于OGNL表达式的,主要有以下几类:

  1. if 语句 (简单的条件判断)
  2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似
  3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
  4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)、
  5. set (主要用于更新时)
  6. foreach (在实现 mybatis in 语句查询时特别有用)

if标签语句

if标签用来实现根据条件拼接sql语句,下面示例用来判断参数如果不为null,则拼接sql。

使用示例

<select id="ifTest" resultType="com.sl.po.Product">
	  select * from products where 
	  <if test="ProductName!=null">
	      name like #{ProductName}
	  </if>
	  <if test="description!=null">
	      and description like CONCAT(CONCAT('%', #{Description, jdbcType=VARCHAR}),'%')
	  </if>
</select>

当参数ProductName和Description不为null,则正常拼接处sql语句:select * from products where name like ? and description like CONCAT(CONCAT(’%’, ?),’%’)

where标签语句

当 where 中的条件使用的 if 标签较多时,这样的组合可能会导致错误, “where”标签会自动判断如果它包含的标签中有返回值的话,就在sql中插入一个‘where’,如果where标签最后返回的内容是以 and 或者or 开头的,也会被自动移除掉

使用示例

<select id="whereTest" resultType="com.sl.po.Product">
        select * from products
        <!-- where标签自动移除第一个and-->
        <where>
            <if test="Name!=null">
                and name like #{Name}
                <!--name like #{Name}-->
            </if>
            <if test="description!=null">
                and description like #{Description}
            </if>
        </where>
</select>

set标签语句

set 标签是用在更新操作的时候,功能和 where 标签元素差不多,主要是在包含的语句前输出一个 set,然后如果包含的语句是以逗号结束的话将会把该逗号忽略,如果 set 标签最终返回的内容为空的话则可能会出错(update table where id=1)

使用示例

<!-- if + set 实现按条件更新-->
 <update id="setTest">
      update products        <!-- set标签将移除最后一个“,” -->
      <set>
          <if test="cityCode!=null">
            citycode = #{cityCode} ,
          </if>
          <if test="Name!=null">
             name = #{Name} ,
          </if>
          <if test="description!=null">
              description = #{Description} ,
          </if>
      </set>
      where id =#{id}
</update>

trim标签语句

trim 元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides;正因为 trim 有这样的功能,它可以用来实现 where 和 set 的效果。

使用示例

<!-- if+trim 使用trim代理where-->
<select id="trimwhereTest" resultType="com.sl.po.Product">
    select * from products
<!-- 移除首部所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容-->
    <trim prefix="WHERE" prefixOverrides="AND | OR">
        <if test="Name!=null">
            and name like #{Name}
        </if>
        <if test="description!=null">
            and description like #{Description}
        </if>
    </trim>

</select>

choose (when, otherwise)标签

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql,类似于sql server语句(case when then)

使用示例

<!-- choose + when + otherwise 只能选择一个作为查询条件 作用类似sql case when then -->
<select id="choosewhenotherwiseTest" resultType="com.sl.po.Product">
    select * from products
 <where>
    <choose>
        <when test="name!=null">
            and name like #{Name}
        </when>
        <when test="description!=null">
            and description like #{Description}
        </when>
        <otherwise>
            and unitprice > #{UnitPrice}
        </otherwise>
    </choose>
 </where>
</select>

如果name!=null,则解析出sql: select * from product where name like ?
Name==null&& description!=null,则解析出sql: select * from product where description like ?
否则:select * from product where unitprice >?

foreach标签语句

mybatis提供foreach标签,用来对一个集合进行遍历,通常是用来构建 IN 条件语句,也可用于其他情况下动态拼接sql语句。

foreach标签有以下几个属性collection, item,index,open,separator,close。

  1. collection表示需要遍历的集合
  2. item 表示每次遍历时生成的对象名
  3. index表示在迭代过程中,每次迭代到的位置)
  4. open表示开始遍历时要拼接的字符串
  5. separator表示在每次遍历时两个对象直接的连接字符串
  6. close表示结束遍历时要拼接的字符串

当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
在使用foreach的时候针对不同的参数类型, collection属性值要分为以下3种情况:
7. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
8. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
9. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map或者Object。

单个集合使用示例

<!-- 只有一个List参数时它的参数名为list,即collection="list" ;  如果参数类型时数组object[],则  collection="array" -->
<select id="foreachTest" resultType="com.sl.po.Product">
      select * from products 
      <where>
        <if test="list!=null">
          <foreach item="id" index="index"  collection="list" open="id in(" separator="," close=")">#{id}</foreach>
        </if>
      </where>
</select>

对象中含有集合属性使用示例:

<!-- 通过pojo传递list, collection值为pojo中对应的属性名-->
<select id="foreachVoTest" resultType="com.sl.po.Product">
      select * from products 
      <where>
         <if test="name!=null"> and name like #{name} </if>
         <if test="ids!=null">
            <foreach item="item" index="index"  collection="ids" open="and id in(" separator="," close=")">#{item}</foreach>
         </if>
      </where>
 </select>

Sql片段

Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

使用示例:

<select id="sqlTest" resultType="com.sl.po.Product">
        select * from products
        <where>        <!-- 引用sql片段 -->
        <include refid="sqltemp"/>
          <!-- 提取sql片段
            <if test="cityCode!=null">
               and citycode = #{cityCode}
            </if>
            <if test="Name!=null">
                and name like #{Name}
            </if>
            <if test="description!=null">
                and description like #{Description}
            </if>
             -->
        </where>
</select>
    <!-- 定义sql片段 :将where条件提取 -->
    <sql id="sqltemp">
    <if test="cityCode!=null">
               and citycode = #{cityCode}
            </if>
            <if test="Name!=null">
                and name like #{Name}
            </if>
            <if test="description!=null">
                and description like #{Description}
            </if>
    </sql>

Mapper接口动态代理

实现原理及规范

Mapper接口动态代理的方式需要手动编写Mapper接口,Mybatis框架将根据接口定义创建接口的动态代理对象,代理对象的方法体实现Mapper接口中定义的方法。

使用Mapper接口需要遵守以下规范:

  1. Mapper.xml文件中的namespace与mapper接口的类路径相同
  2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
  3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
  4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

编写Mapper.xml映射文件

定义mapper映射文件ProductMapper.xml,需要修改namespace的值为 ProductMapper接口路径。

<?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">
<!-- namespace:此处使用包名+文件名 的形式 -->
<mapper namespace="com.sl.mapper.ProductMapper">
    <!-- 返回自定义类型 注意 selectAllProduct返回的是集合,这种情况下resultType是集合包含的类型,而不能是集合本身 -->
    <select id="selectAllProduct" resultType="com.sl.po.Product">
        select * from products
    </select>
  <select id="selectProductsByVo" resultType="com.sl.po.Product">
        select * from products
        <where>
            <if test="product.cityCode!=null">
               and citycode = #{product.cityCode}
               <!-- citycode = #{cityCode} -->
            </if>
            <if test="product.Name!=null">
                and name like #{product.Name}
            </if>
            <if test="product.Description!=null">
                and description like #{product.Description}
            </if>
        </where>
  </select>  
</mapper>

编写Mapper.java接口

接口定义注意点:

  1. Mapper接口方法名和Mapper.xml中定义的statement的id相同
  2. Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
  3. Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
package com.sl.mapper;
import java.util.List;
import com.sl.po.Product;
import com.sl.po.ProductVo;

public interface ProductMapper {
    
    List<Product> selectAllProduct();
    
    List<Product> selectProductsByVo(ProductVo vo);
    
}

注册Mapper.xml配置文件(或者Mapper.java接口)

修改SqlMapConfig.xml文件:

<mappers>
        <!-- 注册productMapper.xml文件 -->
        <mapper resource="mapper/productMapper.xml"></mapper> <!-- mapper.xml文件和mapper接口可以不在一个包下  -->
        
        <!-- 注册mapper接口 -->
        <!-- <mapper class="com.sl.mapper.ProductMapper"></mapper>  --> <!--通过注册mapper接口方式: Mapper接口和mapper.xml必须在同一个包下 -->
        
</mappers>

由于参数类型在mapper.xml配置文件中ParameterType配置,所以Mapper.java中接口方法只有一个参数,且类型与mapper.xml中配置的相同(mapper.xml可省略参数类型配置)。

  • 9
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值