1 Mybatis動態SQL

word發表於2022-05-05

Mybatis動態SQL

1. 註解開發

​ 我們也可以使用註解的形式來進行開發,用註解來替換掉xml。 使用註解來對映簡單語句會使程式碼顯得更加簡潔,但對於稍微複雜一點的語句,Java 註解不僅力不從心,還會讓你本就複雜的 SQL 語句更加混亂不堪。 所以我們在實際企業開發中一般都是使用XML的形式。

1.1 步驟

①在核心配置檔案中配置mapper介面所在的包名

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

②在介面對應方法上使用註解來配置需要執行的sql

public interface UserDao {

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

    @Insert("insert into user values(null,#{username},#{age},#{address})")
    void insertUser(User user);

    @Update("UPDATE USER SET age = #{age} , username = #{username},address = #{address} WHERE id = #{id}")
    void updateUser(User user);

    @Delete("delete from user where id = #{id}")
    void deleteById(Integer id);
}

③和之前的一樣獲取Mapper呼叫方法即可

    public static void main(String[] args) throws IOException {
        //定義mybatis配置檔案的路徑
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //獲取Sqlsession物件
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //獲取UserDao實現類物件
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        //呼叫方法測試
        List<User> userList = userDao.findAll();
        System.out.println(userList);
        //釋放資源
        sqlSession.close();
    }

2.動態SQL

​ 在實際開發中的SQL語句沒有之前的這麼簡單,很多時候需要根據傳入的引數情況動態的生成SQL語句。Mybatis提供了動態SQL相關的標籤讓我們使用。

2.1 if

​ 可以使用if標籤進行條件判斷,條件成立才會把if標籤中的內容拼接進sql語句中。

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
         select * from user
         where  id = #{id}
        <if test="username!=null">
           and username = #{username}
        </if>
    </select>

如果引數username為null則執行的sql為:select * from user where id = ?

如果引數username不為null則執行的sql為:select * from user where id = ? and username = ?

注意:在test屬性中表示引數的時候不需要寫#{},寫了會出問題。

2.2 trim

​ 可以使用該標籤動態的新增字首或字尾,也可以使用該標籤動態的消除字首。

2.2.1 prefixOverrides屬性

​ 用來設定需要被清除的字首,多個值可以用|分隔,注意|前後不要有空格。例如: and|or

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim prefixOverrides="and|or" >
            and
        </trim>
    </select>

最終執行的sql為: select * from user

2.2.2 suffixOverrides屬性

​ 用來設定需要被清除的字尾,多個值可以用|分隔,注意|前後不要有空格。例如: and|or

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim suffixOverrides="like|and" >
            where 1=1 like
        </trim>
    </select>

最終執行的sql為: select * from user 去掉了字尾like

2.2.3 prefix屬性

​ 用來設定動態新增的字首,如果標籤中有內容就會新增上設定的字首

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim prefix="where" >
           1=1
        </trim>
    </select>

最終執行的sql為:select * from user where 1=1 動態增加了字首where

2.2.4 suffix屬性

​ 用來設定動態新增的字尾,如果標籤中有內容就會新增上設定的字尾

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim suffix="1=1" >
           where
        </trim>
    </select>

最終執行的sql為:select * from user where 1=1 動態增加了字尾1=1

2.2.5 動態新增字首where 並且消除字首and或者or

User findByCondition(@Param("id") Integer id,@Param("username") String username);
    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <trim prefix="where" prefixOverrides="and|or" >
            <if test="id!=null">
                id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
        </trim>
    </select>

呼叫方法時如果傳入的id和username為null則執行的SQL為:select * from user

呼叫方法時如果傳入的id為null,username不為null,則執行的SQL為:select * from user where username = ?

2.2 where

​ where標籤等價於:

<trim prefix="where" prefixOverrides="and|or" ></trim>

​ 可以使用where標籤動態的拼接where並且去除字首的and或者or。

例如:

    <select id="findByCondition" resultType="com.sangeng.pojo.User">
        select * from user
        <where>
            <if test="id!=null">
                id = #{id}
            </if>
            <if test="username!=null">
                and username = #{username}
            </if>
        </where>
    </select>

如果id和username都為null,則執行的sql為:**select * from user **

如果id為null,username不為null,則執行的sql為:**select * from user where username = ? **

2.3 set

​ set標籤等價於

<trim prefix="set" suffixOverrides="," ></trim>

​ 可以使用set標籤動態的拼接set並且去除字尾的逗號。

例如:

    <update id="updateUser">
        UPDATE USER
        <set>
            <if test="username!=null">
                username = #{username},
            </if>
            <if test="age!=null">
                age = #{age},
            </if>
            <if test="address!=null">
                address = #{address},
            </if>
        </set>
        
    </update>

如果呼叫方法時傳入的User物件的id為2,username不為null,其他屬性都為null則最終執行的sql為:UPDATE USER SET username = ? where id = ?

2.4 foreach

​ 可以使用foreach標籤遍歷集合或者陣列型別的引數,獲取其中的元素拿來動態的拼接SQL語句。

例如:

方法定義如下

List<User> findByIds(@Param("ids") Integer[] ids);

如果期望動態的根據實際傳入的陣列的長度拼接SQL語句。例如傳入長度為4個陣列最終執行的SQL為:

select * from User WHERE id in( ? , ? , ? , ?, ? ) 

則在xml對映檔案中可以使用以下寫法

	<select id="findByIds" resultType="com.sangeng.pojo.User">
        select * from User
        <where>
            <foreach collection="ids" open="id in(" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>

collection:表示要遍歷的引數。

open:表示遍歷開始時拼接的語句

item:表示給當前遍歷到的元素的取的名字

separator:表示每遍歷完一次拼接的分隔符

close:表示最後一次遍歷完拼接的語句

注意:如果方法引數是陣列型別,預設的引數名是array,如果方法引數是list集合預設的引數名是list。建議遇到陣列或者集合型別的引數統一使用@Param註解進行命名。

2.5 choose、when、otherwise

​ 當我們不想使用所有的條件,而只是想從多個條件中選擇一個使用時。可以使用choose系列標籤。類似於java中的switch。

例如:

介面中方法定義如下

List<User> selectChose(User user);

期望:

​ 如果user物件的id不為空時就通過id查詢。

​ 如果id為null,username不為null就通過username查詢。

​ 如果id和username都會null就查詢id為3的使用者

xml對映檔案如下

 	<select id="selectChose" resultType="com.sangeng.pojo.User">
        select * from user
        <where>
            <choose>
                <when test="id!=null">
                    id = #{id}
                </when>
                <when test="username!=null">
                    username = #{username}
                </when>
                <otherwise>
                    id = 3
                </otherwise>
            </choose>
        </where>
    </select>
  • choose類似於java中的switch

  • when類似於java中的case

  • otherwise類似於java中的dufault

​ 一個choose標籤中最多隻會有一個when中的判斷成立。從上到下去進行判斷。如果成立了就把標籤體的內容拼接到sql中,並且不會進行其它when的判斷和拼接。如果所有的when都不成立則拼接otherwise中的語句。

3. SQL片段抽取

​ 我們在xml對映檔案中編寫SQL語句的時候可能會遇到重複的SQL片段。這種SQL片段我們可以使用sql標籤來進行抽取。然後在需要使用的時候使用include標籤進行使用。

例如:

    <sql id="baseSelect" >id,username,age,address</sql>
    <select id="findAll" resultType="com.sangeng.pojo.User">
        select <include refid="baseSelect"/>  from user
    </select>

最終執行的sql為: select id,username,age,address from user

相關文章