让咱们回忆一下上篇博客中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请求,因此嗯。。。就酱。