讓咱們回憶一下上篇博客中mybatis是怎樣發揮它的做用的,主要是三類文件,第一mapper接口,第二xml文件,第三全局配置文件(application.properties),而今天咱們就是來簡化mybatis的工做的——利用註解替代xml配置文件。spring
先貼出mapper接口代碼sql
@Mapper
public interface UserMapper { //獲取用戶名單 public List<User> getUser() throws Exception; //根據id刪除用戶 public void deleteUser(int id)throws Exception; //新增用戶 public void addUser(User user)throws Exception; //修改用戶信息 public void updateUser(User user) throws Exception; }
相較於上次的代碼新增了一個修改用戶信息的接口,然而怎麼作才能替代xml呢???數據庫
針對以上的增刪改查的操做,有四個註解@Select、@Delete、@Insert、@Update,在註解中加上以前在xml中寫的sql就好了,因此完整的mapper接口文件以下json
@Mapper
public interface UserMapper { //獲取用戶名單 @Select("select * from user") public List<User> getUser() throws Exception; //根據id刪除用戶 @Delete("delete from user where id = #{id}") public void deleteUser(int id)throws Exception; //新增用戶 @Insert("insert into user(id,username,age)values(#{id},#{username},#{age})") public void addUser(User user)throws Exception; //修改用戶信息 @Update("update user set username = #{name} where id = #{id}") public void updateUser(User user) throws Exception; }
剩下的service和controller中的代碼很簡單,和xml開發中的寫法保持一致。須要值得注意的是不要忘記在各個接口和類中類名前的位置加上對應的註解,@Mapper、@Service、@Component等,否則spring是掃描不到的。這裏有個小技巧,若是在啓動類中加上註解@MapperScan(「com.XX.dao」),便可以省去@Mapper註解數組
說完了註解的開發咱們來看一下這樣的需求,若是咱們要往數據庫中更新一個對象,前臺傳過來的對象中有幾個屬性沒有賦值,因此咱們controller接收時就會將這幾個屬性置空,而咱們須要更新不爲空的屬性,這時該怎麼辦??固然能夠在service中將這個對象處理後再更新到數據庫中,可是其實動態sql就能夠直接解決這個問題。首先將問題分個類瀏覽器
例如如今前臺將這樣一個對象傳過來mybatis
{
"id":1,
"age":12
}
我控制器的方法爲app
//更新用戶 public String updateUser(User user)throws Exception{ userService.updateUser(user); return "id爲"+user.getId()+"的用戶更新了"; }
若是我直接更新到後臺顯然會把這條記錄以前的用戶名給覆蓋爲空(在數據庫容許該字段爲空的狀況下),因此看直接來看個人動態sql代碼post
<update id="updateUser" parameterType="com.fc.pojo.User"> update user set <if test = "username != null"> user.username = #{username}, </if> <if test = "age != 0"> user.age = #{age} </if>
where id = #{id} </update>
這樣的sql拼接代碼看起來很簡單,可是有一個問題,若是age屬性爲0(前臺若是不傳age屬性的話默認賦值爲0)的話,最終sql語句會變成 update user set user.username =?,where id = ?測試
這樣顯然也是不對的,因此mybatis爲咱們提供了<set></set>標籤將多餘的逗號去掉,因此最終的動態sql變成
<update id="updateUser" parameterType="com.fc.pojo.User"> update user <set> <if test = "username != null"> user.username = #{username}, </if> <if test = "age != 0"> user.age = #{age} </if> </set> where id = #{id} </update>
這樣就解決了咱們的問題了。同理在select語句中,也有這樣的問題
<select id="getUser" parameterType="com.fc.pojo.User" resultType="com.fc.pojo.User"> select * from user where <if test="username != null"> username=#{username} </if> <if test="age!= null"> and age=#{age} </if> </select>
若是age爲空的話sql就變成了select * from user where and age=?,因此要加上<where></where>標籤,這樣改進後的xml就是
<select id="getUser" parameterType="com.fc.pojo.User" resultType="com.fc.pojo.User"> select * from user <where> <if test="username != null"> username=#{username} </if> <if test="age!= null"> and age=#{age} </if> </where> </select>
咱們在開發的時候常常會遇到這樣的需求,刪除多個對象,前臺直接傳一個對象id的集合,這個時候常規的作法是對集合處理,將id拿出來一個個刪掉,其實也能夠將集合放入一個包裝類中,直接把包裝類做爲parameterType傳入xml中,在xml中處理id集合。下面是包裝類,我加上了數組的方式,不只是id集合,還有id數組,均可以用這種方法來作
public class UserVo { private List<Integer>idList;//id集合 private int[]idArray; //id數組 public List<Integer> getIdList() { return idList; } public void setIdList(List<Integer> idList) { this.idList = idList; } public int[] getIdArray() { return idArray; } public void setIdArray(int[] idArray) { this.idArray = idArray; } }
而xml文件中要使用foreach標籤,在el表達式中和js中好像都有相似的用法,用來作循環操做,須要注意的是collection的值應該和包裝類中的屬性名保持一致。具體代碼以下
<!-- 以id集合刪除用戶 --> <delete id="deleteByIdList" parameterType="com.fc.pojo.UserVo"> delete from user where id in <foreach item="id" collection="idList" open="(" separator="," close=")"> #{id} </foreach> </delete> <!-- 以id數組刪除用戶 --> <delete id="deleteByIdArray" parameterType="com.fc.pojo.UserVo"> delete from user where id in <foreach item="id" collection="idArray" open="(" separator="," close=")"> #{id} </foreach> </delete>
而後是Controller代碼
//刪除id集合 @RequestMapping(value="deleteByIdList",method=RequestMethod.DELETE) public String deleteByIdList(@RequestBody UserVo userVo)throws Exception{ userService.deleteByIdList(userVo); return "id列表裏的用戶都刪掉了"; } //刪除id數組 @RequestMapping(value="deleteByIdArray",method=RequestMethod.DELETE) public String deleteByIdArray(@RequestBody UserVo userVo)throws Exception{ userService.deleteByIdArray(userVo); return "id數組裏的用戶都刪掉了"; }
mapper接口和service的代碼我就不貼了,套路跟以前都是同樣的
最後是用來測試的json,第一個是測數組的,第二個測集合的
{
"idArray":[1,2,3]
}
{
"idList":[1,2,3]
}
sql片斷就是將一段重複率較高的sql抽取出來,供別的sql調用,這樣能夠有效地提升代碼的複用率,話很少說,好比咱們在新增一個用戶時須要返回新增用戶id,而咱們以前的代碼中已經有新增用戶的sql,重複寫一遍顯得畫蛇添足了,就能夠把插入語句抽取出來供屢次調用,代碼以下,爲了看到效果,我把以前的新增用戶的語句也使用調用sql片斷的方法來作
<sql id="base_insert_sql" > insert into user(id,username,age)values(#{id},#{username},#{age}) </sql> <!-- 新增用戶 --> <insert id="addUser" parameterType="com.fc.pojo.User"> <include refid="base_insert_sql" /> </insert> <!-- 新增用戶,返回用戶id --> <insert id="addUserWithId" parameterType="com.fc.pojo.User"> <selectKey keyProperty="id" resultType="int"> select LAST_INSERT_ID() </selectKey> <include refid="base_insert_sql" /> </insert>
好了,我在開發中經常使用到的動態sql就這些了,而後把以上xml文件轉爲註解的方法我就懶得去作了,有空再補上,最後安利一款測試軟件Postman,挺好用的,公司也在用這個,以上的全部代碼都是我用PostMan測試經過的,畢竟瀏覽器也發不了post和delete請求,因此嗯。。。就醬。