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