1. 程式人生 > 其它 >MyBatis(7)——動態SQL

MyBatis(7)——動態SQL

技術標籤:javamybaitsjavamybatis

動態SQL指的是根據不同的查詢條件 , 生成不同的Sql語句。
MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。

  -------------------------------
  - if
  - choose (when, otherwise)
  - trim (where, set)
  - foreach
  -------------------------------

1.1 環境搭建

搭建資料庫

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

在這裡插入圖片描述
構建實體類

@Data
public class Blog {
    private String id;
    private String title;
    private
String author; private Date createTime; private int views; }

編寫介面類

public interface BlogMapper {
}

編寫Mapper.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.kuang.mapper.BlogMapper"> </mapper>

核心檔案的配置(mybatis-config.xml)

<?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>
<!--    引入外部配置檔案-->
    <properties resource="db.properties"/>
    
    <settings>
<!--        標椎日誌輸出-->
        <setting name="logImpl" value="LOG4J"/>
<!--        駝峰對映-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>


    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>


<!--    繫結介面-->
    <mappers>
        <mapper class="com.xxxx.dao.BlogMapper"/>
    </mappers>

</configuration>

日誌檔案配置log4j.properties

#將等級為DEBUG的日誌資訊輸出到console和file這兩個目的地,console和file的定義在下面的程式碼
log4j.rootLogger=DEBUG,console,file

#控制檯輸出的相關設定
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#檔案輸出的相關設定
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/xxxx.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日誌輸出級別
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

db.properties檔案的配置

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

pom.xml檔案的配置

<?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</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>myBatis_01</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <!--可能出現問題說明:Maven靜態資源過濾問題-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>

    </dependencies>

</project>

工具類的編寫

public class IDUtil {
    public static String genId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
}
package com.xxxx.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;

// SqlSessionFactory ---> SqlSession
public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            // 第一步 : 獲取sqlSessionFactory物件
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//    既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的例項。
//    SqlSession 提供了在資料庫執行 SQL 命令所需的所有方法
    public static SqlSession getSqlSesion() {
//        自動提交事務
        return sqlSessionFactory.openSession(true);
    }
}

插入資料(初始化部落格)
Mapper

package com.xxxx.dao;

import com.xxxx.pojo.Blog;

public interface BlogMapper {
    int addBlog(Blog blog);
}

Mapper.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.xxxx.dao.BlogMapper">

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

Test

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.Date;


public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);

           Blog blog = new Blog();
           blog.setId(IDUtil.genId());
           blog.setTitle("Mybatis如此簡單");
           blog.setAuthor("zs");
           blog.setCreateTime(new Date());
           blog.setViews(9999);

           mapper.addBlog(blog);

           blog.setId(IDUtil.genId());
           blog.setTitle("Java如此簡單");
           mapper.addBlog(blog);

           blog.setId(IDUtil.genId());
           blog.setTitle("Spring如此簡單");
           mapper.addBlog(blog);

           blog.setId(IDUtil.genId());
           blog.setTitle("微服務如此簡單");
           mapper.addBlog(blog);

       }
    }

}

在這裡插入圖片描述環境搭建完畢!!!

1.2 if

編寫介面類

    List<Blog> queryBlogif(Map map);

編寫XML檔案

    <select id="queryBlogif" parameterType="map" resultType="com.xxxx.pojo.Blog">
        select * from blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>

編寫測試

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Map<String, String> map = new HashMap<String, String>();
           map.put("title","Mybatis如此簡單");
           map.put("author","zs");
           List<Blog> blogs = mapper.queryBlogif(map);
           for (Blog blog : blogs) {
               System.out.println(blog);
           }
       }
    }
}

在這裡插入圖片描述
但是會出現問題

去掉不合規矩的 1=1

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

列印一下問題

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

用Where解決問題

1.3 Where

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

    </select>

注意我的測試類

public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Map<String, String> map = new HashMap<String, String>();
//           map.put("title","Mybatis如此簡單");
           map.put("author","zs");
           List<Blog> blogs = mapper.queryBlogif(map);
           for (Blog blog : blogs) {
               System.out.println(blog);
           }
       }
    }
}

控制檯列印的sql語句
自動將 and 去掉了

Preparing: select * from blog WHERE author = ? 

1.4 choose

有時候,我們不想用到所有的查詢條件,只想選擇其中的一個,查詢條件有一個滿足即可,使用 choose 標籤可以解決此類問題,類似於 Java 的 switch 語句。

編寫介面方法

List<Blog> queryBlogChoose(Map map);

mapper.xml

    <select id="queryBlogChoose" parameterType="map" resultType="com.xxxx.pojo.Blog">
        select * from blog
            <where>
                <choose>
                    <when test="title != null">
                        title = #{title}
                    </when>
                    <when test="author != null">
                        and author = #{author}
                    </when>
                </choose>
            </where>
    </select>

測試類

public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Map<String, String> map = new HashMap<String, String>();
           map.put("title","Mybatis如此簡單");
           map.put("author","zs");
           List<Blog> blogs = mapper.queryBlogChoose(map);
           for (Blog blog : blogs) {
               System.out.println(blog);
           }
       }
    }
}

注意列印

 map.put("title","Mybatis如此簡單");
           map.put("author","zs");
Preparing: select * from blog WHERE title = ? 

1.5 Set

編寫介面

int updateBlog(Map map);

mapper.xml

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

測試類

public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Map<String, String> map = new HashMap<String, String>();
           map.put("author","zj");
           map.put("id" , "8283887ec6414603972d4a98ce26599d");
           mapper.updateBlog(map);
       }
    }
}

注意列印

update blog SET author = ? where id = ?; 

1.6 sql片段

有時候可能某個 sql 語句我們用的特別多,為了增加程式碼的重用性,簡化程式碼,我們需要將這些程式碼抽取出來,然後使用時直接呼叫。

提取SQL片段

 <sql id="if">
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </sql>

引用SQL片段

 <update id="updateBlog" parameterType="map">
        update blog
        <set>
            <include refid="if"></include>
        </set>
        where id = #{id};
    </update>

注意列印

Parameters: zj(String), 8283887ec6414603972d4a98ce26599d(String)

1.7 Foreach

將資料庫中前三個資料的id修改為1,2,3;
需求:我們需要查詢 blog 表中 id 分別為1,2,3的部落格資訊

編寫介面

List<Blog> queryBlogForeach(Map map);

mapper.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.xxxx.dao.BlogMapper">
    <!--
    collection:指定輸入物件中的集合屬性
    item:每次遍歷生成的物件
    open:開始遍歷時的拼接字串
    close:結束時拼接的字串
    separator:遍歷物件之間需要拼接的字串
    select * from blog where 1=1 and (id=1 or id=2 or id=3)
-->
   <select id="queryBlogForeach" parameterType="map" resultType="com.xxxx.pojo.Blog">
       select * from blog
       <where>
           <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
           id=#{id}
           </foreach>
       </where>
   </select>
</mapper>

注意測試類

public class DaoTest {
    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Map<String, List> map = new HashMap<>();
           List<Integer> ids = new ArrayList<>();
           ids.add(1);
           ids.add(2);
           ids.add(3);
           map.put("ids" , ids);
           List<Blog> blogs = mapper.queryBlogForeach(map);
           for (Blog blog : blogs) {
               System.out.println(blog);
           }
       }
    }
}

注意列印

Preparing: select * from blog WHERE ( id=? or id=? or id=? )