让我们回忆一下上篇博客中mybatis是怎样发挥它的作用的,主要是三类文件,第一mapper接口,第二xml文件,第三全局配置文件(application.properties),而今天我们就是来简化mybatis的工作的——利用注解替代xml配置文件。
先贴出mapper接口代码
@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接口文件如下
@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就可以直接解决这个问题。首先将问题分个类
if+set/where
例如现在前台将这样一个对象传过来
{
"id":1,
"age":12
}
我控制器的方法为
//更新用户
public String updateUser(User user)throws Exception{
userService.updateUser(user);
return "id为"+user.getId()+"的用户更新了";
}
如果我直接更新到后台显然会把这条记录之前的用户名给覆盖为空(在数据库允许该字段为空的情况下),所以看直接来看我的动态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>
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>
foreach
我们在开发的时候经常会遇到这样的需求,删除多个对象,前台直接传一个对象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抽取出来,供别的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请求,所以嗯。。。就酱。
spring boot整合mybatis基于注解开发以及动态sql的使用的更多相关文章
-
Spring Boot整合MyBatis(非注解版)
Spring Boot整合MyBatis(非注解版),开发时采用的时IDEA,JDK1.8 直接上图: 文件夹不存在,创建一个新的路径文件夹 创建完成目录结构如下: 本人第一步习惯先把需要的包结构创建 ...
-
Spring Boot 整合 Mybatis Annotation 注解的完整 Web 案例
摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 公司需要人.产品.业务和方向,方向又要人.产品.业务和方向,方向… 循环』 本文提纲一. ...
-
Spring Boot整合Mybatis完成级联一对多CRUD操作
在关系型数据库中,随处可见表之间的连接,对级联的表进行增删改查也是程序员必备的基础技能.关于Spring Boot整合Mybatis在之前已经详细写过,不熟悉的可以回顾Spring Boot整合Myb ...
-
Spring Boot 实战 —— MyBatis(注解版)使用方法
原文链接: Spring Boot 实战 -- MyBatis(注解版)使用方法 简介 MyBatis 官网 是这么介绍它自己的: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过 ...
-
Spring Boot整合Mybatis并完成CRUD操作
MyBatis 是一款优秀的持久层框架,被各大互联网公司使用,本文使用Spring Boot整合Mybatis,并完成CRUD操作. 为什么要使用Mybatis?我们需要掌握Mybatis吗? 说的官 ...
-
spring boot 整合 mybatis 以及原理
同上一篇文章一样,spring boot 整合 mybatis过程中没有看见SqlSessionFactory,sqlsession(sqlsessionTemplate),就连在spring框架整合 ...
-
Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题
现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warnin ...
-
Spring Boot系列(三):Spring Boot整合Mybatis源码解析
一.Mybatis回顾 1.MyBatis介绍 Mybatis是一个半ORM框架,它使用简单的 XML 或注解用于配置和原始映射,将接口和Java的POJOs(普通的Java 对象)映射成数据库中的记 ...
-
Spring Boot整合Mybatis报错InstantiationException: tk.mybatis.mapper.provider.base.BaseSelectProvider
Spring Boot整合Mybatis时一直报错 后来发现原来主配置类上的MapperScan导错了包 由于我使用了通用Mapper,所以应该导入通用mapper这个包
随机推荐
-
Java poi读取,写入Excel,处理row和cell可能为空的情况
首先需要导入包 import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.NP ...
-
AngularJS初始化普通数组和对象数组
普通数组: ng-init="persons=['john','jack']" 对象数组: ng-init="persons=[{name:'john',age:20}, ...
-
linux log find 查询
常用的日志查询命令:find 1.从根目录开始查找所有扩展名为.log的文本文件,并找出包含”ERROR”的行: find / -type f -name "*.log" | xa ...
-
Microsoft Edge与Google Chrome那些不同的举止
以下针对14393版本Edge与Chrome 54 html dom/select的如果options里没有符合的值时edge会选择第一个,chrome(54)会置空选项 html dom/input ...
-
Spring Security3实现,权限动态获取
Spring Security3实现,权限动态获取 原文 http://blog.csdn.net/yangwei19680827/article/details/9359113 主题 网络安全Sp ...
-
ios开发-指纹识别
最近我们使用支付宝怎么软件的时候,发现可以使用指纹了,看起来是否的高大上.当时苹果推出了相关接口,让程序写起来很简单哈. 在iPhone5s的时候,苹果推出了指纹解锁.但是在ios8.0的时候苹果才推 ...
-
redis两种持久化方法对比分析
1.前言 最近在项目中使用到Redis做缓存,方便多个业务进程之间共享数据.由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能, ...
-
windows server 2016安装
slmgr /skms kms.03k.org slmgr /ato slmgr /ipk WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY kms服务器: https://03k.org/ ...
-
js删除数组中元素的方法
一.清空数组 var ary = [1,2,3,4]; ary.splice(0,ary.length);//清空数组 console.log(ary); // 输出 [],空数组,即被清空了 二.删 ...
-
django 关于render的返回数据
1,问题探讨 : 通过ajax 发送请求,接受render返回的数据.到底是什么样的类型呢? def text(request): # v = reverse("test") # ...