1. 程式人生 > 其它 >SQL模糊查詢的四種匹配模式

SQL模糊查詢的四種匹配模式

MyBatis-9.28

環境:

  • JDK1.8
  • Mysql5.7
  • maven 3.6.1
  • IDEA

SSM框架:配置檔案的,最好方式是看官方文件

1、簡介

1.1 什麼是Mybatis

  • MyBatis是一款優秀的持久層框架
  • 它支援定製Sql,儲存過程以及高階對映
  • Mybatis幾乎避免了所有的JDBC程式碼和手動設定引數以及獲取結果集
  • Mybatis支援簡單的Xml或註解來配置對映原生型別、介面和Java的POJO(Plain Old Java Objects 普通老式Java物件)為資料庫中的記錄
  • MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了[google code](
    https://baike.baidu.com/item/google
    code/2346604),並且改名為MyBatis 。2013年11月遷移到Github
  • iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAOs)

1.2 如何獲得MyBatis?

1.3 持久化

資料持久化

  • 持久化就是將程式的資料在持久狀態轉化為瞬時狀態的一個過程
  • 記憶體:斷電即失
  • 資料庫(jdbc),io檔案持久化
  • 生活:冷藏、罐頭

為什麼要持久化

  • 有些物件不能讓它丟掉

  • 記憶體太貴了

1.4 持久層

Dao層、Service層、Contrller層

  • 完成持久化工作的程式碼

  • 層界限十分明顯

1.5 為什麼要用Mybatis?

  • 方便將資料寫入資料庫中

  • JDBC操作複雜,Mybatis框架,簡化、自動化、框架

  • 不用Mybatis也可以,Mybatis容易上手和使用,但技術沒有高低之分

  • 優點

    • 簡單易學
    • 靈活
    • sql和程式碼的分離,提高了可維護性。
    • 提供對映標籤,支援物件與資料庫的orm欄位關係對映
    • 提供物件關係對映標籤,支援物件關係組建維護
    • 提供xml標籤,支援編寫動態sql。

重要的一點,使用的人多!

Spring SpringMVC SpringBoot

2、第一個Mybatis程式

2.1 搭建環境

新建專案

  1. 新建一個maven專案

  2. 刪除src

  3. 匯入maven依賴

    <!--mysql驅動-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>
    <!--mybatis-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    

2.2 建立一個專案

  • 編寫Mybatis核心配置檔案
<?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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>
  • 編寫Mybatis工具類
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();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

2.3 編寫程式碼

  • 實體類

    public class User {
        private int id;
        private String name;
        private String pwd;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public User() {
        }
    }
    
  • Dao介面

    public interface UserDao {
        List<User> getUserList();
    }
    
  • 介面實現類

    介面實現類由原來的Impl轉換為一個Mapper配置檔案

    <?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.zhang.dao.UserDao">
        <select id="getUserList" resultType="com.zhang.pojo.User">
            select * from user
        </select>
    </mapper>
    

2.4 測試

注意點:org.apache.ibatis.binding.BindingException: Type interface com.zhang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什麼?

核心配置檔案中註冊mappers

junit測試

   @Test
    public void test(){
        //第一步,獲取物件
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一:getMapper
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> userList = userDao.getUserList();
        for (User user:userList) {
            System.out.println(user);
        }
        //關閉sqlSession
        sqlSession.close();
    }

可能會遇到的問題:

  1. 配置檔案沒有註冊
  2. 繫結介面錯誤
  3. 方法名不對
  4. 返回型別不對
  5. Maven匯出資源問題

3、CURD

1、namespace

namespace中的包名要和Dao/mapper介面的包名一致!

2、select

選擇,查詢語句

  • id:就是對應namespace的方法名

  • resultType:Sql語句執行的返回值

  • parameterType:引數型別!

  1. 編寫介面

    List<User> getUserList();
    
  2. 編寫Mapper,xml中的sql語句

    <select id="getUserList" resultType="com.zhang.pojo.User">
        select * from mybatis.user
    </select>
    
  3. 測試

    public void getUserById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(1);
        System.out.println(user);
    }
    

3、insert

<insert id="addUser" parameterType="com.zhang.pojo.User" >
    insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd})
</insert>

4、update

<update id="updateUser" parameterType="com.zhang.pojo.User" >
    update mybatis.user set id=#{id},name=#{name},pwd=#{pwd}   where  id=#{id};
</update>

5、delete

<delete id="deleteUser" parameterType="int" >
    delete from mybatis.user where id = #{id}
</delete>

注意點

  • 增刪改要提交事務

6、萬能Map

假設,我們的實體類,或者資料庫中的表,欄位或者引數過多,我們應當考慮使用Map!

int addUser2(Map<String,Object> map);
<insert id="addUser2" parameterType="Map" >
    insert into mybatis.user (id, name, pwd) values (#{userid},#{userName},#{passWord})
</insert>
public void addUser2(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    Map map = new HashMap<String, Object>();
    map.put("userid", 6);
    map.put("userName", "zhangxy");
    map.put("passWord", "49815");
    userMapper.addUser2(map);
    sqlSession.commit();
    sqlSession.close();
}

Map傳遞引數,直接在sql中取出key即可 【 parameterType="map"】

物件傳遞引數,直接取物件的屬性即可【parameterType="com.zhang.pojo.User"】

只有一個基本型別,直接在sql中可以取到

多個引數用Map,或者註解

7、思考題

模糊查詢怎麼寫?

1、在寫java程式碼的時候,傳遞萬用字元“%”

List<User> userList = userMapper.getUserList2("%z%");

2、在sql拼接的時候,傳遞萬用字元“%”

<select id="getUserList2" resultType="com.zhang.pojo.User">
    select * from mybatis.user where name like "%"#{value}"%"
</select>

4、配置解析

1、核心配置檔案

mybatis-config.xml

MyBatis的配置檔案包含了會深深影響MyBatis行為的設定和屬性資訊

configuration(配置)
properties(屬性)
settings(設定)
typeAliases(類型別名)
typeHandlers(型別處理器)
objectFactory(物件工廠)
plugins(外掛)
environments(環境配置)
environment(環境變數)
transactionManager(事務管理器)
dataSource(資料來源)
databaseIdProvider(資料庫廠商標識)
mappers(對映器)

2、配置環境(environments)

MyBatis可以配置成適應多個環境

不過要記住:儘管可以配置多個環境,但SqlSessionFactory例項只能選擇一種環境。

學會使用配置多套執行環境!

Mybatis預設事務管理器是JDBC,連線池POOLED

3、屬性(properties)

我們可以通過properties屬性來引用配置檔案

這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定。【db.properties】

編寫一個配置檔案

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

在核心配置檔案中引入

<properties resource="db.properties">
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</properties>
  • 可以直接引入外部檔案
  • 可以在其增加一些屬性配置
  • 如果兩個檔案中有同一屬性,優先使用外部配置檔案
  • 核心配置中,標籤都是順序的,properties應放在前面

4、類型別名

  • 類型別名可為 Java 型別設定一個縮寫名字。
  • 它僅用於 XML 配置,意在降低冗餘的全限定類名書寫。
<typeAliases>
    <typeAlias type="com.zhang.pojo.User" alias="User"/>
</typeAliases>

也可以指定一個包名,MyBatis 會在包名下面搜尋需要的 Java Bean

掃描這個包的別名時,預設別名為類名,首字母小寫

<typeAliases>
	<package name="com.zhang.pojo"/>
</typeAliases>

在實體類少的時候,使用第一種

在實體類多的時候,建議使用第二種

第一種可以diy別名,第二種要定義別名,需要通過註解的方式

@Alias("hello")
public class User {

5、設定

這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的執行時行為

6、其它配置

7、對映器

MapperRegistry:註冊繫結我們的Mapper檔案

方式一:【推薦使用】

<mappers>
    <mapper resource="com/zhang/dao/UserMapper.xml"/>
</mappers>

方式二:使用class檔案繫結註冊

<mappers>
    <mapper class="com.zhang.dao.UserMapper"/>
</mappers>

注意點:

  • 介面與配置檔案必須同名
  • 介面和配置檔案必須在同一個包下

方式三:使用掃描包注入繫結

<mappers>
    <package name="com.zhang.dao"/>
</mappers>

注意點:

  • 介面與配置檔案必須同名
  • 介面和配置檔案必須在同一個包下

8、生命週期和作用域

生命週期和作用域是至關重要的,因為錯誤的使用會導致非常嚴重的併發問題

SqlSessionFactoryBuilder

  • 一旦建立了SqlSessionFactory,就不需要它了
  • 區域性變數

SqlSessionFactory

  • 資料庫連線池
  • SqlSessionFactory 一旦被建立就應該在應用的執行期間一直存在,沒有任何理由丟棄它或重新建立另一個例項。
  • 因此 SqlSessionFactory 的最佳作用域是應用作用域
  • 最簡單的就是使用單例模式或者靜態單例模式

SqlSession

  • 連線到連線池的一個請求

  • SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。

  • 用完之後需要趕緊關閉,否則資源會被佔用

這裡的每一個Mapper就代表一個具體的業務

5、解決屬性名與欄位名不一致的問題

1、問題

資料庫中的欄位

新建一個專案,拷貝之前的,測試實體類欄位不一致的情況

測試出現的問題

解決方式

  • 起別名
<select id="getUserById" parameterType="int" resultType="com.zhang.pojo.User">
    select id,name,pwd as password from mybatis.user where id = #{id}
</select>

2、結果集對映

id name pwd
id name password
<resultMap id="UserMap" type="User">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" resultMap="UserMap" resultType="User">
    select * from mybatis.user where id = #{id}
</select>
  • resultMap 元素是 MyBatis 中最重要最強大的元素。
  • ResultMap 的設計思想是,對簡單的語句做到零配置,對於複雜一點的語句,只需要描述語句之間的關係就行了。
  • ResultMap最優秀的地方在於,如果你對它相當瞭解,你根本不需要配置它

7、分頁

思考:為什麼要分頁?

  • 減少資料的處理量

7.1 limit分頁

使用語法

select * from user limit startIndex,pagesize

使用Mybatis實現分頁,核心語法

  1. 介面

    List<User> getUserByLimit(Map<String,Integer> map);
    
  2. Mapper

    <select id="getUserByLimit" parameterType="map" resultMap="UserMap" resultType="User">
        select * from mybatis.user limit #{startIndex},#{pagesize}
    </select>
    
  3. 測試

    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper user = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> para = new HashMap<String, Integer>();
            para.put("startIndex", 1);
            para.put("pagesize", 2);
            List<User> userList = user.getUserByLimit(para);
            for(User userItem:userList){
            System.out.println(userItem);
        }
    }
    

7.2、RowBounds分頁

不再使用Sql分頁

  1. 介面

    List<User> getUserByRowBounds();
    
  2. Mapper

    <select id="getUserByRowBounds" resultMap="UserMap">
        select * from mybatis.user
    </select>
    
  3. 測試

    public void getUserByRowBounds(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            RowBounds rowBounds = new RowBounds(1, 2);
            List<User> userList = sqlSession.selectList("com.zhang.dao.UserMapper.getUserByRowBounds", null, rowBounds);
            for (User user : userList) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    

7.3分頁外掛

MyBatis 分頁外掛 PageHelper

瞭解即可,萬一以後公司的架構,說要使用,需要知道這個是什麼東西!

8、註解

8.1、面向介面程式設計

8.2、使用註解開發

  1. 註解在介面上實現
@Select("select * from user")
List<User> getUserList();
  1. 需要在核心配置檔案中繫結註解介面
<mapper class="com.zhang.dao.UserMapper"/>
  1. 測試

    public void getUserList(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //底層使用的反射
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
    

本質:反射機制實現

底層:動態代理

8.3、 CURD

我們可以在工具類建立的時候實現自動提交事務

public static SqlSession getSqlSession() {
    return sqlSessionFactory.openSession(true);
}

編寫介面,增加註解。要將介面繫結配置在核心配置檔案中!

    @Select("select * from user")
    List<User> getUserList();

    @Select("select * from user where id = #{id}")
    User getUserById(@Param("id") int id);

    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
    int addUser(User user);

    @Update("update user set name = #{name},pwd = #{password} where id = #{id}")
    int updateUser(User user);

    @Delete("delete from user where id = #{uid}")
    int deleteUser(@Param("uid") int id);

測試類

		SqlSession sqlSession = MybatisUtils.getSqlSession();
        //底層使用的反射
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        userMapper.updateUser(new User(7, "王九", "151853"));

        userMapper.deleteUser(7);

//        userMapper.addUser(new User(7, "王六", "484848"));

//        User user = userMapper.getUserById(2);
//        System.out.println(user);

//        List<User> userList = userMapper.getUserList();
//        for (User user : userList) {
//            System.out.println(user);
//        }
        sqlSession.close();

關於@Param()註解

  • 基礎型別的引數或String型別,需要加上
  • 引用型別不需要加
  • 如果只有一個基本型別的話,可以不加,但建議加
  • 在sql引用的,是@Param()定義的名稱

9、LomBok

簡介:

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.

使用步驟:

  1. 在IDEA中安裝Lombok外掛包

  2. 在專案中匯入lombok的jar包

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.10</version>
            </dependency>
    
  3. 在實體類中添加註解

@Getter and @Setter
@FieldNameConstants
@ToString
@EqualsAndHashCode
@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor
@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog
@Data
@Builder
@SuperBuilder
@Singular
@Delegate
@Value
@Accessors
@Wither
@With
@SneakyThrows

@Data 無參構造,get,set,toString,Hashcode,equals

@AllArgsConstructor 有參構造

@NoArgsConstructor 無參構造

10、多對一處理

測試環境搭建

  1. 匯入lombok
  2. 新建實體類Teacher、Student
  3. 建立Mapper介面
  4. 建立Mapper.xml檔案
  5. 在核心配置檔案中繫結註冊我們的Mapper介面或者檔案!【方式很多,隨心選】
  6. 測試查詢能否成功
CREATE TABLE `teacher`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;

insert into `teacher` (`id`,`name`) values(1, "張老師");

CREATE TABLE `student`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid`(`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;

INSERT INTO `student` (`id`,`name`,`tid`) values (1,"張三",1);
INSERT INTO `student` (`id`,`name`,`tid`) values (2,"李四",1);
INSERT INTO `student` (`id`,`name`,`tid`) values (3,"王五",1);
INSERT INTO `student` (`id`,`name`,`tid`) values (4,"趙六",1);
INSERT INTO `student` (`id`,`name`,`tid`) values (5,"宋七",1);

按照查詢巢狀處理

    <select id="getStudentList" resultMap="studentTeacher">
        select * from student
    </select>
    <resultMap id="studentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--複雜的屬性,我們需要單獨處理
        物件:assoaciation
        集合:collection
        --> 
        <association property="teacher" column="tid" javaType="com.zhang.pojo.Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id = #{tid}
    </select>

按結果集巢狀處理

    <select id="getStudentList2" resultMap="studentTeacher2">
        select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid = t.id
    </select>
    <resultMap id="studentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="com.zhang.pojo.Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

11、一對多

  1. 環境搭建

    實體類

    public class Student {
        int id;
        String name;
        int tid;
    }
    
    public class Teacher {
        int id;
        String name;
        List<Student> studentList;
    }
    

按照結果巢狀處理

<select id="getTeacherById" resultMap="TeacherStudent">
        select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where t.id = s.tid and t.id = #{id}
    </select>
    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="studentList" ofType="com.zhang.pojo.Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

按照查詢巢狀處理

 <select id="getTeacherById2" resultMap="TeacherStudent2">
        select * from teacher where id = #{id}
    </select>
    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="studentList" column="id" javaType="ArrayList" ofType="Student" select="getStudentList"/>
    </resultMap>
    <select id="getStudentList" resultType="Student">
        select * from student where tid = #{id}
    </select>

小結

  1. 關聯 association 【一對多】

  2. 集合 collection 【多對一】

  3. JavaType & ofType

    1. JavaType 用來指定實體類中屬性的型別
    2. ofType 用來指定對映到List或者集合中的pojo型別,泛型中的約束型別

注意點

  • 保證Sql的可讀性,儘量保證通俗易懂

面試高頻

  • MySql引擎型別
  • InnoDB底層原理
  • 索引
  • 索引優化

12、動態Sql

什麼是動態Sql,動態Sql就是通過不同的條件,動態生成不同的Sql

利用動態 SQL,可以徹底擺脫這種痛苦

如果你之前用過 JSTL 或任何基於類 XML 語言的文字處理器,你對動態 SQL 元素可能會感覺似曾相識。在 MyBatis 之前的版本中,需要花時間瞭解大量的元素。藉助功能強大的基於 OGNL 的表示式,MyBatis 3 替換了之前的大部分元素,大大精簡了元素種類,現在要學習的元素種類比原來的一半還要少。

if
choose (when, otherwise)
trim (where, set)
foreach
CREATE TABLE `blog` (
`id` VARCHAR(50) NOT NULL COMMENT '部落格ID',
`title` VARCHAR(100) NOT NULL COMMENT '部落格標題',
`author` VARCHAR(100) NOT NULL COMMENT '部落格作者',
`create_time` datetime NOT NULL COMMENT '建立時間',
`views` INT(30) NOT NULL COMMENT '瀏覽量'
)ENGINE =INNODB DEFAULT CHARSET=utf8

建立一個基礎工程

  1. 導包

  2. 編寫配置檔案

  3. 編寫實體類

    @Data
    @AllArgsConstructor
    public class Blog {
        private String id;
        private String title;
        private String author;
        private Date createTime;
        private int views;
    }
    
  4. 編寫實體類對應Mapper介面和Mapper.xml檔案

    public interface BlogMapper {
        int addBlog(Blog blog);
    
        List<Blog> getList(Map map);
    }
    
        <select id="getList" parameterType="map" resultType="Blog">
            select * from blog where 1=1
            <if test="title != null">
                and title = #{title}
            </if>
            <if test="author != null">
                and author = #{author}
            </if>
        </select>
    
  5. 測試

IF

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

choose

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

trim(where,set)

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


tirm動態SQL
https://www.cnblogs.com/waterystone/p/7070836.html

所謂動態SQL,本質還是SQL語句,只是通過邏輯去實現SQL程式碼

if

where, set, choose, when

SQL片段

有的時候,我們可能會將一部分SQL抽取出來,實現複用!

  1. 使用SQL標籤抽取公共部分

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

        <select id="getList" parameterType="map" resultType="Blog">
            select * from blog
            <where>
                <include refid="sql-title-author">
                </include>
            </where>
        </select>
    

注意事項:

  • 最好基於單表來定義SQL片段!
  • 不要存在where標籤!

Foreach

select * from user where 1=1 and (id = 0 or id = 1 or id = 2)
<foreach item="id" collection="ids" open=")" separator="or" close=")">
	#{id}
</foreach>
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open=" and (" separator=" or " close=")">
                id = #{id}
            </foreach>
        </where>
    </select>

動態sql就是在搭接sql語句,我們只要保證SQL的正確性,按照SQL的格式,去排列組合就可以了

建議:

先在Mysql中寫出完整的SQL,再對應的去修改成為我們的動態SQL實現通用即可!

13、快取

1、一級快取(預設開啟)

在本次SqlSession會話中有效,通常web服務,都是連線開啟快取,斷開即失。

查詢一次之後將會被快取

增刪改查後,會重新整理快取

sqlSession.clearCache(); 手動清理快取

2、二級快取

  • 二級快取也稱全域性快取,一級快取作用域太低,所以誕生了二級快取
  • 基於namespace級別的快取,一個名稱空間,對應一個二級快取
    • 一個會話查詢出的快取儲存在一級快取
    • 當前會話關閉,則一級快取會失效,但一級快取會轉存至二級快取
    • 新增的會話查詢,就可以直接查詢到二級快取
    • 不同mapper的快取對應不同的快取(map)中

步驟

  1. 開啟快取(在核心配置檔案配置)

    <!--顯示的開啟全域性快取-->
    <setting name="cacheEnabled" value="true"/>
    
  2. 要在使用的二級快取中開啟(在Mapper中配置)

        <!--在mapper中開啟二級快取-->
        <cache/>
    

    也可以自定義一些引數

        <!--在mapper中開啟二級快取 FIFO快取策略,flushInterval快取重新整理時間,size快取大小,readOnly是否只讀-->
        <cache eviction="FIFO"
               flushInterval="60000"
               size="512"
               readOnly="true"
        />
    
  3. 測試

    org.apache.ibatis.cache.CacheException: Error serializing object.
    
    1. 問題,我們需要將實體類序列化,否則會報錯!

      public class User implements Serializable {
      
  4. 小結

    只要開啟了二級快取,在同一個mapper中就有效