SpringBoot(六)mybatis基本语法

111 阅读8分钟

今天开始正式编写博客的功能。需要使用到数据库的交互(增删改查等)

 

之前在做测试的时候没有正经写过myBatis的查询语句,我懒,基本上都是调用IDEA生成的文件中的方法,有返回值证明数据库联通了就完事了。

 

我在刚才使用IDEA生成了我数据库中几张表的方法,我看了一下,能用的方法好像不是很多。众所周知,我是一个干PHP的,在使用PHP的框架的时候,我就很不喜欢使用框架中自带的数据库查询寻方法。我都是清一色的原生sql来操作数据库。

 

再加上我第一次使用myBatis,我这里决定我使用到的sql全部手写。

我这里特指SpringBoot框架中的mybatis框架使用。

 

一:mybatis的xml文件基本格式

我这里使用IDEA生成的mybatis生成的xml文件做示例:

<?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">
<mapper namespace="com.springbootblog.dao.ArticleDao">
  <resultMap id="BaseResultMap" type="com.springbootblog.pojo.Article">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="artlogo" jdbcType="VARCHAR" property="artlogo" />
    <result column="another" jdbcType="VARCHAR" property="another" />
  </resultMap>
  <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.springbootblog.pojo.Article">
    <result column="artdesc" jdbcType="LONGVARCHAR" property="artdesc" />
  </resultMap>
  <sql id="Blob_Column_List">
    artdesc
  </sql>
  <delete id="deleteByExample" parameterType="com.springbootblog.pojo.ArticleExample">
    delete from xxx.article
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </delete>
  <insert id="insert" parameterType="com.springbootblog.pojo.Article">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
      MariaDB
    </selectKey>
    insert into xxx.article (artlogo, another, is_top,
      sort_no, `status`, putime,
      uptime, arttitle, art_cid,
      labelstr, click_num, resourse_id,
      email, is_show, artdesc
      )
    values (#{artlogo,jdbcType=VARCHAR}, #{another,jdbcType=VARCHAR}, #{isTop,jdbcType=INTEGER},
      #{sortNo,jdbcType=INTEGER}, #{status,jdbcType=BIT}, #{putime,jdbcType=VARCHAR},
      #{uptime,jdbcType=VARCHAR}, #{arttitle,jdbcType=VARCHAR}, #{artCid,jdbcType=INTEGER},
      #{labelstr,jdbcType=VARCHAR}, #{clickNum,jdbcType=INTEGER}, #{resourseId,jdbcType=INTEGER},
      #{email,jdbcType=VARCHAR}, #{isShow,jdbcType=INTEGER}, #{artdesc,jdbcType=LONGVARCHAR}
      )
  </insert>
  <update id="updateByPrimaryKey" parameterType="com.springbootblog.pojo.Article">
    update xxx.article
    set artlogo = #{artlogo,jdbcType=VARCHAR},
    another = #{another,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
  <!-- 下边是我自己编写的sql -->
  <select id="selectBySearchAndPage" resultType="java.lang.Long" >
    SELECT count(1) as num FROM article p1
    LEFT JOIN article_info p2 ON p1.id = p2.article_id
    LEFT JOIN art_category p3 ON p1.art_cid = p3.id
    <where>
      <if test="search != null &amp; search != ''">
        p1.arttitle LIKE "%search%"
      </if>
    </where>
  </select>
</mapper>

 

1:xml 文件声明:

<?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">

这个没什么可说的,按照这个写就可以了。

 

二:标签分类

l   定义SQL语句

n   insert

n   delete

n   update

n   select

 

l   配置关联关系

n   collection

n   association

 

l   配置java对象属性与查询结果集中列名的对应关系

n   resultMap

 

l   控制动态SQL拼接

n   foreach

n   if

n   choose

n   when

n   otherwise

 

l   格式化输出

n   where

n   set

n   trim

 

l   定义常量

n   sql

 

l   其他

n   Include

n   Mapper

 

三:基础SQL标签

1:查询select

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

2)   paramterType 定义传入的参数类型

3)   resultType 返回数据类型对应实体类

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

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

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

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

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

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

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

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

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

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

具体实例如下所示:

<select id="selectBySearchAndPage" resultMap="BaseResultMap">
   SELECT p1.*,DATE_FORMAT(p1.putime,'%Y-%m-%d'AS addtime,p3.cat_name FROM article p1
   LEFT JOIN article_info p2 ON p1.id = p2.article_id
   LEFT JOIN art_category p3 ON p1.art_cid = p3.id
   <where>
     <if test="search != null &amp; search != ''">
       p1.arttitle LIKE "%#{search}%"
     </if>
   </where>
   ORDER BY p1.is_top DESC,p1.sort_no DESC, p1.id DESC
   LIMIT #{startNum}, #{limit}
 </select>

我在编写上方代码的时候,有些复杂了,理论上不应该在select标签中使用resultMap属性,resultMap属性对应的resultMap标签中的type还需要对应一个实体类。

那我直接在select标签中使用resultType属性对应一个实体类就可以了,就省去了编写resultMap标签的麻烦了。

 

2:update/insert/delete

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

2)   parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。

3)   flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。

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

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

6)   useGeneratedKeys(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server这样的关系数据库管理系统的自动递增字段, oracle使用序列是不支持的,通过selectKey可以返回主键),默认值:false。

7)   keyProperty (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

8)   keyColumn(仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

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

<delete id="deleteByExample" parameterType="com.springbootblog.pojo.ArticleInfoExample">
   delete from xxxx.article_info
   <if test="_parameter != null">
     <include refid="Example_Where_Clause" />
   </if>
 </delete>
<update id="updateByExampleSelective" parameterType="map">
   update xxxx.article_info
   <set>
     <if test="record.id != null">
       id = #{record.id,jdbcType=INTEGER},
     </if>
     <if test="record.articleId != null">
       article_id = #{record.articleId,jdbcType=INTEGER},
     </if>
     <if test="record.content != null">
       content = #{record.content,jdbcType=LONGVARCHAR},
     </if>
   </set>
   <if test="_parameter != null">
     <include refid="Update_By_Example_Where_Clause" />
   </if>
 </update>
<insert id="insert" parameterType="com.springbootblog.pojo.ArticleInfo">
   <!--使用序列插入oracle数据库返回主键,MYSQL数据库无需添加selectKey -->
   <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
     MariaDB
   </selectKey>
   insert into vueapi..article_info (article_id, content)
   values (#{articleId,jdbcType=INTEGER}, #{content,jdbcType=LONGVARCHAR})
 </insert>

四:配置java对象属性与查询结果集中列名的对应关系标签

resultMap 标签

ResultMap 标签用于描述查询结果集与 Java 对象之间的映射关系。ResultMap 标签有以下属性:

  1. id:指定 ResultMap 的唯一标识

  2. type:指定映射的 Java 对象类型

  3. extends:指定继承的 ResultMap

  4. discriminator:用于多表关联查询时进行分组判断

5.result(属性的配置映射关系,一般不止一个)、association(关联一个对象)、collection(关联一个集合):用于定义映射关系

6:result标签中的property用于给数据库字段命名别名

<resultMap id="BaseResultMap" type="com.springbootblog.pojo.Article">
   <id column="id" jdbcType="INTEGER" property="id" />
   <result column="artlogo" jdbcType="VARCHAR" property="artlogo" />
   <result column="another" jdbcType="VARCHAR" property="another" />
 </resultMap>
<select id="selectByExample" parameterType="com.springbootblog.pojo.ArticleExample" resultMap="BaseResultMap">
   select * from xxx.article
 </select>

简单理解resultMap就是我们自定义的一个sql返回的对象类型。

但是他还是需要对应一个实体类。

 

 

五:控制动态SQL拼接标签

1 :foreach标签

Ø  collection 循环的集合。传的是集合为list,数组为array, 如果是map为java.util.HashMap

Ø  item 循环的key

Ø  index 循环的下表顺序

Ø  open 循环的开头

Ø  close 循环结束

Ø  separator 循环的分隔符

<sql id="Update_By_Example_Where_Clause">
   <where>
     <foreach collection="example.oredCriteria" item="criteria" separator="or">
       <if test="criteria.valid">
         <trim prefix="(" prefixOverrides="and" suffix=")">
           <foreach collection="criteria.criteria" item="criterion">
             <choose>
               <when test="criterion.noValue">
                 and ${criterion.condition}
               </when>
               <when test="criterion.singleValue">
                 and ${criterion.condition} #{criterion.value}
               </when>
               <when test="criterion.betweenValue">
                 and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
               </when>
               <when test="criterion.listValue">
                 and ${criterion.condition}
                 <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                   #{listItem}
                 </foreach>
               </when>
             </choose>
           </foreach>
         </trim>
       </if>
     </foreach>
   </where>
 </sql>

**
**

2 :if标签

基本都是用来判断值是否为空,

注意Integer的判断,mybatis会默认把0变成””

<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>

**
**

3 :choose/when/otherwise标签

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。if是与(and)的关系,而choose是或(or)的关系

<sql id="Update_By_Example_Where_Clause">
   <where>
     <foreach collection="example.oredCriteria" item="criteria" separator="or">
       <if test="criteria.valid">
         <trim prefix="(" prefixOverrides="and" suffix=")">
           <foreach collection="criteria.criteria" item="criterion">
             <choose>
               <when test="criterion.noValue">
                 and ${criterion.condition}
               </when>
               <when test="criterion.singleValue">
                 and ${criterion.condition} #{criterion.value}
               </when>
               <when test="criterion.betweenValue">
                 and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
               </when>
               <when test="criterion.listValue">
                 and ${criterion.condition}
                 <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                   #{listItem}
                 </foreach>
               </when>
             </choose>
           </foreach>
         </trim>
       </if>
     </foreach>
   </where>
 </sql>

**
**

六:格式化输出标签

1 :where

where用来去掉多条件查询时,开头多余的and

<select id="selectByExample" parameterType="com.springbootblog.pojo.ArticleInfoExample" resultMap="BaseResultMap">
   select
   <if test="distinct">
     distinct
   </if>
   <include refid="Base_Column_List" />
   from xxxxx.article_info
   <if test="_parameter != null">
     <include refid="Example_Where_Clause" />
   </if>
   <if test="orderByClause != null">
     order by ${orderByClause}
   </if>
 </select>

**
**

2 :set

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

<update id="updateUser" parameterType="com.it.bean.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>

**
**

3 :trim

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

prefix、suffix 表示再trim标签包裹部分的前面或后面添加内容(注意:是没有prefixOverrides,suffixOverrides的情况下)

prefixOverrides,suffixOverrides 表示覆盖内容,如果只有这两个属性表示删除内容

<insert id="insertSelective" parameterType="com.springbootblog.pojo.ArticleInfo">
   <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
     MariaDB
   </selectKey>
   insert into xxxx.article_info
   <trim prefix="(" suffix=")" suffixOverrides=",">
     <if test="articleId != null">
       article_id,
     </if>
     <if test="content != null">
       content,
     </if>
   </trim>
   <trim prefix="values (" suffix=")" suffixOverrides=",">
     <if test="articleId != null">
       #{articleId,jdbcType=INTEGER},
     </if>
     <if test="content != null">
       #{content,jdbcType=LONGVARCHAR},
     </if>
   </trim>
 </insert>

**
**

七:定义常量标签

sql 标签

Sql 标签用于定义可重用的 SQL 片段,可以在 SQL 映射文件中多次引用。Sql 标签有以下属性:

  1. id:指定 Sql 片段的唯一标识符

  2. databaseId:指定 Sql 片段适用的数据库类型

  3. lang:指定 Sql 片段使用的脚本语言

  4. statementType、parameterType、resultType:用于定义 Sql 片段的类型信息

<sql id="Base_Column_List">
   id, artlogo, another, is_top, sort_no, `status`, putime, uptime, arttitle, art_cid, 
   labelstr, click_num, resourse_id, email, is_show
 </sql>
<select id="selectByExample" parameterType="com.springbootblog.pojo.ArticleExample" resultMap="BaseResultMap">
   select
   <if test="distinct">
     distinct
   </if>
   <include refid="Base_Column_List" />
   from vueapi.article
   <if test="_parameter != null">
     <include refid="Example_Where_Clause" />
   </if>
   <if test="orderByClause != null">
     order by ${orderByClause}
   </if>
 </select>

简单理解,sql标签就是定义了一个sql片段,方便复用:使用include标签引用。

 

 

八:其他标签

1 :mapper标签

Mapper 标签是 Mybatis 中最重要的标签之一,它用于描述 SQL 映射关系。Mapper 标签有以下属性:

  1. namespace:指定 Mapper 接口的完整路径名。

  2. resultMap:指定结果映射关系,将查询结果映射成 Java 对象。

  3. parameterMap:指定参数映射关系,将 Java 对象映射成 SQL 参数。

  4. sql:定义可重用的 SQL 片段。

  5. insert、update、delete、select:定义对应的 SQL 语句及参数映射关系。

<mapper namespace="com.springbootblog.dao.ArticleDao">
</mapper>

**
**

2 :include标签

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

<select id="countByExample" parameterType="com.springbootblog.pojo.ArticleInfoExample" resultType="java.lang.Long">
   select count(*) from xxxx.article_info
   <if test="_parameter != null">
     <include refid="Example_Where_Clause" />
   </if>
 </select>

这部分内容比较多,常用的标签了解即可。使用xml编写sql这个事情我多少是有点接受不了的,后期在项目开发的时候我也不会用xml。但不保证以后工作的时候不会遇到使用xml编写sql的项目,先全面了解一下。

 

有好的建议,请在下方输入你的建议。