一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫(kù)技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫(kù) - Mysql - MyBatis 動(dòng)態(tài)SQL全面詳解

MyBatis 動(dòng)態(tài)SQL全面詳解

2021-11-21 22:11素衣黛眉 Mysql

MyBatis 的強(qiáng)大特性之一便是它的動(dòng)態(tài) SQL。如果你有使用 JDBC 或其他類似框架的經(jīng)驗(yàn),你就能體會(huì)到根據(jù)不同條件拼接 SQL 語(yǔ)句有多么痛苦。拼接的時(shí)候要確保不能忘了必要的空格,還要注意省掉列名列表最后的逗號(hào)。利用動(dòng)態(tài) SQL 這

前言

前面mysql都是通過(guò)靜態(tài)sql進(jìn)行查詢的,但是如果業(yè)務(wù)復(fù)雜的時(shí)候,我們會(huì)遇到引號(hào)問(wèn)題,或者多一個(gè)空格,這就使得sql代碼編寫錯(cuò)誤了,所以為了解決這個(gè)問(wèn)題,我們有了動(dòng)態(tài)sql。

mybatis框架的動(dòng)態(tài)sql技術(shù)是一種根據(jù)特定條件動(dòng)態(tài)拼裝sql語(yǔ)句的功能,它存在的意義是為了解決拼接sql語(yǔ)句字符串時(shí)的痛點(diǎn)問(wèn)題。具體是通過(guò)標(biāo)簽來(lái)實(shí)現(xiàn)的。

動(dòng)態(tài)sql

1.先看一下模塊目錄結(jié)構(gòu)

在類路徑的resources下的mapper包下創(chuàng)建sql.xml文件(共性抽取)

MyBatis 動(dòng)態(tài)SQL全面詳解

2.物理建模和邏輯建模

這里省略物理建模步驟,要求數(shù)據(jù)庫(kù)的表與pojo類要對(duì)應(yīng)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package pojo;
 
import lombok.allargsconstructor;
import lombok.data;
import lombok.noargsconstructor;
 
@data
@allargsconstructor
@noargsconstructor
public class employee {
    private integer empid;
    private string empname;
    private double empsalary;
 
}

3. 引入依賴

把之前的log4j復(fù)制到類路徑resouces下,另外我們引入依賴后的pom.xml如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?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">
    <modelversion>4.0.0</modelversion>
 
    <groupid>org.example</groupid>
    <artifactid>day03-mybatis02-dynamic</artifactid>
    <version>1.0-snapshot</version>
    <packaging>jar</packaging>
 
    <dependencies>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- mybatis核心 -->
        <dependency>
            <groupid>org.mybatis</groupid>
            <artifactid>mybatis</artifactid>
            <version>3.5.7</version>
        </dependency>
 
        <!-- junit測(cè)試 -->
        <dependency>
            <groupid>junit</groupid>
            <artifactid>junit</artifactid>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
 
        <!-- mysql驅(qū)動(dòng) -->
        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <version>5.1.3</version>
            <scope>runtime</scope>
        </dependency>
 
        <!-- log4j日志 -->
        <dependency>
            <groupid>log4j</groupid>
            <artifactid>log4j</artifactid>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
 
</project>

4.全局配置文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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>
    <!--駝峰映射-->
    <settings>
        <setting name="mapunderscoretocamelcase" value="true"/>
    </settings>
    <!--類型別名映射-->
    <typealiases>
        <package name="pojo"/>
    </typealiases>
    <!--環(huán)境配置-->
    <environments default="dev">
        <environment id="dev">
            <transactionmanager type="jdbc"></transactionmanager>
            <datasource type="pooled">
                <property name="username" value="root"/>
                <property name="password" value="888888"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis-example"/>
                <property name="driver" value="com.mysql.jdbc.driver"/>
            </datasource>
                
        </environment>
    </environments>
    <!--路徑映射-->
    <mappers>
        <mapper resource="mapper/sql.xml"/>
        <package name="mapper"/>
    </mappers>
</configuration>

注意: 這里有駝峰映射,別名映射,路徑映射和路徑映射。和以前的不同的是,我們這里做了sql語(yǔ)句的共性抽取,所以得加一個(gè)sql的路徑映射 <mapper resource="mapper/sql.xml"/>

5.sql共性抽取文件

在類路徑resources下的包mapper下創(chuàng)建一個(gè)sql.xml(因?yàn)槲覀僺ql是要寫在映射文件中,自己本身也是映射文件,所以需要寫在mapper下)。到要用的時(shí)候,在映射路徑文件中需要用到這個(gè)sql語(yǔ)句的地方加入 <include refid="mapper.sql.myselectsql"></include>

?
1
2
3
4
5
6
7
8
9
10
11
12
<?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="mapper.sql">
 
        <sql id="myselectsql">
    select emp_id,emp_name,emp_salary from t_emp
</sql>
 
 
</mapper>

共性抽取文件也可以不配置,這時(shí)候直接在映射文件中把要執(zhí)行的語(yǔ)句重新編寫就行了。

6.mapper接口

一共有七個(gè)方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package mapper;
 
import org.apache.ibatis.annotations.param;
import pojo.employee;
 
import java.util.list;
 
public interface employeemapper {
 
     //根據(jù)員工的empid查詢大于該empid的所有員工,如果empid為null,則查詢?nèi)w員工
    list<employee> selectemployeelistbyempid(integer empid);
 
    /**
     * 查詢大于傳入的empid并且工資大于傳入的empsalary的員工集合,如果傳入的empid為null,則不考慮empid條件
     * 傳入的empsalary為null則不考慮empsalary的條件
     */
    list<employee> selectemployeelistbyempidandempsalary(@param("empid") integer empid, @param("empsalary") double empsalary);
 
    /**
     * 根據(jù)empid更新員工信息,如果某個(gè)值為null,則不更新這個(gè)字段
     */
    void updateemployee(employee employee);
 
    /**
     * 根據(jù)emp_id查詢員工信息,如果0<emp_id<6,那么就查詢所有大于該emp_id的員工,如果emp_id是大于6,那么就查詢所有小于該emp_id的員工
     * 如果是其它情況,則查詢所有員工信息
    
     */
    list<employee> selectemployeelist(integer empid);
 
    /**
     * 添加員工信息
     */
    void insertemployee(employee employee);
 
    /**
     * 批量添加員工集合   
     */
    void insertemployeelist(@param("employeelist") list<employee> employeelist);
 
    /**
     * 根據(jù)員工的id集合查詢員工集
     */
    list<employee> selectemployeelistbyempidlist(list<integer> idlist);
}

if

目標(biāo):根據(jù)員工的empid查詢大于該empid的所有員工,如果empid為null,則查詢?nèi)w員工。

dao接口的方法為:
list<employee> selectemployeelistbyempid(integer empid);

靜態(tài)sql:

?
1
2
3
4
5
<select id="selectemployeelistbyempid" resulttype="employee">
 
    <include refid="mapper.sql.myselectsql"></include> where emp_id>#{empid}
 
</select>

動(dòng)態(tài)sql:

?
1
2
3
4
5
6
<select id="selectemployeelistbyempid" resulttype="employee">
     <include refid="mapper.sql.myselectsql"></include>
     <if test="empid != null">
         where emp_id>#{empid}
     </if>
 </select>

<include refid="mapper.sql.myselectsql"></include>表示引用抽取出的sql片段,也可以直接寫sql語(yǔ)句。如果是靜態(tài)sql,當(dāng)id為null時(shí),查詢出來(lái)的是空,動(dòng)態(tài)sql則可以查出全部。if標(biāo)簽里面有test屬性名,作為判斷語(yǔ)句。

where

目標(biāo):

  • 查詢大于傳入的empid并且工資大于傳入的empsalary的員工集合
  • 如果傳入的empid為null,則不考慮empid條件
  • 傳入的empsalary為null則不考慮empsalary的條件

dao接口方法:

list<employee> selectemployeelistbyempidandempsalary(@param("empid") integer empid, @param("empsalary") double empsalary);

用if標(biāo)簽的動(dòng)態(tài)sql:

?
1
2
3
4
5
6
7
8
<select id="selectemployeelistbyempidandempsalary" resulttype="employee">
    <include refid="mapper.sql.myselectsql"></include> where
   <if test="empid != null">
            emp_id>#{empid}
        </if>
        <if test="empsalary != null">
           and emp_salary>#{empsalary}
        </if>

這里可以看到,如果empsalary為空,那么sql語(yǔ)句為select * from t_emp where emp_id >#{empid},但是如果empid為空,那么sql語(yǔ)句為select * from t_emp where and emp_salary>#{empsalary},很明顯這個(gè)是錯(cuò)的,if標(biāo)簽在這里就不適用了。所以我們用where標(biāo)簽,或者trim標(biāo)簽。

where和if的動(dòng)態(tài)sql:

?
1
2
3
4
5
6
7
8
9
10
11
12
<select id="selectemployeelistbyempidandempsalary" resulttype="employee">
    <include refid="mapper.sql.myselectsql"></include>
   
    <where>
        <if test="empid != null">
            emp_id>#{empid}
        </if>
        <if test="empsalary != null">
           and emp_salary>#{empsalary}
        </if>
    </where>
</select>

where標(biāo)簽的作用:

  • 在第一個(gè)條件之前自動(dòng)添加where關(guān)鍵字
  • 自動(dòng)去掉第一個(gè)條件前的連接符(and、or等等)

trim

trim是修建的意思,其實(shí)就是去頭去尾,這里還是根據(jù)上面那個(gè)方法

trim的動(dòng)態(tài)sql

?
1
2
3
4
5
6
7
8
9
10
11
12
<select id="selectemployeelistbyempidandempsalary" resulttype="employee">
    <include refid="mapper.sql.myselectsql"></include>
    <trim prefix="where" prefixoverrides="and|or">
        <if test="empid != null">
            emp_id>#{empid}
        </if>
 
        <if test="empsalary != null">
            and emp_salary>#{empsalary}
        </if>
    </trim>
</select>

trim標(biāo)簽:

  • prefix:指定要?jiǎng)討B(tài)添加的前綴
  • suffix屬性:指定要?jiǎng)討B(tài)添加的后綴
  • prefixoverrides:指定要?jiǎng)討B(tài)去掉的前綴,使用“|”分隔有可能的多個(gè)值
  • suffixoverrides屬性:指定要?jiǎng)討B(tài)去掉的后綴,使用“|”分隔有可能的多個(gè)值

set

目標(biāo):根據(jù)empid更新員工信息,如果某個(gè)值為null,則不更新這個(gè)字段

dao接口方法:
void updateemployee(employee employee);
我們先用上面的trim標(biāo)簽來(lái)解決一下這個(gè)問(wèn)題,

trim的動(dòng)態(tài)sql:

?
1
2
3
4
5
6
7
8
9
10
11
<update id="updateemployee" >
    <trim prefix="set" prefixoverrides=",">
        <if test="empname!=null">
            emp_name=#{empname}
        </if>
        <if test="empsalary!=null">
            , emp_salary=#{empsalary}
        </if>
    </trim>
    where emp_id=#{empid}
</update>

set的動(dòng)態(tài)sql

?
1
2
3
4
5
6
7
8
9
10
<update id="updateemployee" >
    update t_emp
     <set >
         <if test="empname!=null">
             emp_name=#{empname}
         </if>
         <if test="empsalary!=null">
            , emp_salary=#{empsalary}
         </if>
     </set>

可以看出

set標(biāo)簽的作用:

  • 自動(dòng)在要修改的第一個(gè)字段之前添加set關(guān)鍵字
  • 去掉要修改的第一個(gè)字段前的連接符(,)

choose、when、otherwise

目標(biāo):

  • 根據(jù)emp_id查詢員工信息,如果0<emp_id<6,那么就查詢所有大于該emp_id的員工
  • 如果emp_id是大于6,那么就查詢所有小于該emp_id的員工
  • 如果是其它情況,則查詢所有員工信息

dao接口方法:
list<employee> selectemployeelist(integer empid);

動(dòng)態(tài)sql

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<select id="selectemployeelist" resulttype="employee">
  
    <include refid="mapper.sql.myselectsql"></include> where
    <choose>
    <!--&lt;是<號(hào)的轉(zhuǎn)義字符-->
        <when test="empid>0 and empid&lt;6">
            emp_id>#{empid}
        </when>
        <when test="empid>6">
            emp_id&lt;#{empid}
        </when>
        <otherwise>
            1==1
        </otherwise>
    </choose>
 
</select>

choose、when、otherwise
相當(dāng)于if ... else if... else if ... else

  • 如果某一個(gè)when的條件成立,則不會(huì)繼續(xù)判斷后續(xù)的when
  • 如果所有的when都不成立,則會(huì)拼接otherwise標(biāo)簽中的內(nèi)容

foreach

目標(biāo)1:批量添加員工信息

dao接口方法:

void insertemployeelist(@param("employeelist") list employeelist);

1.動(dòng)態(tài)sql

?
1
2
3
4
5
6
7
8
<insert id="insertemployeelist">
    insert into t_emp(emp_name,emp_salary)values
    <!--collection標(biāo)簽可以寫list,collection,
    或者自己自己定義參數(shù)名@param("employeelist") list<employee> employeelist-->
    <foreach collection="employeelist" separator="," item="emp">
        (#{emp.empname},#{emp.empsalary})
    </foreach>
</insert>

目標(biāo)2:根據(jù)多個(gè)id查詢多個(gè)員工信息

dao接口

list selectemployeelistbyempidlist(list idlist);

2.動(dòng)態(tài)sql

?
1
2
3
4
5
6
<select id="selectemployeelistbyempidlist" resulttype="employee">
    <include refid="mapper.sql.myselectsql"></include>
     <foreach collection="collection" item="id" separator="," open="where emp_id in (" close=")">
         #{id}
     </foreach>
</select>

批量查詢:foreach標(biāo)簽

  1. collection屬性: 表示要遍歷的對(duì)象,如果要遍歷的參數(shù)使用@param注解取名了就使用該名字,如果沒(méi)有取名list,或者collection。
  2. item屬性: 表示遍歷出來(lái)的元素,我們到時(shí)候要拼接sql語(yǔ)句就得使用這個(gè)元素: 如果遍歷出來(lái)的元素是pojo對(duì)象, 那么我們就通過(guò) #{遍歷出來(lái)的元素.pojo的屬性} 獲取數(shù)據(jù);如果遍歷出來(lái)的元素是簡(jiǎn)單類型的數(shù)據(jù),那么我們就使用 #{遍歷出來(lái)的元素} 獲取這個(gè)簡(jiǎn)單類型數(shù)據(jù)
  3. separator屬性: 遍歷出來(lái)的元素之間的分隔符
  4. open屬性: 在遍歷出來(lái)的第一個(gè)元素之前添加前綴
  5. close屬性: 在遍歷出來(lái)的最后一個(gè)元素之后添加后綴

測(cè)試程序

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import mapper.employeemapper;
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 org.junit.after;
import org.junit.before;
import pojo.employee;
 
import java.io.inputstream;
import java.util.arraylist;
import java.util.list;
 
public class test {
    private employeemapper employeemapper;
    private inputstream is;
    private sqlsession sqlsession;
    @before
    public void init() throws exception{
        //目標(biāo):獲取employeemapper接口的代理對(duì)象,并且使用該對(duì)象調(diào)用selectemployee(1)方法,然后返回employee對(duì)象
        //1. 將全局配置文件轉(zhuǎn)成字節(jié)輸入流
        is = resources.getresourceasstream("mybatisconfig.xml");
        //2. 創(chuàng)建sqlsessionfactorybuilder對(duì)象
        sqlsessionfactorybuilder sqlsessionfactorybuilder = new sqlsessionfactorybuilder();
        //3. 使用構(gòu)建者模式創(chuàng)建sqlsessionfactory對(duì)象
        sqlsessionfactory sqlsessionfactory = sqlsessionfactorybuilder.build(is);
        //4. 使用工廠模式創(chuàng)建一個(gè)sqlsession對(duì)象
        sqlsession = sqlsessionfactory.opensession();
        //5. 使用動(dòng)態(tài)代理模式,創(chuàng)建employeemapper接口的代理對(duì)象
        employeemapper = sqlsession.getmapper(employeemapper.class);
    }
 
 
    @after
    public void after() throws exception{
        //提交事務(wù)!!!
        sqlsession.commit();
        //7. 關(guān)閉資源
        is.close();
        sqlsession.close();
    }
 
    @org.junit.test
    public void testselectemployeelistbyempid(){
        system.out.println(employeemapper.selectemployeelistbyempid(null));
    }
 
    @org.junit.test
    public void testselectemployeelistbyempidandempsalary(){
        system.out.println(employeemapper.selectemployeelistbyempidandempsalary(2, 300d));
    }
 
    @org.junit.test
    public void testupdateemployee(){
        employee employee = new employee(3,"celia", 9000d);
 
        employeemapper.updateemployee(employee);
    }
 
    @org.junit.test
    public void testselectemployeelist(){
    system.out.println(employeemapper.selectemployeelist(7));
}
 
   @org.junit.test
   public void testinsertemployee(){
        employeemapper.insertemployee(new employee(null,"tom",300d));
    }
 
    @org.junit.test
    public void testinsertemployeelist(){
        list<employee> employeelist = new arraylist<>();
        for (int i = 11; i <=20 ; i++) {
            employeelist.add(new employee(null,"aobama"+i,2000d));
        }
 
        employeemapper.insertemployeelist(employeelist);
 
    }
 
    @org.junit.test
    public void testselectemployeelistbyempidlist(){
        list<integer> idlist = new arraylist<>();
        idlist.add(23);
        idlist.add(33);
        idlist.add(32);
        idlist.add(21);
        idlist.add(22);
        system.out.println(employeemapper.selectemployeelistbyempidlist(idlist));
    }
 
 
}

到此這篇關(guān)于mybatis 動(dòng)態(tài)sql全面詳解的文章就介紹到這了,更多相關(guān)mybatis 動(dòng)態(tài)sql內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://www.cnblogs.com/jasmine-e/p/15354425.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩香蕉网| 日本国产高清色www视频在线 | 2022天天干| 国产经典一区二区三区蜜芽 | 美日韩一区二区三区 | 91精品国产品国语在线不卡 | 成年美女黄网站色视频大全免费 | 日韩毛片在线 | 国产四虎 | 日本一区二区三区在线 视频 | 欧美日韩国产成人综合在线影院 | 韩国三级 720p| 韩国一级淫片特黄特刺激 | 久久精品一卡二卡三卡四卡视频版 | 国产hd老头老太婆 | 国产综合久久久久久 | 交换年轻夫妇HD中文字幕 | 欧美精品一二三区 | 6080午夜| 精品一区二区三区视频 | 欧美靠逼| 国产精品videosse | 欧美伊人久久久久久久久影院 | 97青草香蕉依人在线播放 | 午夜伦伦电影理论片大片 | 99在线在线视频免费视频观看 | 福利视频一区二区思瑞 | 亚洲欧美成人综合久久久 | 极品妖艳许清赵丽全文免费阅读 | 亚洲精品一二区 | 国产伦码精品一区二区 | 亚洲视频久久 | 性欧美sexovideotv | 精品国产91高清在线观看 | 精品手机在线视频 | 亚洲精品成人AV在线观看爽翻 | 成年人福利视频 | 国产男女爱视频在线观看 | 九九精品视频在线免费观看 | 亚洲欧美综合在线观看 | 饭冈加奈子在线播放观看 |