Mybatis动态SQL学习笔记

Mybatis的动态SQL

1、什么是动态SQL?

概念: 搞清楚什么是动态SQL?

回答:动态SQL就是指根据不同的条件生成不同的SQL语句

核心:

  • 利用不同的参数,就会生成不同的SQL语句。

  • Mybatis提供了一些动态SQL专用的标签,根据它的规则,它会比较智能的执行一些SQL拼接/转换的操作。来达到实现动态SQL的目的。

  • 利用动态SQL能够简化我们开发时使用的SQL语句,将我们从这种复杂的工作中解放出来,提高业务的开发效率。

Mybatis中的动态SQL对应的四大标签:

  • if
  • choose(when,otherwise)
  • trim(where,set)
  • foreach
2、搭建环境:

0、创建博客表:

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT '博客id',
  `title` varchar(100) NOT NULL COMMENT '博客标题',
  `author` varchar(30) NOT NULL COMMENT '博客作者',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8


1、创建一个基础的工程:(项目结构如下:)

在这里插入图片描述

2、导入相关的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>Mybatis-Test</artifactId>
        <groupId>edu.nwu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Mybatis-05</artifactId>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>

        <dependency>
            <groupId> org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>



    </dependencies>

</project>

3、编写MyBatis核心配置文件:(在settings中开启驼峰命名的自动转换)

开启驼峰命名自动转换的作用:

  • 将数据库带有_的字段与pojo类的属性驼峰命名相关联。(一些数据库的规范就是使用下划线作为分隔符)

  • 例如pojo类有个属性叫 userName,数据库对应字段叫user_name。

注意:一定要在Seetings中开启日志系统,这样可以查看动态SQL拼接的结果,方便调试!

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--xml 中元素的标签上下位置是有要求的-->
    <!-- 将配置文件改为properties -->
    <properties resource="db.properties"/>

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
        <!--<setting name="logImpl" value="LOG4J"/>-->
    </settings>

    <!--包的别名配置-->
    <typeAliases>
        <!-- 给包下所有类起别名 -->
        <package name="edu.nwu.pojo"/>
        <!-- 给一个类起别名 alias是自己起的别名-->
        <!--<typeAlias type="edu.nwu.pojo.User" alias="User"/>-->
    </typeAliases>

    <!-- 一个environments 标签元素可以有多套配置 -->
    <environments default="development">
        <!-- 里面的每一个environment代表一个具体的环境 -->
        <environment id="development">
            <!--transactionManager 事务管理器 -->
            <transactionManager type="JDBC"/>
            <!-- dataSource 数据源配置 -->
            <dataSource type="POOLED">
                <!-- 连接数据库的配置i-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="edu.nwu.mapper"/>
    </mappers>
</configuration>

对应的数据库配置文件:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8
username=root
password=123456

4、编写实体类:(需要与数据库对应:ORM)

package edu.nwu.pojo;

import lombok.Data;

import java.util.Date;
@Data
public class Blog {

    private String id;
    private String title;
    private String author;
    private Date create_time;
    private int views;

}

5、编写接口类(添加数据)

package edu.nwu.mapper;

import edu.nwu.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

	int addBlog(Blog blog);  
}

6、工具类:

IDUtils:产生随机的ID字符串!

package edu.nwu.utils;

import java.util.UUID;

public class IDUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
}

MybatisUtils:简化数据库连接(将工厂类等抽象到方法中)

package edu.nwu.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 工厂模式:
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }catch (IOException e){
            e.printStackTrace();
        }


    }

    // 获取sqlSession的连接:所有的增删改都需要我们手动提交事务
    public static SqlSession getSession(){

        return sqlSessionFactory.openSession();

    }


    // 如果你增加了true这个参数,它就会自动提交事务。(不需要session.commit()了)
    public static SqlSession getSession(boolean flag){
        return sqlSessionFactory.openSession(flag);

    }
}

7、接口类对应的 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="edu.nwu.mapper.BlogMapper">

    <insert id="addBlog" parameterType="Blog">
        insert into mybatis.blog (id, title, author, create_time, views) values
        (#{id},#{title},#{author},#{create_time},#{views});
    </insert>

</mapper>

8、编写测试类添加数据:

@Test
public void testAddBlog(){
        SqlSession session = MybatisUtils.getSession(true);
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Blog blog = new Blog();
        blog.setId(IDUtils.getId());
        blog.setTitle("Mybatis So Easy");
        blog.setAuthor("狂神说");
        blog.setCreate_time(new Date());
        blog.setViews(9999);
        int i = mapper.addBlog(blog);

        Blog blog2 = new Blog();
        blog2.setId(IDUtils.getId());
        blog2.setTitle("Mybatis So Easy");
        blog2.setAuthor("狂神说");
        blog2.setCreate_time(new Date());
        blog2.setViews(9999);
        int i1 = mapper.addBlog(blog2);

        Blog blog3 = new Blog();
        blog3.setId(IDUtils.getId());
        blog3.setTitle("Mybatis So Easy");
        blog3.setAuthor("狂神说");
        blog3.setCreate_time(new Date());
        blog3.setViews(9999);
        int i2 = mapper.addBlog(blog3);


    }

然后通过IDEA连接数据库修改其中的数据,最后达到如下图所示的结果:

在这里插入图片描述

3、动态SQL之IF标签:

1、接口类添加方法: getBlogByIf(Map map)

package edu.nwu.mapper;

import edu.nwu.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

    List<Blog> getBlogByIf(Map map);

    int addBlog(Blog blog);
}

2、在对应的配置文件中添加实现逻辑:

<select id="getBlogByIf" resultType="Blog" parameterType="map">
        select * from  blog where
        <if test="title!=null">
          title = #{title}
        </if>
  			<if test="author!=null">
  				and author = #{author}
  			</if>
 </select>

3、编写测试文件:(测试结果)

@Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("title","AAA");
        map.put("author","狂神说");
        List<Blog> blogByIf = mapper.getBlogByIf(map);
        for (Blog blog : blogByIf) {
            System.out.println(blog);
        }

    }

由于title和author字段都存在,所以执行时,会自动拼接为:(我们可以根据日志来获取它拼接出来的SQL语句效果,并以此来调试动态SQL的编写错误

select * from blog where title = ”AAA“ and author = "狂神说"

结果如下:

注意:Preparing: select * from blog where title = ? and author = ?

==>  Preparing: select * from blog where title = ? and author = ? 
==> Parameters: AAA(String), 狂神说(String)
<==    Columns: id, title, author, create_time, views
<==        Row: f8b576c95544409cb2bf4700d4f6f9a3, AAA, 狂神说, 2020-02-21 16:12:50.0, 9999
<==        Row: 87ec8ec9ad6b4c4ca282073be9b64322, AAA, 狂神说, 2020-02-21 16:13:49.0, 9999
<==      Total: 2
Blog(id=f8b576c95544409cb2bf4700d4f6f9a3, title=AAA, author=狂神说, create_time=null, views=9999)
Blog(id=87ec8ec9ad6b4c4ca282073be9b64322, title=AAA, author=狂神说, create_time=null, views=9999)

小结:

  • 这个拼接不是什么情况都适用的
  • 如果只给定author字段,会在where 后面拼接上一个and语句,这样不符合SQL的语法规则。
  • 后面会利用 Mybatis中的 where字段来改善这种情况。

备份:

<select id="getBlogByIf" resultType="Blog" parameterType="map">
    select * from  blog
    <where>
        <if test="title!=null">
            title = #{title}
        </if>
        <if test="author!=null">
            and author = #{author}
        </if>
    </where>
</select>
4、动态SQL之 trim(where, set)

1)利用 where标签 来改善刚才的 if 标签的不足之处:(我们刚才的where 是SQL的关键字,这里的where 是一个专有的标签!

<select id="getBlogByIf" resultType="Blog" parameterType="map">
    select * from  blog
    <where>
        <if test="title!=null">
            title = #{title}
        </if>
        <if test="author!=null">
            and author = #{author}
        </if>
    </where>
</select>

测试类:

@Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<String, String>();
//        map.put("title","AAA");
        map.put("author","狂神说");
        List<Blog> blogByIf = mapper.getBlogByIf(map);
        for (Blog blog : blogByIf) {
            System.out.println(blog);
        }

    }

结果:select * from blog WHERE author = ? 拼接后的字段

==>  Preparing: select * from blog WHERE author = ? 
==> Parameters: 狂神说(String)
<==    Columns: id, title, author, create_time, views
<==        Row: 46248845d2db4122b64ae2c9e3ff5465, Mybatis So Easy, 狂神说, 2020-02-21 16:08:05.0, 9999
<==        Row: 78b98934353e4c63be9fe2b6899575cd, Mybatis So Easy, 狂神说, 2020-02-21 16:10:02.0, 9999
<==        Row: 8d2509d052224ec5a77207b726ee59bc, Mybatis So Easy, 狂神说, 2020-02-21 16:10:36.0, 9999
<==        Row: f8b576c95544409cb2bf4700d4f6f9a3, AAA, 狂神说, 2020-02-21 16:12:50.0, 9999
<==        Row: 87ec8ec9ad6b4c4ca282073be9b64322, AAA, 狂神说, 2020-02-21 16:13:49.0, 9999
<==        Row: c09cb27e33074e9abdaea48d871b27ce, Spring So Easy, 狂神说, 2020-02-21 16:14:53.0, 9999
<==        Row: f37c98fb748a4c998e9ae58e6cd5a96e, 大数据 So Easy, 狂神说, 2020-02-21 16:17:54.0, 9999
<==        Row: 3821ffba1a514d93865893ce42e65b8e, 微服务 So Easy, 狂神说, 2020-02-21 16:19:21.0, 9999
<==        Row: 9dfd7f4f4d6b4b5598e3aeabb17b976f, Mybatis So Easy, 狂神说, 2020-02-21 16:19:21.0, 9999
<==        Row: 6a17e8672b0e40e68d572974b0446a10, Mybatis So Easy, 狂神说, 2020-02-21 16:19:21.0, 9999
<==      Total: 10
Blog(id=46248845d2db4122b64ae2c9e3ff5465, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=78b98934353e4c63be9fe2b6899575cd, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=8d2509d052224ec5a77207b726ee59bc, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=f8b576c95544409cb2bf4700d4f6f9a3, title=AAA, author=狂神说, create_time=null, views=9999)
Blog(id=87ec8ec9ad6b4c4ca282073be9b64322, title=AAA, author=狂神说, create_time=null, views=9999)
Blog(id=c09cb27e33074e9abdaea48d871b27ce, title=Spring So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=f37c98fb748a4c998e9ae58e6cd5a96e, title=大数据 So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=3821ffba1a514d93865893ce42e65b8e, title=微服务 So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=9dfd7f4f4d6b4b5598e3aeabb17b976f, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=6a17e8672b0e40e68d572974b0446a10, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)

注意:

  • 利用where 标签装饰后的字段,会自动检查and 关键字
  • 当在map中只有author字段的时候,就会智能的摒弃掉and关键字
  • 当map中两个条件否符合的时候,其不会造成任何影响,SQL仍然按照预期那样进行双条件匹配查询。

trim 原理:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

trim中各个字段释义:

  • Prefix :前缀,即为需要在trim前加的前缀关键字
  • prefixOverrides:前缀覆盖,即为:这些语句中存在前缀为 AND|OR 的语句需要进行智能拼接。
  • Suffix:后缀,即为需要在trim中的语句执行完再加的语句
  • suffixOverrides:后缀覆盖,即为:这些语句中存在后缀为,的语句需要进行只能拼接。
  • 注意:以上字段均可出现在trim中,甚至四个全部出现也可以,它会自动地进行拼接,但一般用不到这么多。

2)利用 set 标签来进行数据修改:

<update id="updateBlog" parameterType="map">
    update mybatis.blog
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>

1、编写对应的接口方法:List queryBlogChoose(Map map);

package edu.nwu.mapper;

import edu.nwu.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

    List<Blog> getBlogByIf(Map map);

    int addBlog(Blog blog);

    int updateBlog(Map map);
}

2、在配置文件中添加实现逻辑:

<update id="updateBlog" parameterType="map">
        update blog set 
        <if test="title!=null">
            title = #{title},
        </if>
        <if test="author!=null">
            author = #{author}
        </if>
        where id = #{id}
    </update>

3、编写测试类:

    @Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("title","XXXX");
        map.put("author","小波说");
        map.put("id","87ec8ec9ad6b4c4ca282073be9b64322");
//        List<Blog> blogByIf = mapper.getBlogByIf(map);
//        for (Blog blog : blogByIf) {
//            System.out.println(blog);
//        }
        int i = mapper.updateBlog(map);
        System.out.println(i);

    }

4、结果:Preparing: update blog set title = ?, author = ? where id = ?

==>  Preparing: update blog set title = ?, author = ? where id = ? 
==> Parameters: XXXX(String), 小波说(String), 87ec8ec9ad6b4c4ca282073be9b64322(String)
<==    Updates: 1
1

但当只有参数:title 的时候就会报错,因为多了一个逗号。

我们使用set标签来改善这个问题:

<update id="updateBlog" parameterType="map">
        update blog
        <set>
            <if test="title!=null">
                title = #{title},
            </if>
            <if test="author!=null">
                author = #{author}
            </if>
        </set>

        where id = #{id}

    </update>

编写测试类进行测试:

@Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("title","XXXX");
//        map.put("author","小波说");
        map.put("id","87ec8ec9ad6b4c4ca282073be9b64322");
//        List<Blog> blogByIf = mapper.getBlogByIf(map);
//        for (Blog blog : blogByIf) {
//            System.out.println(blog);
//        }
        int i = mapper.updateBlog(map);
        System.out.println(i);

    }

得到结果:Preparing: update blog SET title = ? where id = ?

==>  Preparing: update blog SET title = ? where id = ? 
==> Parameters: XXXX(String), 87ec8ec9ad6b4c4ca282073be9b64322(String)
<==    Updates: 1
1

小结:

  • 同where 标签一样,set标签页智能地实现了自动去除逗号的功能,使得动态SQL的拼接更为简单。
  • where和set 标签能够实现动态拼接的原理都是因为使用了:trim() ,具体实现可以参考Mybatis的官方文档中的动态SQL一栏。

trim原理

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
4、动态SQL之choose(when, othrewise)

1、在接口中添加方法:List<Blog> queryBlogChoose(Map map);

package edu.nwu.mapper;

import edu.nwu.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

    List<Blog> getBlogByIf(Map map);

    int addBlog(Blog blog);

    List<Blog> queryBlogChoose(Map map);

    int updateBlog(Map map);
}

2、在配置文件中添加实现逻辑:

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <choose>
                <when test="title != null">
                    title = #{title}
                </when>
                <when test="author != null">
                    and author = #{author}
                </when>
                <otherwise>
                    and views = #{views}
                </otherwise>
            </choose>
        </where>
    </select>

3、编写测试类:

    @Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, Integer> map = new HashMap<String, Integer>();
//        map.put("title","asdf");
//        map.put("author","1111");
//        map.put("id","87ec8ec9ad6b4c4ca282073be9b64322"); // put了也没用,在SQL中没有相关字段读取
        map.put("views",9999);
        List<Blog> blogByIf = mapper.queryBlogChoose(map);
        for (Blog blog : blogByIf) {
            System.out.println(blog);
        }


    }

4、结果如下:select * from mybatis.blog WHERE views = ?

==>  Preparing: select * from mybatis.blog WHERE views = ? 
==> Parameters: 9999(Integer)
<==    Columns: id, title, author, create_time, views
.......

5、改写测试代码:

    @Test
    public void testSelectByIf(){
        SqlSession session = MybatisUtils.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("title","asdf");
        map.put("author","1111");
//        map.put("id","87ec8ec9ad6b4c4ca282073be9b64322"); // put了也没用,在SQL中没有相关字段读取
//        map.put("views",9999);
        List<Blog> blogByIf = mapper.queryBlogChoose(map);
        for (Blog blog : blogByIf) {
            System.out.println(blog);
        }
    }

6、测试结果:select * from mybatis.blog WHERE title = ?

==>  Preparing: select * from mybatis.blog WHERE title = ? 
==> Parameters: asdf(String)
<==      Total: 0

分析总结

  • choose 跟 Java 中的 switch 很像,只能选择一个合适的执行。
  • Otherwise只在choose 中选项都失效的时候才会执行,类似于Java中switch中的default
5、动态SQL之SQL片段:

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用SQL标签抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    
  2. 在需要使用的地方使用Include标签引用即可

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>
    

注意事项:

  • 最好基于单表来定义SQL片段!
  • 不要存在where标签
6、Foreach

相关概念:

在这里插入图片描述

注意:看清楚每一个标识符都代表什么意思。

其中,colooection代表的是通过接口方法中传递进来的参数名,当条用接口方法的参数是:map集合的时候,其代表了Map中对应的键,传递进去的是map中键对应的数值

1、编写接口的实现方法:List<Blog> queryBlogForeach(Map map);

package edu.nwu.mapper;

import edu.nwu.pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {

    List<Blog> getBlogByIf(Map map);

    int addBlog(Blog blog);

    List<Blog> queryBlogChoose(Map map);

    int updateBlog(Map map);

    List<Blog> queryBlogForeach(Map map);

}

2、修改对应的配置文件:

<select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from mybatis.blog

        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id = #{id}
            </foreach>
        </where>

</select>

执行结果:Preparing: select * from mybatis.blog WHERE ( id = ? or id = ? or id = ? )

==>  Preparing: select * from mybatis.blog WHERE ( id = ? or id = ? or id = ? ) 
==> Parameters: 46248845d2db4122b64ae2c9e3ff5465(String), 78b98934353e4c63be9fe2b6899575cd(String), 8d2509d052224ec5a77207b726ee59bc(String)
<==    Columns: id, title, author, create_time, views
<==        Row: 46248845d2db4122b64ae2c9e3ff5465, Mybatis So Easy, 狂神说, 2020-02-21 16:08:05.0, 9999
<==        Row: 78b98934353e4c63be9fe2b6899575cd, Mybatis So Easy, 狂神说, 2020-02-21 16:10:02.0, 9999
<==        Row: 8d2509d052224ec5a77207b726ee59bc, Mybatis So Easy, 狂神说, 2020-02-21 16:10:36.0, 9999
<==      Total: 3
Blog(id=46248845d2db4122b64ae2c9e3ff5465, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=78b98934353e4c63be9fe2b6899575cd, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)
Blog(id=8d2509d052224ec5a77207b726ee59bc, title=Mybatis So Easy, author=狂神说, create_time=null, views=9999)

3、分析总结:

  • Foreach 其实就是for循环遍历先执行,执行前拼接上open符号("("),
  • 在每一次循环中执行逻辑:id = #{id} ,这个 {}里的id 是item的别名,就是collecition中的一个个数值。
  • 而且,每执行一次循环都要添加一个分隔符:separator(“or”)
  • 循环完毕的时候,执行close(")")
  • 最终,拼接完毕!select * from mybatis.blog WHERE ( id = ? or id = ? or id = ?
7、动态SQL编写技巧:

技巧:

  • 明白动态SQL的本质就是通过逻辑代码来拼接SQL语句(为了高效开发)

  • 熟记if、where、set、when、otherwise、Foreach等标签的写法及作用

  • 核心技巧:开启日志系统,根据日志返回的拼接结构动态调整xml文件中动态SQL的写法

8、动态SQL29道练习题:

方式:

  • 打开老师的订单管理项目,将其中每一个Mapper接口中对应的方法都实现一遍

核心思维

  • 注意配合网站的运行效果来思考业务逻辑是什么,需要用连接查询吗?(要看自己构建的类对象属性只使用从数据库中查出来的字段够不够填充给对象,不够的话,就需要用联表查询)

  • 假设如果筛选的字段是一段纯文字的字段,需不需要用模糊查询呢?

  • 在编写动态SQL时,使用trim有时候比直接使用set或者where更方便,因为它能设置4个属性,而且编写SQL的随意性也可以更高,自动化拼接更有效。

  • 如果返回的表字段名称和实体类属性名称不一致,要不然用resultMap进行转换,要么直接将搜索出来的表字段起别名(起别名是一个聪明的方法)

项目报错解决方案:

  • Mybatis ,细节很重要。一些十分细小的错误(多余的字母、空格、大小写),会引起程序报错
  • 排错方法:倒着看,只看报错的原因即可,要么调试,要么百度报错原因
  • 逻辑不能理解(这个是正常现象,必须结合业务逻辑和功能才知道为何这么做!)
X、SQL面试相关:

慢SQL 1s 1000s

面试高频

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值