标签分类

定义SQL语句

  1. insert
  2. delete
  3. update
  4. select

配置关联关系

  1. collection
  2. association
  3. resultMap

动态SQL拼接

  1. foreach
  2. if
  3. choose

条件查询

  1. where
  2. set
  3. trim

mybatis使用where标签and不动态去除

  • 如果有注释会导致去除失败,但是代码中并没有任何注释,后来把所有空格去掉测试发现可以动态去除,
  • 然后重新换行添加空格发现也可以正常去除了,后通过代码比较发现,原来的空格用的是tab,tab导致去除失败,
  • 所以遇到这个问题的同学可以检查下自己代码是不是也出现了类似情况。

复用

  1. sql
  2. include

查询select

标签属性

  • id 唯一的名称,对应dao中mapper的接口名称

  • paramterType 定义传入的参数类型

  • resultType 返回数据类型对应实体类

  • resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用

  • flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false

  • useCache 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true

  • timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)

  • fetchSize 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。

  • statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

  • resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。

  • databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

  • resultOrdered 这个设置仅针对嵌套结果 select 语句适用:如果为true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至导致内存不够用。默认值:false。

  • resultSets 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。

<!--  List<User> selectUsers(@Param("cond")Map<String, Object> map); --><!-- 返回的是List,resultType给定的值是List里面的实体类而不是list,mybatis会自动把结果变成List -->
    <select id="selectUsers" parameterType="map" resultType="con.it.bean.User">
        select id, username, password, sex, birthday, address from user u
        <where>
            <trim suffixOverrides=",">
                <if test="cond.username != null and cond.username != ''">
                    u.username = #{cond.username},
                </if>
                <if test="cond.sex != null">
                    and u.sex = #{cond.sex},
                </if>
                 <if test="cond.beginTime != null">
                    <![CDATA[  and DATE_FORMAT(u.birthday, '%Y-%m-%d %H:%T:%s') >= DATE_FORMAT(#{beginTime}, '%Y-%m-%d %H:%T:%s'),   ]]>
                </if>
                <if test="cond.endTime != null">
                    <![CDATA[  and DATE_FORMAT(u.birthday, '%Y-%m-%d %H:%T:%s') <= DATE_FORMAT(#{endTime}, '%Y-%m-%d %H:%T:%s'),   ]]>
                </if>
                <if test="cond.address != null and cond.address != ''">
                    and u.addrerss like '%' || #{cond.address} || '%',
                </if>
            </trim>
        </where>
    </select>

增删改

标签属性

  • id 唯一的名称,对应dao中mapper的接口名称
  • parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
  • flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。
  • timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
  • statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
  • useGeneratedKeys(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server这样的关系数据库管理系统的自动递增字段, oracle使用序列是不支持的,通过selectKey可以返回主键),默认值:false。
  • keyProperty (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
  • keyColumn(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
  • databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
   <insert id="insert" parameterType="com.osvue.demo.User">

        <!-- 使用序列插入oracle数据库返回主键,MYSQL数据库无需添加selectKey -->
        <selectKey resultType="long" order="BEFORE" keyProperty="id">
            SELECT user_seq.NEXTVAL as id from DUAL
        </selectKey>
        
        insert into User (ID, USERNAME, PASSWORD, SEX, ADRESS, CREATED_BY, CREADTED_DATE)
        values (#{id}, #{username}, #{password}, #{sex}, #{adress}, #{createdBy}, SYSDATE)
    </insert>

sql 标签

定义一些常用的sql语句片段

<sql id="selectParam">
    id, username, password, sex, birthday, address
</sql>

include 标签

引用其他的常量,通常和sql一起使用

<select>
    select <include refid="selectParam"></include>
    from user
</select>

if 标签

基本都是用来判断值是否为空,注意Integer的判断,mybatis会默认把0变成 ‘’

<!-- OGNL 表达式,直接写 key 或对象的属性.不需要添加任
何特字符号 -->
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>

<if test="item != null and item != ''"></if>

<!-- 如果是Integer类型的需要把and后面去掉或是加上or-->
<if test="item != null"></if>
<if test="item != null and item != '' or item == 0"></if> 

collection与association标签

  • collection与association的属性一样,都是用于resultMap返回关联映射使用,collection关联的是集合,而association是关联单个对象

标签属性

  1. property resultMap返回实体类中字段和result标签中的property一样
  2. column 数据库的列名或者列标签别名,是关联查询往下一个语句传送值。注意: 在处理组合键时,您可以使用column=“{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。
  3. javaType 一般为ArrayList或是java.util.List
  4. ofType java的实体类,对应数据库表的列名称,即关联查询select对应返回的类
public class Question {
  

   private Long id; //问题id
   
   private String question; //问题
   
   private Integer questionType; //问题类型
   
   private List<QuestionAnswer> answerList; //问题选项集合
   
   //Getter和Setter省略
}


public class QuestionAnswer {
   
   private Long id; //选项id
   
   private Long questionId;  //问题id
   
   private String answer; //选项
   
   //Getter和Setter省略
}
<!-- 具体可参考下面ResultMap -->
<collection property="answerList" javaType="java.util.List"
          ofType="com.osvue.demo.QuestionAnswer" column="id" 
           select="setlectQuestionAnswerByQuestionId"/>

resultMap标签

resultMap属性

  • id 唯一标识
  • type 返回类型
  • extends 继承别的resultMap,可选
  • 关联其他标签
  • id 设置主键使用,使用此标签配置映射关系(可能不止一个)
  • result 一般属性的配置映射关系,一般不止一个
  • association 关联一个对象使用
  • collection 关联一个集合使用
   <!-- 返回关联查询的问题 -->
   <resultMap id="detail_result" type="com.osvue.demo.Question">
    <id column="id" property="id" />
    <result column="question" property="question" />
    <result column="question_type" property="questionType" />
    <collection property="answerList" javaType="java.util.List"
                ofType="com.osvue.demo.QuestionAnswer" column="id" 
                select="setlectQuestionAnswerByQuestionId"/>
   </resultMap>

<!-- 查询问题集 -->
<select id="selectQuestions" parameterType="map" resultMap="detail_result">
    select q.id, q.question, q.question_type 
    from question q 
    <where>
        <if test="cond.id != null">
            q.id = #{cond.id}
        </if>
        <if test="cond.idList != null and cond.idList.size() != 0">
            q.id in 
            <foreach collection="cond.idList" item="id" open="(" separator="," close=")">
                #{id}
            </foreach>
        </if>
    </where>
</select>

<!-- 查询对应问题的答案集 -->
<select id="setlectQuestionAnswerByQuestionId" parameterType="long" resultType="com.osvue.demo.QuestionAnswer">
    select a.id, a.answer from question_answer a where a.question_id = #{id}
</select>

foreach标签

foreach属性

  • collection 循环的集合。传的是集合为list,数组为array, 如果是map为java.util.HashMap
  • item 循环的key
  • index 循环的下表顺序
  • open 循环的开头
  • close 循环结束
  • separator 循环的分隔符

<select id="selIn" parameterType="list" resultType="log">
select * from log where id in
    <foreach collection="list" item="abc" open="("
    close=")" separator=",">
    #{abc}
    </foreach>
</select>

<sql id="base_column">id, question_id, answer</sql>

<!-- oracle的批量插入 -->
<insert id="insertBatchOracle" parameterType="list">
​    insert into question_answer ( <include refid="base_column" /> ) 
​    select question_answer_seq.NEXTVAL, A.* from (
​        <foreach collection="list" item="item" separator="union all">
​            select #{item.questionId}, #{item.answer} from dual
​        </foreach>
​    ) A 
</insert>

<!-- Mysql的批量插入,主键自增 -->
<insert id="insertBatchMysql" parameterType="list">
​    insert into question_answer ( <include refid="base_column" /> ) 
​    values 
​        <foreach collection="list" item="item" open="(" separator="union all" close=")">
​            #{item.id}, #{item.questionId}, #{item.answer}
​        </foreach>
</insert>

where标签

where

  • 当编写 where 标签时,如果内容中第一个是 and 去掉第一个 and
  • 如果<where>中有内容会生成 where 关键字,如果没有内容不 生成 where 关键
   <select id="selectUserList" parameterType="com.osvue.demo.User" resultType="com.osvue.demo.User">
       <!-- 引用Sql片段 -->
       select <include refid="selectParam"> from user u
       <where>
           <!--where 可以自动去掉条件中的第一个and-->
           <if test="id != null">
               and u.id = #{id}
           </if>
           <if test="name != null and name != ''">
               and u.name = #{name}
           </if>
       </where>
   </select>

set标签

set用在修改 SQL 中 set 从句

  • 作用:去掉最后一个逗号
  • 作用:如果 set 里面有内容生成 set 关键字,没有就不生成
  • id=#{id} 目的防止 set 中没有内容,mybatis 不生成 set 关 键字,如果修改中没有 set 从句 SQL 语法错误
<update id="upd" parameterType="log" >
update log
	<set>
		id=#{id},
		<if test="accIn!=null and accIn!=''">
			accin=#{accIn},
		</if>
		<if test="accOut!=null and accOut!=''">
        	accout=#{accOut},
		</if>
	</set>
where id=#{id}
</update>

set是mybatis提供的一个智能标记,当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。 没有使用if标签时,如果有一个参数为null,都会导致错误,如下示例:

   <update id="updateUser" parameterType="com.osvue.demo.user">
  ​     update user
  ​     <set><if test="username != null and username != ''">
  ​             username = #{username},
  ​         </if><if test="sex != null and sex == 0 or sex == 1">
  ​             sex = #{sex},
  ​         </if><if test="birthday != null ">  
  ​             birthday = #{birthday},
  ​         </if ><if test="address != null and address != ''">
  ​             address = #{address},
  ​         </if><if test="lastModifiedBy != null and lastModifiedBy != ''">
  ​             last_modified_by = #{lastModifiedBy},
  ​             last_modified_date = SYSDATE,
  ​         </if></set><where>
  ​         id = #{id}
  ​     </where>
   </update>

trim标签

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

  • prefix 在前面添加内容
  • prefixOverrides 去掉前面内容
  • suffix 在后面添加内容
  • suffixOverrieds 去掉后面内容
  • 执行顺序去掉内容后添加内容

标签属性

  • prefix、suffix 表示再trim标签包裹部分的前面或后面添加内容(注意:是没有prefixOverrides,suffixOverrides的情况下)
  • prefixOverrides,suffixOverrides 表示覆盖内容,如果只有这两个属性表示删除内容
<update id="test" parameterType="com.osvue.demo.User">
​    update user
​        <!-- 开头加上set,结尾去除最后一个逗号 --><trim prefix="set" suffixOverrides=","><if test="username!=null and username != ''">
​                name= #{username},
​            </if>

            <if test="password!=null and password != ''">
                password= #{password},
            </if>
    
        </trim>
        <where>
            id = #{id}
        </where>
    </update>

choose、when、otherwise标签

  • 有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。

  • choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句

  • choose为switch,when为case,otherwise则为default

  • if 是与(and)的关系,而choose是或(or)的关系

choose、when、others(用于if-else类似的条件判断)

<select id="chooseInWhere" resultMap="userMap">
        select * from user where 1=1
        <choose>
            <when test="id !=null">
                and id=#{id}
            </when>
            <otherwise>
                and id=2
            </otherwise>
        </choose>
    </select>
<select id="getUserList" resultType="com.osvue.demo.User" parameterType="com.osvue.demo.User">  
    SELECT <include refid="resultParam"></include> FROM User u   
    <where>  
        <choose>  
            <when test="username !=null and username != ''">  
                u.username LIKE CONCAT(CONCAT('%', #{username}),'%')  
            </when >  
            <when test="sex != null">  
                AND u.sex = #{sex}  
            </when >  
            <when test="birthday != null ">  
                AND u.birthday = #{birthday}  
            </when >  
            <otherwise>  
            </otherwise>  
        </choose>  
    </where>    
</select>  

番外篇

bind [模糊查询]

<select id="selByLog" parameterType="log" resultType="log">
	<bind name="accin" value="'%'+accin+'%'"/>
	#{money}

<!-- 也可使用 concat 拼接 -->
  	<if test="reportName != null and reportName !=''">
				AND a.feedback_name like concat ('%',#{reportName},'%')
			</if>
</select>