水下功夫做透,水上才能顺风顺水。

mybatis

一. Mybatis预备知识

(1)标签

 标签分为:闭合标签和空标签

标签属性格式

键名="值" <--!标签属性-->

闭合标签

<标签名 标签属性 标签属性......><--!开始标签-->
<--!标签内容-->
</标签名><--!结束标签-->

空标签(空标签没有内容但可以有属性,在开始标签中自动闭合)

<标签名 标签属性 标签属性....../>

xml文件内容的注释: <!--注释内容--> 

(2)jdbc(java database connectivity的缩写)

jdbcType 与 javaType 存在对应关系

(3)XML

在 xml 文件中出现 “<” , “>” ,双引号 等特殊字符时可以使用XML 文件转义标签(XML 自身的)   

<![CDATA[特殊字符]]>

 

 

二. Mybatis配置

1.resource xml文件配置修改,需要重启服务才能生效。

2. resultMap:适合使用返回值是自定义实体类的情况

    (resultType适合使用返回值得数据类型是非自定义的,即jdk的提供的类型)

<resultMap id="标识名" type="类名">
    <id column="类主键名" jdbcType="jdbcType类型(大写)" property="类的主键属性" />
    <result column="类字段名" jdbcType="jdbcType类型(大写)" property="类的属性"/>

    <association property="关联对象属性名" javaType="关联对象类名">     
        <id column="主键字段名" jdbcType="jdbcType类型(大写)" property="关联对象的主键属性"/>     
        <result column="类字段名" jdbcType="jdbcType类型(大写)" property="关联对象的属性"/>   
    </association> 
     
    <collection property="关联集合属性名" ofType="集合中对象类名">     
         <id column="集合中对象对应的表的主键字段" jdbcType="jdbcType类型(大写)" property="集合中对象的主键属性" />     
         <result column="集合中对象对应表的任意字段" jdbcType="jdbcType类型(大写)" property="集合中对象的属性" />     
    </collection>
</resultMap>

 3. 关联的嵌套查询(在collection中添加select属性)

如果collection标签是使用嵌套查询,格式如下:

<collection column="传递给嵌套查询语句的字段参数" property="pojo对象中集合属性" ofType="集合属性中的pojo对象" select="嵌套的查询语句" >   </collection>

例子:

<resultMap id="BasePlusResultMap" type="com.meikai.shop.entity.TShopSku">
    <id column="ID" jdbcType="BIGINT" property="id" />
    <result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" />
    <result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" />
    <collection column="{skuId=ID}" property="attributes" ofType="com.meikai.shop.entity.TShopAttribute" select="getAttribute" > 
    </collection>
</resultMap>

collection的select会执行下面的查询属性语句:

<resultMap id="AttributeResultMap" type="com.meikai.shop.entity.TShopAttribute">     
    <id column="ID" jdbcType="BIGINT" property="id" />     
    <result column="ATTRIBUTE_NAME" jdbcType="VARCHAR" property="attributeName" /> 
</resultMap>
<select id="getAttribute"  resultMap="AttributeResultMap">     
    select a.ID,s.ATTRIBUTE_NAME from t_shop_attribute a     
    where  a.ID = #{skuId,jdbcType=BIGINT}; 
</select>

BasePlusResultMap包含了属性查询语句的Collection 

所以通过下面的查询商品语句就可获得商品以及其包含的属性集合:

<select id="getById"  resultMap="BasePlusResultMap">     
    select s.ID,s.SKU_NAME,s.CATEGORY_ID from t_shop_sku s     
    where  s.ID = #{id,jdbcType =BIGINT}; 
</select>

 三. Mybatis 传参

parameterType属性:用于指定参数类型,可以省略不写,但结果类型不能省略。(自查得)

jdbcType属性:指定参数需要转换成的jdbc类型,查询时建议加上。更新或插入时必须加上,当传入的参数为name为空时不会使程序出现问题,否则当参数为空时,mybatis不知道具体要转换成什么jdbcType类型,有些特殊情况会报错。

0.#{}和${}的区别

相同点:都可以获取map中的值或者pojo对象属性的值。

不同点:

#{}是预编译处理,Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值,使用#{}可以有效的防止SQL注入,提高系统安全性。
${}是字符串替换,Mybatis在处理${}时,就是把${}替换成变量的值。

大多情况下,我们去参数的值都应该去使用#{},只有在原生jdbc不支持占位符的地方(比如比如字段名、【分】表名),我们才使用${}进行取值。

按照年份分表: select * from ${year}_salary where xxx;   

排序: select * from tbl_employee order by ${f_name} ${order}

1.单个参数

 

 

 2.按顺序传参

 

 注意:没有使用parameterType属性,早期版本用#{0},#{1}

 

3.使用@Param注解(支持多类型参数)

 

4.Map传参(支持多种类型参数)

 

 

 5. 实体对象传参

 

 

 6. List传参

 

 

 

 

 7.数组传参

 

 

四. Mybatis的insert、update、delete操作

1. 默认返回被操作记录条数。mybatis的insert、update、delete语句,默认是不返回被操作记录主键的,而是返回被操作记录条数(由mysql驱动返回给mybatis)。

2. 获取到记录主键id。<insert useGeneratedKeys="true" keyProperty="你的实体类id" keyColumn="你的表id"></insert>

useGeneratedKeys:必须设置为true,否则无法获取到主键id。

keyProperty:设置为POJO对象的主键id属性名称。

keyColumn:设置为数据库记录的主键id字段名称。

3. 批量更新和插入(此种效率比循环插入要高10倍)

 

<insert id="insertBatch">
    INSERT INTO t_user
            (id, name, del_flag)
    VALUES
    <foreach collection ="list" item="user" separator =",">
         (#{user.id}, #{user.name}, #{user.delFlag})
    </foreach >
</insert>

 

<update id="updateBatch" parameterType="java.util.List">
        update mydata_table
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="status =case" suffix="end,">
                <foreach collection="list" item="item" index="index">
                     when id=#{item.id} then #{item.status}
                </foreach>
            </trim>
        </trim>
        where id in
        <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
            #{item.id,jdbcType=BIGINT}
        </foreach>
    </update>

<trim>

当然这是最简单的批量更新实现,有时候可能需要更新多个字段,那就需要将

<trim prefix="status =case" suffix="end,">
     <foreach collection="list" item="item" index="index">
          when id=#{item.id} then #{item.status}
     </foreach>
</trim>

复制拷贝多次,更改prefix和when...then...的内容即可.

五.Mybatis的select操作

1. include空标签和其属性refid(引用唯一标识)

<include refid="Base_Column_List" />

 2. foreach标签和其属性

foreach元素的属性主要有collection,index,item,open,separator,close。【类似PHP:foreach ($array as $key => $value)】

collection[必填]: 1. 要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。

2. 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:如果User有属性List ids。入参是User对象,那么这个collection = "ids".如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"。

item[选填]:集合中元素迭代时的别名。

index[选填]:在list和数组中,index是元素的序号,在map中,index是元素的key。

open[选填]:foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。

separator[选填]:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。

close[选填]: foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:   

如果传入的是单参数且参数类型是一个List的时候,collection属性值为list .

如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array .

如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.

针对最后一条,我们来看一下官方说法:  注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以“list”作为键,而数组实例的键将是“array”。 

所以,不管是多参数还是单参数的list,array类型,都可以封装为map进行传递。如果传递的是一个List,则mybatis会封装为一个list为key,list值为object的map,如果是array,则封装成一个array为key,array的值为object的map,如果自己封装呢,则colloection里放的是自己封装的map里的key值。

 

 int insertRecoverWriteOffBatch(@Param("list") List<RecoverWriteOff> recoverWriteOffList);
  <insert id="insertRecoverWriteOffBatch"  parameterType="java.util.List">
    insert into t_recover_write_off (write_off_batch_no, merchant_no,
      flow_no, deduct_amount, create_time,
      update_time)
    values
    <foreach collection="list" item="recoverWriteOff" separator=",">
      (#{recoverWriteOff.writeOffBatchNo,jdbcType=VARCHAR}, #{recoverWriteOff.merchantNo,jdbcType=VARCHAR},
      #{recoverWriteOff.flowNo,jdbcType=VARCHAR}, #{recoverWriteOff.deductAmount,jdbcType=DECIMAL}, #{recoverWriteOff.createTime,jdbcType=TIMESTAMP},
      #{recoverWriteOff.updateTime,jdbcType=TIMESTAMP})
    </foreach>
  </insert>


 int updateRecoverFundFlowByPrimaryKeyBatch(@Param("list") List<RecoverFundFlow> list);

  <update id="updateRecoverFundFlowByPrimaryKeyBatch" parameterType="java.util.List" >
    <foreach collection="list" item="item" index="index" open="" close="" separator=";">
      update t_recover_fund_flow
      <set >
        <if test="item.matchStatus != null" >
          match_status = #{item.matchStatus,jdbcType=VARCHAR},
        </if>
        <if test="item.recoverBalance != null" >
          recover_balance = #{item.recoverBalance,jdbcType=DECIMAL},
        </if>
        <if test="item.updateTime != null" >
          update_time = #{item.updateTime,jdbcType=TIMESTAMP},
        </if>
        <if test="item.writeOffAmount != null" >
          write_off_amount = #{item.writeOffAmount,jdbcType=DECIMAL},
        </if>
      </set>
      where id = #{item.id,jdbcType=BIGINT}
    </foreach>
  </update>

 

posted @ 2019-10-24 12:04  北方寒士  阅读(159)  评论(0编辑  收藏  举报