想用springboot+mybatis写一个个人博客(因为舍不得买的服务器放哪不用)然后mybatis之前也就是了解一点完全不懂就是边看后面边踩坑边爬坑。所以记录一下mybatis的使用防止自己忘记

首先上表结构

数据库表结构
CREATE TABLE `h_blog` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '博客ID',
  `userId` bigint(11) DEFAULT NULL COMMENT '用户ID',
  `title` varchar(255) DEFAULT NULL COMMENT '博客标题',
  `mdContent` longtext COMMENT 'markendown保存的内容用以修改回显',
  `content` longtext COMMENT '博客内容',
  `createTime` timestamp NULL DEFAULT NULL COMMENT '发表时间',
  `lookNum` bigint(11) DEFAULT NULL COMMENT '浏览量',
  `likeNum` bigint(11) DEFAULT NULL COMMENT '点赞量',
  `commentNum` bigint(11) DEFAULT NULL COMMENT '评论量',
  `modifyTime` timestamp NULL DEFAULT NULL COMMENT '最后修改时间',
  `tagIds` varchar(255) DEFAULT NULL COMMENT '博客标签Id(可以有多个,隔开)',
  `categoryId` bigint(11) DEFAULT NULL COMMENT '分类ID',
  `blogHeader` varchar(255) DEFAULT NULL COMMENT '博客图标',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='博客表';
分类表
CREATE TABLE `dic_catgory` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '分类表ID',
  `catName` varchar(255) DEFAULT NULL COMMENT '分类名称',
  `catDesc` text COMMENT '分类描述',
  `catParentId` bigint(11) DEFAULT NULL COMMENT '父分类ID(分类导航)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COMMENT='博客分类表';
用户表
CREATE TABLE `h_user` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '用户表ID主键自增',
  `nickname` varchar(255) NOT NULL COMMENT '用户昵称',
  `header` varchar(255) DEFAULT NULL COMMENT '用户头像',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

1.保存

保存的时候大部分是想要返回保存的主键ID的 所以要加上useGeneratedKeys="true" keyProperty="id" 一个是要返回主键一个是要将返回的值放到哪个字段中。其本身返回的还是Integer的影响行数,但是在传入的对象中取id是可以取出保存记录的主键ID的

<insert id="saveBlog" parameterType="Blog" useGeneratedKeys="true" keyProperty="id"  >
        INSERT INTO h_blog(userId,title,mdContent,content,createTime,categoryId,tagIds,blogHeader)
        values (
        #{userId},
        #{title},
        #{mdContent},
        #{content},
        #{createTime},
        #{tagIds},
        #{blogHeader}
        )
    </insert>

2.删除

删除时要注意的是 前面的id就是dao层对于分类删除的方法名 parameterType就是入参的类型了 #{id}为什么里面的是id呢 这样是因为我的方法定义是

Integer delCatgory(Long id);这样的  就跟调用一样,你参数名字是什么这里取就是什么,如果是上面保存的的那种实体类可以直接取实体类字段

删除返回的是影响的行数

删除分类的 因为我的博客没想要删除博客
<delete id="delCatgory" parameterType="java.lang.Long">
        DELETE FROM dic_catgory WHERE id=#{id}
</delete>

3.更新

重点了!更新这里是使用了语句的  在里面我使用了trim语句 其中有几个属性需要介绍

prefix="("表示在其内部的字符串前面加一个(

suffix=")"表示在其内部的字符串后面加上一个)

prefixOverrides=","表示在字符串前去掉一个,

suffixOverrides=","表示在字符串后面去掉一个,

这几个属性是很有用的在字符串拼接的时候,像保存记录和更新记录,使用trim和if可以使这些语句很灵活,没有的字段就不更新,要不然得写多少条重复的语句才能满足情况,不然就会更新掉已有的数据为null了。

if语句就很熟悉了 里面属性就是test 表示要判断的条件 这里判断的就是博客的字段是否有值没有值就不让这段字符串插入。

更新语句也是返回的影响的行数的integer类型

划重点了这里
<update id="updateBlogById" parameterType="Blog"  >
        UPDATE h_blog set
        <trim  suffixOverrides="," >
            <if test="title!=null">
                title=#{title},
            </if>
            <if test="mdContent!=null">
                mdContent=#{mdContent},
            </if>
            <if test="content!=null">
                content=#{content},
            </if>
            <if test="lookNum!=null">
                lookNum=#{lookNum},
            </if>
            <if test="likeNum!=null">
                likeNum=#{likeNum},
            </if>
            <if test="commentNum!=null">
                commentNum=#{commentNum},
            </if>
            <if test="modifyTime!=null">
                modifyTime=#{modifyTime},
            </if>
            <if test="tagIds!=null">
                tagIds=#{tagIds}
            </if>
            <if test="categoryId!=null">
                categoryId=#{categoryId},
            </if>
            <if test="blogHeader!=null">
                blogHeader=#{blogHeader},
            </if>
        </trim>
            WHERE id=#{id}
    </update>

4.最重要的 就是查询了。也是平常开发中使用最多的语句了

根据难易将介绍查询

4.1

最简单的查询 入参是categoryId比如 findBlogByCategoryId(Long categoryId);这样子  在里面取的时候就直接#{categoryId}

返回值是Blog 这里可能会有疑问了  这样返回的应该是list 其实就是list 但是只要声明容器里的类型就好了 然后在方法那边定义返回类型坐等收货就好啦。mybatis会自动帮我们放入容器中交给我们的

根据分类查询返回博客list
<select id="findBlogByCategoryId" parameterType="java.lang.Long" resultType="Blog">
        SELECT * FROM h_blog WHERE categoryId=#{categoryId} ORDER BY id DESC
    </select>

4.2

这个也是我最近才get到的真的看到感觉很巧妙了。根据传入的categoryId 判断博客表的tagIds字符串里面有没有这个id如果有就返回 其实这个categoryId我放的是tagIds但是不想再在实体类里加字段了就这样写了。也不难理解,就是数据库进行了字段搜索返回的也是list

<select id="findBlogByTagId" parameterType="java.lang.Long" resultType="Blog">
        SELECT * FROM h_blog WHERE FIND_IN_SET(#{categoryId},tagIds) ORDER BY id DESC
    </select>

4.3

最后的这个比较难一点(应该是比较麻烦)但是实际中这种也挺常用的,毕竟数据库不能每个表都放很多数据所以才有分表,但是每个表的数据大多都有关联要一起用。所以拿博客举例子我要 取出一个博客 然后我要将博客中的评论封装成list放到博客的实体类中。首先要在博客的bean中新加一个属性就是private List<Comment> comment; 记得getter和setter哦

然后要设置一个resultMap

这些都是查的文档总结出来的,也有看官方文档看一些基础的语句
其实resultMap还有一个association但是还没有仔细去看比较想去实现,相信不久会用到的因为总要连接其他的表展示数据的如果不用容器返回就要使用到association了 自己摸索还是很慢的 哭哭QAQ

不过现在看错误的能力增强了,很精准的判错还是很省时间的(^-^)V

这里要先设置返回类型 为resultMap 就是下面的这样子 jdbcType是在数据库存储的类型 javaType是bean中的类型 property是bean中字段名字 column是查询返回数据的字段名字支持as改名所以如果改了要写改过的名字哦

javaType支持的字段名称连接http://www.cnblogs.com/thinkingandworkinghard/p/7606299.html没有的不要用会报错说枚举中没有这个类型

因为我要返回评论的list所以我下面加了collection块

其中也是有几个属性 collection行上的property属性声明的是该list在博客bean中的字段名字 ofType是list容器中的类型

里面result的属性作用和上面的一样就不再赘述了  下下面是查询 有二级左查询(其实我也不知道该叫什么)

说道查询我要提一嘴了:之前公司大哥提问过我这个外连接和内连接查询效率问题,在翻阅了文档和实际演示之后其实他们效率差不多如果在语句写的很好的情况下比如约束条件的顺序,连接主从表顺序之类的。所以我觉得外连接查询最好的使用场景其实是它的连接表的功能,会很容易让人理解连接出的结果表模型所以就更容易让人使用。


<resultMap id="blogMap" type="Blog" >
        <id property="id" column="id" jdbcType="BIGINT" javaType="Long"/>
        <result property="userId" column="userId" jdbcType="BIGINT"  javaType="Long"/>
        <result property="title" column="title" jdbcType="VARCHAR" javaType="String"/>
        <result property="content" column="content" jdbcType="VARCHAR" javaType="String"/>
        <result property="createTime" column="createTime" jdbcType="TIMESTAMP" javaType="Date"/>
        <result property="lookNum" column="lookNum" jdbcType="BIGINT" javaType="Long"/>
        <result property="likeNum" column="likeNum" jdbcType="BIGINT" javaType="Long"/>
        <result property="commentNum" column="commentNum" jdbcType="BIGINT" javaType="Long"/>
        <result property="modifyTime" column="modifyTime" jdbcType="TIMESTAMP" javaType="Date"/>
        <result property="tagIds" column="tagIds" jdbcType="VARCHAR" javaType="String"/>
        <result property="categoryId" column="categoryId" jdbcType="BIGINT" javaType="Long"/>
        <result property="blogHeader" column="blogHeader" jdbcType="VARCHAR" javaType="String"/>
        <!--property是Blog实体类中属性名 ofType是集合中类型 column是集合类型的主键 select是查询方法 可以是mapper的也可以是其他mapper的要写好路径 -->
        <!--<collection property="comment" ofType="Comment" select="" />-->
        <collection property="comment" ofType="Comment" >
            <!--这里面的column是查询出来结果集字段名字-->
            <id column="c_id" property="id" />
            <result column="c_userId" property="userId" />
            <result column="c_content" property="content" />
            <result column="c_parentId" property="parentId" />
            <result column="c_createTime" property="createTime" />
            <result column="c_nickname" property="nickname" />
            <result column="c_header" property="header" />
        </collection>
    </resultMap>

 这个是我的查询语句 其查询出来是将三个表连接到一起,有两个左连接可能不容易理解一开始我以为是第二个左联是将前面的左联的结果当主表进行第二次左联,但是我在前面的展示字段添加发现是可以添加的 所以我觉得这个左联是一起左联的。 只不过将这样写会更直观

<select id="findBlogAndComment" resultMap="blogMap" parameterType="java.lang.Long" >
        select hc.id c_id , hc.userId c_userId , hc.content c_content , hc.parentId c_parentId , hc.createTime c_createTime ,
        hu.nickname c_nickname , hu.header c_header ,
        hb.*
        from h_comment hc LEFT JOIN h_user hu on hc.userId = hu.id
        LEFT JOIN h_blog hb on hc.blogId=hb.id
        where hb.id=#{id}
    </select>

效果展示

 

就到这里了。共勉

(预计还会有第二篇总结,到我使用熟练会将其他的方法展示出来)

PS:写这个总结用了四十多分钟  总共写的话花在这个上面时间并不多 ,大多时间在查阅文档和写dao、service、controller方法上面(最怕这个麻烦事了但是还是要写TAT) 所以总体不难只要了解到位,错两次就会了!!!