今天开始正式编写博客的功能。需要使用到数据库的交互(增删改查等)
之前在做测试的时候没有正经写过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 & 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 & 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 标签有以下属性:
-
id:指定 ResultMap 的唯一标识
-
type:指定映射的 Java 对象类型
-
extends:指定继承的 ResultMap
-
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 标签有以下属性:
-
id:指定 Sql 片段的唯一标识符
-
databaseId:指定 Sql 片段适用的数据库类型
-
lang:指定 Sql 片段使用的脚本语言
-
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 标签有以下属性:
-
namespace:指定 Mapper 接口的完整路径名。
-
resultMap:指定结果映射关系,将查询结果映射成 Java 对象。
-
parameterMap:指定参数映射关系,将 Java 对象映射成 SQL 参数。
-
sql:定义可重用的 SQL 片段。
-
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的项目,先全面了解一下。
有好的建议,请在下方输入你的建议。