Mybatis单表操作之普通操作、模糊查询、分页查询、动态SQL

目录

前言

1、构建数据库

2、 普通操作

3、模糊查询

4、分页查询

​5、动态SQL


前言

最近有点学累了,很久没有学习新东西了,花了一个晚上的时间归纳和整理了Mybatis对表的操作,主要是对单表进行操作,包括基本的单表操作CRUD,以及模糊查询、分页查询及动态SQL等 。后面会陆续把一对多,多对一查询及多表查询整理一下。

1、构建数据库

在学习之前,你首先要先建一个数据库,本文用Navicat建了一个数据库ssmbuild,里面放了一张books表。然后,把核心配置文件、实体类、工具类等等先写好,该部分可以参考博主以往的博客

CREATE DATABASE `ssmbuild`;

USE `ssmbuild`;

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
`bookID` INT(10) NOT NULL  COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
 PRIMARY KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT  INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢'),
(4,'Java',15,'Java修仙手册'),
(5,'C++',25,'C++致命宝典');

2、 普通操作

(1) 查询书籍

查询书籍,既可以查询全部书籍,也可以根据id去查询,当然后面会用到动态查询(可以根据某个字段进行模糊查询)。由于SQL语句较简单,所以这里用注解的方式实现 ,因为查询所有书籍会返回若干条记录,所以用集合来保存,最后用增强for去打印集合

//查询所有的书籍
    @Select("select *from ssmbuild.books")
    List<Books> queryAllBooks();
//根据BookId查询相应的书籍
    @Select("select *from ssmbuild.books where bookID=#{id}")
    Books queryBooksById(@Param("id") int BookID);
@Test
    public void test1() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        List<Books> allBooks = mapper.queryAllBooks();
        for (Books books : allBooks) {
            System.out.println(books);
        }
        sqlSession.close();
    }
 @Test
    public void test5(){
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        Books books = mapper.queryBooksById(5);
        System.out.println(books);
        sqlSession.close();
    }

(2) 增加书籍

可以用带参构造方法和map键值对来增加书籍,返回类型void和int均可,注意实体类的成员变量属性要与数据库字段名一致,否者用resultmap将column与properties对应起来也是可以滴

    //用带参构造方法增加书籍
    int addBooks(Books books);
    //用map键值对增加书籍
    int addBooks2(Map<String, Object> map);
<insert id="addBooks" parameterType="books">
        insert into ssmbuild.books (bookID, bookName, bookCounts, detail)
        VALUES (#{bookID}, #{bookName}, #{bookCounts}, #{detail})
    </insert>
    <insert id="addBooks2" parameterType="map">
        insert into ssmbuild.books (bookID, bookName, bookCounts, detail)
        VALUES (#{bookID}, #{bookName}, #{bookCounts}, #{detail})
    </insert>
 @Test
    public void test6(){
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        int res = mapper.addBooks(new Books(8, "kali", 1000, "kali学的好,号子蹲的早"));
        if (res>0){
            System.out.println("增加书籍成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    public void test7(){
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        Map<String,Object> map=new HashMap<>();
        map.put("bookID",9);
        map.put("bookName","一支红杏出墙来");
        map.put("bookCounts",300);
        map.put("detail","小王老师又一巨作");
        int res = mapper.addBooks2(map);
        if (res>0){
            System.out.println("插入成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

注:增删改, 均变动了数据库记录,需要提交事务,有两种方式:上面代码commit方式是一种,还有一种一劳永逸的方式,即将工具类里调用openSession的方法改为true。

(3) 删除书籍

这里是根据id去删除书籍,后面可以用动态sql之foreach去批量删除书籍 

int deleteBooks(@Param("id") int BookID);
<delete id="deleteBooks" parameterType="books">
        delete
        from ssmbuild.books
        where bookID = #{id}
    </delete>

 (4)更新书籍

普通的更新,除了主键外,所有的字段都需要进行更新,后面可以用动态更新,哪里想更,更哪里,妈妈再也不要担心我的学习了。 

int updateBooks(Books books);
<update id="updateBooks" parameterType="books">
        update ssmbuild.books
        set bookName  = #{bookName},
            bookCounts=#{bookCounts},
            detail=#{detail}
        where bookID = #{bookID}
    </update>
@Test
    public void test10(){
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        int res = mapper.updateBooks(new Books(7, "数据库", 1000, "从入库到跑路"));
        if (res>0){
            System.out.println("更新成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

 3、模糊查询

(1)模糊查询"%",可匹配任意类型和长度的字符 

@Select("select *from ssmbuild.books where detail like '%小王老师%'")
    List<Books> queryLikeBooks();

查询结果:

(2)模糊查询"_",可匹配单个任意字符,它常用来限制表达式的字符长度

@Select("select *from ssmbuild.books where detail like '从_门到__'")
    List<Books> queryLikeBooks1();

查询结果: 

 注:模糊查询有很多种,常用的有这两种,博主偷懒,所以用的注解的方式

4、分页查询

分页查询有limit和RowBounds分页,limit分页用的较多,limit a,b,a表示起始索引,从0开始,表示第一条记录, b表示是指从第a+1条开始,取b条。

 @Select("select *from ssmbuild.books limit 5,2")
    List<Books> queryLimitBooks();

 查询结果:上述表示从第六条记录开始,取两条记录,所以查询结果的id应该为6,7

 5、动态SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过JDBC或其它类似的框架,你应该就能理解根据不同条件拼接SQL语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

(1)动态SQL之IF

//动态SQL之IF选择查询
    List<Books> queryIfBooks(Map<String, Object> map);
<select id="queryIfBooks" parameterType="map" resultType="books">
        select *from ssmbuild.books where 1=1
            <if test="bookName!=null">
                bookName like #{bookName}
            </if>
            <if test="detail!=null">
                and detail like #{detail}
            </if>
    </select>
@Test
    public void test11() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        HashMap<String,Object> map =new HashMap<String,Object>();
        map.put("detail","%小王%");
        //map.put("bookName","%Java%");
        List<Books> allBooks = mapper.queryIfBooks(map);
        for (Books books : allBooks) {
            System.out.println(books);
        }
        sqlSession.close();
    }

为啥这里要用sql注入(where1=1)的方式 ?这里“where 1”,“where true”也都可以 ,去掉1=1,你就能发现问题所在了。只要跳过bookName字段,对detail字段进行查询时,系统就拼接不起来了,正常语句where后面都要加上判断的条件。所以where1=1的方式能保证对查询条件进行拼接并保证查询能进行下去。当然这里推荐使用where标签,where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句,什么意思呢?就是说在匹配不到合适的字段条件时,where字段不加上去,就成了“select *from  ssmbuild.books”了,变成查询所有字段了。若子句的开头为 “AND” 或 “OR”,where 元素会将它们去除。像下面的错误,用上where标签,就会舍弃and,成了“select *from  ssmbuild.books where detail like 条件”,能查询出与detail标签相关的内容了。

加上where标签,用IF同时对bookName和detail进行模糊查询时,你会发现什么都查不出来,也许你会说博主这不是在胡说八道吗,但我想在这先卖个关子,这就是上面为啥要先注释掉一条了。

(2) 动态Sql之set

set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

int updateSetBooks(Map<String,Object> map);
<update id="updateSetBooks" parameterType="map">
        update ssmbuild.books
        <set>
            <if test="bookName!=null">bookName=#{bookName},</if>
            <if test="bookCounts!=null">bookCounts=#{bookCounts},</if>
            <if test="detail!=null">detail=#{detail}</if>
        </set>
        where bookID=#{bookID}
    </update>
@Test
    public void test12() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        HashMap<String,Object> map =new HashMap<String,Object>();
        map.put("bookID",7);
        map.put("bookName","大数据");
        int res = mapper.updateSetBooks(map);
        if (res>0){
            System.out.println("更新成功!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

这里用set对7号书籍的书籍名称进行修改,原表是数据库,现在应该是改成大数据了。 

(3)动态SQL之Choose

动态SQL之Choose,跟if查询类似,但if需要同时满足多个查询条件,而choose满足一个就会查出,现在就解开上面卖的关子。

List<Books> queryChooseBooks(Map<String,Object> map);
<select id="queryChooseBooks" parameterType="map" resultType="books">
        select *from ssmbuild.books
        <where>
            <choose>
                <when test="bookName!=null">
                    bookName like #{bookName}
                </when>
                <when test="bookCounts!=null">
                   AND bookCounts like #{bookCounts}
                </when>
                <when test="detail!=null">
                    AND detail like #{detail}
                </when>
                <otherwise>AND featured = 1 </otherwise>
            </choose>
        </where>
    </select>
 @Test
    public void test13() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        HashMap<String,Object> map =new HashMap<String,Object>();
        map.put("detail","%小王%");
        map.put("bookName","%Java%");
        List<Books> allBooks = mapper.queryChooseBooks(map);
        for (Books books : allBooks) {
            System.out.println(books);
        }
        sqlSession.close();
    }

这里的junit测试单元是不是在哪见过?对的,跟if查询不要说一毛一样,简直就是双胞胎,也就方法名不同而已。那结果呢?话不多说,看图。if要条件全部满足才能查出,而choose查到一个就不会继续查了,有点类似多分支Switch语句。

(4) 动态SQL之foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值(官方文档说的很清楚)。我们这用foreach实现批量删除,当然还可以用来实现批量增加记录。

//使用foreach批量删除书籍
    void deleteSomeBooks(List<Integer> list);

注:尽量不要像博主一样在配置文件中加中文 ,有时会报错,具体怎么解决,参考博主以往文章

<delete id="deleteSomeBooks" parameterType="map">
        <!--collection: 表示类型,如果参数是数组,就写成array,如果是集合,就写成list
        item: 表示集合中每一个元素进行迭代时的别名,自己随便取名
        index,指定一个名字,用于表示在迭代过程中,每次迭代到的位置
        -->
        delete
        from ssmbuild.books
        where bookID in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

这里是删除id=9到id=18之间的书籍记录 

 @Test
    public void test8(){
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        ArrayList<Integer> list = new ArrayList<>();
        for (int num=9;num<19;num++){
            list.add(num);
        }
        mapper.deleteSomeBooks(list);
        sqlSession.commit();
        sqlSession.close();
    }

(5)动态SQL之trim

自定义trim元素,trim可以定制set和where功能,即不用手动去写"and","or",","等。其实set里的“,”及where里的“and”不加也不会报错,但为了书写规范还是加吧。所以感觉trim有点鸡肋。

int updateTrimBooks(Map<String,Object> map);
<update id="updateTrimBooks" parameterType="map">
        update ssmbuild.books
        <trim prefix="SET" suffixOverrides=",">
            <if test="bookName!=null">bookName=#{bookName}</if>
            <if test="bookCounts!=null">bookCounts=#{bookCounts}</if>
            <if test="detail!=null">detail=#{detail}</if>
        </trim>
        where bookID=#{bookID}
    </update>
@Test
    public void test14() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BookMapper mapper = sqlSession.getMapper(BookMapper.class);
        HashMap<String,Object> map =new HashMap<String,Object>();
        map.put("bookID",7);
        map.put("bookName","数据库");
        int res = mapper.updateTrimBooks(map);
        if (res>0){
            System.out.println("更新成功!");
        }
        sqlSession.close();
    }

 我又把大数据改为数据库了,有点强迫症,结果如下:

所有的项目文件结构如下所示:

猜你喜欢

转载自blog.csdn.net/qq_53860947/article/details/123674037