欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis多表查詢與動態(tài)SQL特性詳解

 更新時間:2022年11月04日 15:53:27   作者:未見花聞  
動態(tài)SQL可以省略很多拼接SQL的步驟,使用類似于JSTL方式,下面這篇文章主要給大家介紹了關于Mybatis多表查詢與動態(tài)SQL特性的相關資料,文字通過實例代碼介紹的非常詳細,需要的朋友可以參考下

1.較復雜的查詢操作

1.1 參數(shù)占位符 #{} 和 ${}

#{}:預處理符,如將id=#{2}替換為id=?,然后使用2替換?。

${}:替換符,如將id=${2}替換為id=2。

兩種占位符都可以正常使用的場合:傳入的參數(shù)類型是數(shù)值類型

使用${}

select * from userinfo where id=${id}
select * from userinfo where id=2

使用#{}

select * from userinfo where id=#{id}
select * from userinfo where id=?

對于這兩種參數(shù)占位符,個人建議能使用#{}就使用#{},因為${}存在SQL注入的問題,以及如果傳入的類型是字符串也會出類型。

只能使用#{}而不能使用${}的場合:傳入參數(shù)類型為String

使用${}

select * from userinfo where username=${username}
//實際執(zhí)行的語句
Preparing: select * from userinfo where username=張三

但是在sql中通過字符串來查詢數(shù)據(jù),是需要加上引號的,而使用${}生成的sql并沒有帶引號,因此不適用于字符串參數(shù)的sql。

使用#{}

select * from userinfo where username=#{username}
//實際執(zhí)行語句
select * from userinfo where username=?

由于使用#{}是將目標參數(shù)替換為占位符,然后利用JDBC中的占位符機制實現(xiàn)sql語句的填充,所以使用#{}構造的sql是可以正常運行的,并且沒有SQL注入的問題。

所以,#{}相比于${},它支持所有類型的參數(shù),包括數(shù)值類與字符串類,而${}支持數(shù)值類型,不支持字符串類型的參數(shù),但也可以在原來sql里面為${}外面加上一對引號。

select * from userinfo where username='${username}'
//實際執(zhí)行語句
Preparing: select * from userinfo where username='張三'

當傳遞的參數(shù)為字符串類型的時候,雖然加上一對引號,使用${}也可以做到,但是${}存在SQL注入問題,所以仍然不推薦,有關SQL注入后面我們會介紹到。

大部分場合下,使用#{}都可以解決,但還是存在一小部分只能是${}來處理的。

如當我們需要按照升序或者逆序得到數(shù)據(jù)庫查詢結果的時候,這種場合就只能使用${},使用#{}會報錯,我們來演示一下。

首先,我們在Mapper接口中聲明一個方法:作用就是按照排序獲取結果集

public List<UserInfo> getOrderList(@Param(value = "order") String order);

我們再去xml文件中去寫sql語句:首先我們使用$進行演示

    <select id="getOrderList" resultType="com.example.demo.model.UserInfo">
        select * from userinfo order by createtime ${order};
    </select>

我們進行一個單元測試,單元測試代碼很簡單,就是調用sql,然后得到結果集:

    @Test
    void getOrderList() {
        List<UserInfo> userMappers = userMapper.getOrderList("desc");
        System.out.println(userMappers);
    }

單元測試結果:

可以正常查詢,得到的結果與預期也是相同的。

我們再來試一試使用#{}來構造sql語句:

    <select id="getOrderList" resultType="com.example.demo.model.UserInfo">
        select * from userinfo order by createtime #{order};
    </select>

單元測試邏輯與代碼不變,我們再來看看單元測試執(zhí)行的一個結果:

我們發(fā)現(xiàn)程序報錯了,這是因為使用了desc的字符串替換了占位符,而我們所需要的不是一個desc字符串,而是直接一個desc的關鍵字,所以sql也拋出了語法錯誤,最終執(zhí)行的sql為:

select * from userinfo order by createtime ‘desc';

期望執(zhí)行的sql為:

select * from userinfo order by createtime desc;

所以在傳遞sql關鍵字的時候,不能使用#{},只能使用${}

1.2SQL注入

SQL注入就是使用${},使用一些特殊的語句,來達到非法獲取數(shù)據(jù)的目的,如不通過正確的密碼獲取某賬戶的信息,下面我們來演示一下,就以登錄的例子來演示,SQL注入可以在不知道密碼的前提下登錄成功,并且獲取到用戶的相關信息。

首先我將數(shù)據(jù)庫只保留一個用戶信息,目的是為了方便演示SQL注入問題:

5

第一步,在Mapper接口中定義方法login,返回登錄成功的用戶對象。

public UserInfo login(@Param("username") String username, @Param(("password")) String password);

第二步,在xml文件中編寫SQL語句,我們需要演示SQL注入,所以我們使用${}來構造sql語句。

    <select id="login" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username='${username}' and password='${password}';
    </select>

第三步,編寫測試類,我們在這個測試類中,傳入有注入問題的SQL語句' or 1='1,使得不需要密碼就能拿到相關的用戶信息。

    @Test
    void login() {
        String username = "admin";
        String password = "' or 1='1";

        UserInfo userInfo = userMapper.login(username, password);
        System.out.println(userInfo);
    }

單元測試運行結果:

我們在不知道用戶密碼的情況下,登錄成功,并拿到了用戶的信息。

最終執(zhí)行的一段sql語句為:

select * from userinfo where username='admin' and password='' or 1='1';

相當于它在原來條件判斷的語句下,后面有加上一個或的邏輯,并且或后面的表達式為true,這樣就使得原來的SQL語句中的條件判斷部分一定為真,所以就在密碼不知道的情況下拿到了用戶的基本信息。

所以我們能不使用#{}就不使用${},因為存在SQL注入問題,如果必須使用${}則需要驗證一下傳遞的參數(shù)是否合法,比如上面定義排序的sql,傳遞的參數(shù)只能是desc或者是asc,如果不是就不能執(zhí)行這條SQL,防止SQL注入的發(fā)生。

1.3like查詢

在Mybatis中使用like查詢比較特殊,因為直接使用#{}會報錯,而使用${},由于輸入的字符串情況很多,無法做到枚舉,驗證比較困難,無法避免SQL注入問題。

首先,我們來演示使用#{}進行like查詢,步驟我就不詳細寫了,就是查詢的步驟。

第一步,聲明方法。

public List<UserInfo> getListByName(@Param("username") String username);

第二步,xml寫sql。

    <select id="getListByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username like '%#{username}%'
    </select>

第三步,單元測試。

    @Test
    void getListByName() {
        String username = "a";
        List<UserInfo> list = userMapper.getListByName(username);
        for (UserInfo userInfo : list) {
            System.out.println(userInfo);
        }
    }

運行結果:報錯了,因為#{}會被替換成一個字符串,而在這個%#{username}%語句中#{username}不能帶上引號,帶上就違背SQL語法,造成錯誤。

這個時候,由于#{}多出一對引號,${}無法枚舉所有情況進行驗證會產生SQL注入,所以不能直接使用#{},我們需要搭配MySQL內置的字符串拼接語句concat

我們將sql改為concat進行字符串拼接:

    <select id="getListByName" resultType="com.example.demo.model.UserInfo">
        select * from userinfo where username like concat('%', #{username}, '%')
    </select>

重新測試一下,發(fā)現(xiàn)可以正常執(zhí)行了:

1.4resultType與resultMap

resultType表示數(shù)據(jù)庫返回的數(shù)據(jù)映射在java程序中所對應的類型,只要定義類中的字段名與數(shù)據(jù)庫中表的字段名字一致就沒有任何問題,但是如果字段名存在沖突,則沖突的字段無法獲取到數(shù)據(jù)庫查詢的結果。

比如用戶名屬性在數(shù)據(jù)庫中的名字是username,而在java程序類中的屬性名為name,此時通過mybatis將數(shù)據(jù)傳遞到程序中的對象時,獲取到的name屬性為null,就不能正確地獲取到對應的屬性值,為了解決這個數(shù)據(jù)庫字段與類中中字段不匹配的問題,我們需要使用到resultMap。

resultMap的使用方式就是在xml文件中設置<resultMap>標簽,至少需要設置兩個屬性,一個是id表示你這個resultMap標簽的名字,還有一個是type屬性,它表示映射到程序中類的類型,需包含包名。

這個標簽里面需要設置至少兩個子標簽,一個是id標簽,另外一個是result標簽,前者表示主鍵,后者表示數(shù)據(jù)庫表中普通的列,這兩種標簽也是至少需要設置兩個屬性,一個是column表示數(shù)據(jù)庫表中的字段名,另外一個是property表示程序類中的字段名,如果只是在單表進行查詢,只設置不同字段名的映射就可以了,但是如果是多表查詢,必須將數(shù)據(jù)表中所有的字段與類中所有的字段生成映射關系。

就像下面這樣,圖中類與數(shù)據(jù)表字段是相同的,實際情況會存在不同的字段名:

1.4多表查詢

1.4.1一對一表映射

一對一關系就是對于一個屬性只與另外一個屬性有關系的映射,這就是一對一的關系,舉個例子,對于一篇博客,它只會對應到一個用戶,則博客與用戶的關系是一對一的關系,下面我們嘗試在mybatis中實現(xiàn)一對一多表聯(lián)查。

那么,首先我們先將數(shù)據(jù)庫的博客表與查程序中的博客類對應起來,就是按照數(shù)據(jù)庫中的博客表建立一個類:

9

@Data
public class Articleinfo {
    private Integer id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private Integer uid;
    private Integer rcount;
    private Integer state;
    //不妨多一個屬性,用戶表
    private UserInfo userInfo;
}

目前文章表中只有一條數(shù)據(jù),如下圖:

8

第二步,創(chuàng)建Mapper接口和對應的xml文件。

第三步,在接口中聲明方法和在xml中寫sql標簽與語句。

//根據(jù)文章名稱獲取文章對象
public Articleinfo getArticleById(@Param("id") Integer id);
    <select id="getArticleById" resultType="com.example.demo.model.Articleinfo">
        select * from articleinfo where id=#{id};
    </select>

第四步,編寫測試方法,我們直接調用查詢方法,然后使用日志輸出對象。

    @Test
    void getArticleById() {
        Articleinfo articleinfo = articleMapper.getArticleById(1);
        log.info("文章詳情:" + articleinfo);
    }

由于我們數(shù)據(jù)表與類的字段名是一致的,那些普通的屬性都一一對應上了,都成功被賦值了,但是由于UserInfo類在數(shù)據(jù)表中沒有,所以并沒有得到UserInfo對象,如果我們想要拿到這個對象,我們得使用resultMap

問題主要有兩個,第一,數(shù)據(jù)庫查詢到的用戶表沒有映射到UserInfo對象,第二,查詢的SQL語句是單表查詢語句,不是多表查詢語句。

所以想要實現(xiàn)一對一多表查詢,需要設置多表查詢SQL語句,我們使用左外連接進行多表查詢:

    <select id="getArticleById" resultMap="BaseMap">
        select a.*, u.* from articleinfo as a left join userinfo as u on  a.uid=u.id where a.id=#{id};
    </select>

此外,我們除了設置UserInfoArticleinfo類中每個屬性與數(shù)據(jù)表的映射之外,我們還要在Articleinfo類對應的resultMap中使用association標簽。最少需要設置兩個屬性,一個是property表示在主表Articleinfo中對應副表UserInfo映射對象的變量名,另外一個是副表UserInfo對應的resultMap。

Articleinfo類對應的resultMap:

    <resultMap id="BaseMap" type="com.example.demo.model.Articleinfo">
        <id column="id" property="id"></id>
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="uid" property="uid"></result>
        <result column="rcount" property="rcount"></result>
        <result column="state" property="state"></result>

        <association property="userInfo" resultMap="com.example.demo.mapper.UserMapper.BaseMap"></association>
    </resultMap>

UserInfo類對應的resultMap:

    <resultMap id="BaseMap" type="com.example.demo.model.UserInfo">
<!--        column 表示數(shù)據(jù)庫字段名 property 表示對應對象的字段名,設置這兩個值可以建立映射-->
<!--        主鍵約束-->
        <id column="id" property="id"></id>
<!--普通變量映射-->
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
        <result column="photo" property="photo"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="state" property="state"></result>
    </resultMap>

如果UserInfo類的resultMap沒有將所有的屬性都與數(shù)據(jù)庫的表映射,就會造成獲取到的userInfo對象中的數(shù)據(jù)不完整,假設只設置了idname的映射,那獲取到的對象只有idname有值。

將兩張表的resultMap映射好后,我們運行同樣的單元測試案例,運行結果如下:

但是,仍然存在一個問題,那就是我們所建的兩個表存在名字相同的字段,可能會出現(xiàn)數(shù)據(jù)覆蓋的情況,如兩個表的主鍵都叫id,但是id在兩個表的含義是不同的,在用戶表它表示用戶id,在文章表它表示文章的id,現(xiàn)在我們將獲取兩表的數(shù)據(jù)的id改為不相同,再來看一看單元測試運行的結果:

10

按理來說,由于不存在id1的用戶,所以獲取到UserInfo對象應該為null才對,但是運行的結果卻存在UserInfo對象,并且與文章表的重名字段都被賦值了文章表中的數(shù)據(jù),為了解決這個問題,我們必須在文章表(主表)的resultMap中設置屬性columnPrefix,它的值隨便設置,作用是識別副表字段時加上一段前綴,如我們給用戶表的字段加上前綴u_,此時sql中就不能使用*來一次表示所有元素了,需要一個一個單獨設置,并將字段全部重命名,帶上u_前綴 。

association字段設置:

<association property="userInfo" columnPrefix="u_" resultMap="com.example.demo.mapper.UserMapper.BaseMap" ></association>

SQL語句需要將用戶表的字段全部重命名:

    <select id="getArticleById" resultMap="BaseMap">
        select a.*, u.id as u_id,
               u.username as u_username,
               u.password as u_password,
               u.photo as u_photo,
               u.createtime as u_createtime,
               u.updatetime as u_updatetime,
               u.state as u_state
        from articleinfo as a left join userinfo as u on  a.uid=u.id where a.id=#{id};
    </select>

12

我們將userInfo對應的用戶表的id再改回為1,讓查詢有關于UserInfo類的數(shù)據(jù)。

再次運行單元測試案例:

我們是能夠獲取到相應的數(shù)據(jù)的,所以如果兩個表字段重名了,進行多表查詢時,需要設置columnPrefix屬性,這樣才能夠避免不同表同名字段數(shù)據(jù)覆蓋的問題。

所以,在創(chuàng)建數(shù)據(jù)庫的數(shù)據(jù)表時,盡量不要讓表與表中的字段重名。

1.4.2一對多表映射

一對多的關系,就是對于一個屬性,它對映著多個其他的屬性,比如用戶與博客之間的關系,一個用戶可以對應多篇博客,則用戶與博客之間的關系就是一對多的關系。同樣的下面我們嘗試使用mybatis實現(xiàn)多對多的多表聯(lián)查。

下面我們以用戶表為主,文章表為輔,來演示如何進行一對多關系的多表查詢。

既然是一對多的關系,那我們可以在UserInfo類中加上一個儲存ArticleInfo對象的List,來儲存用戶發(fā)布或所寫的文章。

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private String photo;
    private String createtime;
    private String updatetime;
    private Integer state;
    private List<Articleinfo> aList;
}

實現(xiàn)多表查詢的大致過程如下:

  • 在Mapper接口中聲明方法,我們聲明一個方法,就是通過用戶id獲取用戶信息以及對應的文章列表。
  • xml文件當中寫resultMap映射關系,與一對一多表查詢不同的是,我們需要設置collection標簽,而不是association標簽。
  • xml文件的resultMap標簽中至少設置resultMap名字id,對應映射的類type等屬性,里面需要設置數(shù)據(jù)表與類中所有字段的映射,以及設置collection標簽,需要設置property屬性表示需映射的對象名,設置resultMap即副表的resultMap路徑,由于你無法保證表與表之間是否存在重名字段,需要設置columnPrefix為副表的字段添加上一個前綴,防止重名數(shù)據(jù)覆蓋。
        <collection
                property="aList"
                resultMap="com.example.demo.mapper.ArticleMapper.BaseMap"
                columnPrefix="a_">
        </collection>

在對應的xml文件當中寫SQL標簽以及語句。

    <select id="getUserAndArticlesById" resultMap="BaseMap">
        select u.*, 
               a.id as a_id,
               a.title as a_title,
               a.content as a_content,
               a.createtime as a_createtime,
               a.updatetime as a_updatetime,
               a.uid as a_uid,
               a.rcount as a_rcount,
               a.state as a_state
               from userinfo as u left join articleinfo as a on u.id=a.uid where u.id=#{uid}
    </select>

編寫單元測試代碼,測試代碼是否編寫正確。

    @Test
    void getUserAndArticlesById() {
        Integer id = 1;
        UserInfo userInfo = userMapper.getUserAndArticlesById(id);
        log.info("用戶信息:" + userInfo);
    }

運行結果:

2.動態(tài)SQL

首先來說一下什么是動態(tài)SQL,官方文檔對于動態(tài)SQL的定義是:

動態(tài) SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據(jù)不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態(tài) SQL,可以徹底擺脫這種痛苦。使用動態(tài) SQL 并非一件易事,但借助可用于任何 SQL 映射語句中的強大的動態(tài) SQL 語言,MyBatis 顯著地提升了這一特性的易用性。

前面所說的mybatis增刪查改,那些傳入的參數(shù)都是一定會傳入的,但是在實際情況中,很多參數(shù)都是非必傳參數(shù),使用動態(tài)SQL就可以解決傳入的參數(shù)是非必傳參數(shù)的情況。

動態(tài)SQL可以解決多余符號的問題,如,等。

2.1if標簽

if標簽的作用就是判斷一個參數(shù)是否有值,如果沒有值就將對應的參數(shù)隱藏。

語法:

<if test="表達式">
	sql
</if>
//例如
<if test="參數(shù)!=null">
	sql部分語句
</if>

當表達式為真,則插入if標簽中的sql,否則不插入。

我們以在用戶表中插入一條數(shù)據(jù)為例,插入的數(shù)據(jù)中頭像photo不是必傳的參數(shù):

方法聲明:

    //使用動態(tài)sql插入數(shù)據(jù)
    public int addUser(UserInfo userInfo);

動態(tài)SQL語句:

其中的photo是非必傳參數(shù),我們使用if標簽來判斷它是否有值,沒有值就不插入目標的SQL語句。

    <insert id="addUser">
        insert into userinfo(username, password
        <if test="photo!=null">
            , photo
        </if>
        ) values(#{username}, #{password}
        <if test="photo!=null">
            , #{photo}
        </if>
        )
    </insert>

單元測試代碼:

    @Test
    void addUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("張三瘋");
        userInfo.setPassword("123456");

        int res = userMapper.addUser(userInfo);
        log.info("受影響的行數(shù)為:" + res);
    }

在單元測試代碼中,我沒有給photo賦值,if標簽會判斷它為空,不會插入對應photo的SQL,因此插入數(shù)據(jù)photo為默認值。

結果:

數(shù)據(jù)庫查詢結果:

18

再來試一試給photo傳值的情況,它生成的SQL有三個參數(shù):

    @Test
    void addUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("張無忌");
        userInfo.setPassword("12345611");
        userInfo.setPhoto("張無忌.png");
        int res = userMapper.addUser(userInfo);
        log.info("受影響的行數(shù)為:" + res);
    }

運行結果:

最終生成的語句多了一個photo參數(shù)。

2.2trim標簽

前面所說的if標簽可以實現(xiàn)非必傳參數(shù)SQL的構造,在極端情況下,有很多個非必傳參數(shù),此時如果只使用if標簽構造出的SQL語句很有可能會多出一個,,因為有很多非必傳參數(shù),如果只傳來一個參數(shù),由于不確定后面是否還會有參數(shù),因此會預留一個,,此時如果沒有其他參數(shù),就會多出一個參數(shù)。

trim標簽可以做到這一點,它可以去除SQL語句前后多余的某個字符,它需要搭配if標簽使用。

<trim>標簽中有如下屬性:

  • prefix:表示整個語句塊,以prefix的值作為前綴
  • suffix:表示整個語句塊,以suffix的值作為后綴
  • prefixOverrides:表示整個語句塊要去除掉的前綴
  • suffixOverrides:表示整個語句塊要去除掉的后綴

語法:

<trim prefix="前綴符", suffix="后綴符", prefixOverrides="去除多余的前綴字符", suffixOverrides="去除多余的后綴字符">
	<if test="表達式">
		...
	</if>
	...
	...
</trim>

假設username password photo都是非必傳參數(shù),但是至少傳遞一個,我們來寫插入語句的動態(tài)SQL。

    <insert id="addUser2">
        insert into userinfo
        <trim prefix="(" suffix=")" prefixOverrides="," suffixOverrides=",">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                password,
            </if>
            <if test="photo!=null">
                photo
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" prefixOverrides="," suffixOverrides=",">
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="photo!=null">
                #{photo}
            </if>
        </trim>
    </insert>

單元測試代碼:

    @Test
    void addUser2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("wangwu");
        userInfo.setPassword("12345622");
        int res = userMapper.addUser(userInfo);
        log.info("受影響的行數(shù)為:" + res);
    }

運行結果與生成的SQL語句:

我們發(fā)現(xiàn)逗號它自動去除了。

2.3where標簽

where標簽主要是實現(xiàn)where關鍵字的替換,如果SQL中沒有使用到where(沒有查詢條件),就會隱藏,存在查詢條件,就會生成含有where的查詢SQL語句,并且可以去除前面的and

我們就不以復雜的案例作為演示了,直接寫一個最簡單的查詢,為了簡單,我們刪除數(shù)據(jù)庫的其他數(shù)據(jù),只留admin一條數(shù)據(jù)。

21

下面我們來寫最簡單的查詢語句,就是根據(jù)id獲取一個用戶信息。

寫動態(tài)SQL時,我故意在最前面寫一個and來證明where標簽是可以自動刪除前面多余的and

    <select id="getUserById" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
        <where>
            <if test="id!=null">
                and id=#{id}
            </if>
        </where>
    </select>

單元測試代碼:

    @Test
    void gerUserById() {
        UserInfo userInfo = userMapper.getUserById(1);
        System.out.println(userInfo);
        //Assertions.assertNotNull(userInfo);
    }

結果:

發(fā)現(xiàn)自動生成了where語句并刪除了多余的and。

如果我們查詢一個null值,就不會生成where語句。

以上<where>標簽也可以使用 <trim prefix="where" prefixOverrides="and"> 替換。

2.4set標簽

其實set標簽與where標簽很相似,只不過where用來替換查詢SQL,set用于修改SQL中,用來自動生成set部分的SQL語句。

set標簽還可以自動去除最后面的一個,

比如我們寫一個能夠修改賬戶名username,密碼password,頭像photo的動態(tài)SQL,根據(jù)id進行修改。

方法聲明:

    //使用動態(tài)SQL實現(xiàn)修改用戶信息,包括賬戶名,密碼,頭像
    public int updateUser(UserInfo userInfo);

動態(tài)SQL:

    <update id="updateUser">
        update userinfo
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="photo!=null">
                photo=#{photo}
            </if>
        </set>
        where id=#{id}
    </update>

單元測試代碼:

    @Test
    void updateUser() {
        UserInfo userInfo = new UserInfo();
        //修改密碼為123456
        userInfo.setPassword("123456");
        userInfo.setId(1);
        int res = userMapper.updateUser(userInfo);
        log.info("受影響的行數(shù):" + res);
    }

運行結果:

修改成功并且可以根據(jù)傳入參數(shù)個數(shù)自動生成相應的修改SQL,以及可以自動去除最后的,


以上<set>標簽也可以使用 <trim prefix="set" suffixOverrides=","> 替換。

2.5foreach標簽

對集合進行遍歷可以使用foreach標簽,常用的場景有批量刪除功能。

  • collection:綁定方法參數(shù)中的集合,如 List,Set,Map或數(shù)組對象
  • item:遍歷時的每一個對象
  • open:語句塊開頭的字符串
  • close:語句塊結束的字符串
  • separator:每次遍歷之間間隔的字符串

為了方便演示批量刪除,我們隨便插入幾條數(shù)據(jù)到數(shù)據(jù)庫:

27

方法聲明:

    //使用動態(tài)sql批量刪除元素
    public int deleteIds(List<Integer> ids);

動態(tài)SQL語句:

    <delete id="deleteIds">`在這里插入代碼片`
        delete from userinfo where id in
        <foreach collection="ids" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

單元測試代碼:

刪除數(shù)據(jù)庫中id為10 11 12的用戶。

    @Test
    void deleteIds() {
        List<Integer> ids = new ArrayList<>();
        ids.add(10);
        ids.add(11);
        ids.add(12);
        
        int res = userMapper.deleteIds(ids);
        log.info("受影響的行數(shù)" + res);
    }

運行結果:

成功生成了批量刪除的SQL,這就是foreach標簽的作用,它能夠遍歷集合。

19

總結

到此這篇關于Mybatis多表查詢與動態(tài)SQL特性的文章就介紹到這了,更多相關Mybatis多表查詢與動態(tài)SQL內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Mysql中@和@@符號的詳細使用指南

    Mysql中@和@@符號的詳細使用指南

    最近工作遇到了一個問題,給自己做個記錄,下面這篇文章主要給大家介紹了關于Mysql中@和@@符號的詳細使用的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • CentOs7 64位 mysql 5.6.40源碼安裝過程

    CentOs7 64位 mysql 5.6.40源碼安裝過程

    這篇文章主要介紹了CentOs7 64位 mysql-5.6.40源碼安裝過程,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-01-01
  • Windows11下MySQL?8.0.29?安裝配置方法圖文教程

    Windows11下MySQL?8.0.29?安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了Windows11下MySQL?8.0.29?安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • MySQL中符號@的作用

    MySQL中符號@的作用

    本文主要介紹了MySQL中符號@的作用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • CentOS中mysql cluster安裝部署教程

    CentOS中mysql cluster安裝部署教程

    這篇文章主要介紹了在CentOS 6.3系統(tǒng)上搭建MySQL Cluster 7.2.25集群的相關資料,需要的朋友可以參考下。
    2016-11-11
  • MySQL中將逗號分隔的字段轉換為多行數(shù)據(jù)的方法

    MySQL中將逗號分隔的字段轉換為多行數(shù)據(jù)的方法

    在我們的實際開發(fā)中,經常需要存儲一些字段,它們使用像,?-?等連接符進行連接,在查詢過程中,有時需要將這些字段使用連接符分割,然后查詢多條數(shù)據(jù),今天,我們將使用一個實際的生產場景來詳細解釋這個解決方案,需要的朋友可以參考下
    2024-04-04
  • mysql主鍵,外鍵,非空,唯一,默認約束及創(chuàng)建表的方法

    mysql主鍵,外鍵,非空,唯一,默認約束及創(chuàng)建表的方法

    這篇文章主要介紹了mysql主鍵,外鍵,非空,唯一,默認約束及創(chuàng)建表的方法,在數(shù)據(jù)庫中,數(shù)據(jù)表是數(shù)據(jù)庫中最重要、最基本的操作對象,是數(shù)據(jù)存儲的基本單位
    2022-07-07
  • MYSQL使用正則表達式過濾數(shù)據(jù)

    MYSQL使用正則表達式過濾數(shù)據(jù)

    這篇文章主要介紹了MYSQL使用正則表達式過濾數(shù)據(jù)的相關資料,感興趣的小伙伴們可以參考一下
    2016-05-05
  • MySQL5.6升級5.7時出現(xiàn)主從延遲問題排查過程

    MySQL5.6升級5.7時出現(xiàn)主從延遲問題排查過程

    這篇文章主要介紹了MySQL5.6升級5.7時出現(xiàn)主從延遲問題排查過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • MySQL巧用sum、case和when優(yōu)化統(tǒng)計查詢

    MySQL巧用sum、case和when優(yōu)化統(tǒng)計查詢

    這篇文章主要給大家介紹了關于MySQL巧用sum、case和when優(yōu)化統(tǒng)計查詢的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03

最新評論