MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
最近在读刘增辉老师所著的《mybatis从入门到精通》一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸!
1. insert用法
1.1 简单的insert方法
假如现在我们想新增一个用户,该如何操作呢?
首先,在接口sysusermapper中添加如下方法。
/** * 新增用户 * * @param sysuser * @return */ int insert(sysuser sysuser);
然后打开对应的sysusermapper.xml文件,添加如下语句。
<insert id="insert"> insert into sys_user(id, user_name, user_password, user_email, user_info, head_img, create_time) values (#{id},#{username},#{userpassword},#{useremail},#{userinfo},#{headimg,jdbctype=blob},#{createtime,jdbctype=timestamp}) </insert>
特别说明:
1)为了防止类型错误,对于一些特殊的数据类型,建议指定具体的jdbctype值。例如headimg指定blob类型,createtime指定timestamp类型。
2)blob对应的类型是bytearrayinputstream,就是二进制数据流。
3)由于数据库区分date、time、datetime类型,但是在java中一般都使用java.util.date类型。因此为了保证数据类型的正确,需要手动指定日期类型。date、time、datetime对应的jdbc类型分别为date、time、timestamp。
在sysusermappertest测试类中添加如下代码,测试下insert()方法。
@test public void testinsert() { sqlsession sqlsession = getsqlsession(); try { sysusermapper sysusermapper = sqlsession.getmapper(sysusermapper.class); sysuser sysuser = new sysuser(); sysuser.setusername("test1"); sysuser.setuserpassword("123456"); sysuser.setuseremail("test@mybatis.tk"); sysuser.setuserinfo("test info"); // 正常情况下应该读入一张图片保存到byte数组中 sysuser.setheadimg(new byte[]{1, 2, 3}); sysuser.setcreatetime(new date()); // 这里的返回值result是执行的sql影响的行数 int result = sysusermapper.insert(sysuser); // 只插入1条数据 assert.assertequals(1, result); // id为null,没有给id赋值,并且没有配置回写id的值 assert.assertnull(sysuser.getid()); } finally { // 为了不影响其他测试,这里选择回滚 // 默认的sqlsessionfactory.opensession()是不自动提交的 // 因此不手动执行commit也不会提交到数据库 sqlsession.rollback(); sqlsession.close(); } }
运行该测试方法,输出日志如下。
debug [main] - ==> preparing: insert into sys_user(id, user_name, user_password, user_email, user_info, head_img, create_time) values (?,?,?,?,?,?,?)
debug [main] - ==> parameters: null, test1(string), 123456(string), test@mybatis.tk(string), test info(string), java.io.bytearrayinputstream@544a2ea6(bytearrayinputstream), 2019-07-02 13:09:07.822(timestamp)
debug [main] - <== updates: 1
现在我们修改下createtime指定的jdbctype类型,直观的理解下jdbctype值的作用。
createtime,jdbctype=date
再次运行测试方法,日志中createtime字段的值如下。
2019-07-02(date)
再次修改createtime指定的jdbctype类型为time。
createtime,jdbctype=time
再次运行测试方法,发现报如下错误:
报错的原因是,数据库中的字段类型为datetime,但是这里只有time部分的值。
通过上面的测试,说明数据库的datetime类型可以存储date(时间部分默认为00:00:00)和timestamp这两种类型的时间,不能存储time类型的时间。
1.2 返回主键值(jdbc方式)
在1.1的例子中,新增完数据,我们并没有拿到数据库中自增的id值,但有些场景中,我们需要先拿到数据库中自增的值,然后再处理其余的逻辑,那么如何拿到数据库中的自增的id值呢?
首先,在接口sysusermapper中添加方法如下。
/** * 新增用户-使用usegeneratedkeys方式 * * @param sysuser * @return */ int insertusegeneratedkeys(sysuser sysuser);
然后打开对应的sysusermapper.xml,添加如下代码。
<insert id="insertusegeneratedkeys" usegeneratedkeys="true" keyproperty="id"> insert into sys_user(user_name, user_password, user_email, user_info, head_img, create_time) values (#{username},#{userpassword},#{useremail},#{userinfo},#{headimg,jdbctype=blob},#{createtime,jdbctype=timestamp}) </insert>
usegeneratedkeys设置为ture后,mybatis会使用jdbc的getgeneratedkeys()方法来取出由数据库内部生成的主键。获取到主键后将其赋值给keyproperty配置的id属性。
在sysusermappertest测试类中添加如下代码,测试新增的insertusegeneratedkeys()方法。
@test public void testinsertusegeneratedkeys() { sqlsession sqlsession = getsqlsession(); try { sysusermapper sysusermapper = sqlsession.getmapper(sysusermapper.class); sysuser sysuser = new sysuser(); sysuser.setusername("test1"); sysuser.setuserpassword("123456"); sysuser.setuseremail("test@mybatis.tk"); sysuser.setuserinfo("test info"); // 正常情况下应该读入一张图片保存到byte数组中 sysuser.setheadimg(new byte[]{1, 2, 3}); sysuser.setcreatetime(new date()); // 这里的返回值result是执行的sql影响的行数 int result = sysusermapper.insertusegeneratedkeys(sysuser); // 只插入1条数据 assert.assertequals(1, result); // 因为id回写,所以id不为null assert.assertnotnull(sysuser.getid()); } finally { sqlsession.rollback(); sqlsession.close(); } }
运行该测试方法,测试通过,输出日志如下。
debug [main] - ==> preparing: insert into sys_user(user_name, user_password, user_email, user_info, head_img, create_time) values (?,?,?,?,?,?)
debug [main] - ==> parameters: test1(string), 123456(string), test@mybatis.tk(string), test info(string), java.io.bytearrayinputstream@544a2ea6(bytearrayinputstream), 2019-07-02 14:02:22.506(timestamp)
debug [main] - <== updates: 1
1.3 返回主键值(selectkey方式)
1.2中回写主键的方法只适用于支持主键自增的数据库。
但有些数据库(比如oracle)不提供主键自增的功能,而是使用序列得到一个值,然后将这个值赋给id,再将数据插入到数据库。
对于这种情况,就可以采用selectkey方式,因为selectkey方式不仅适用于不提供主键自增功能的数据库,也适用于提供主键自增功能的数据库。
我们先来看下mysql的例子。
首先,在接口sysusermapper中添加如下方法。
/** * 新增用户-使用selectkey方式 * * @param sysuser * @return */ int insertuseselectkey(sysuser sysuser);
然后打开对应的sysusermapper.xml文件,添加如下代码。
<insert id="insertuseselectkey"> insert into sys_user(user_name, user_password, user_email, user_info, head_img, create_time) values (#{username},#{userpassword},#{useremail},#{userinfo},#{headimg,jdbctype=blob},#{createtime,jdbctype=timestamp}) <selectkey keycolumn="id" resulttype="long" keyproperty="id" order="after"> select last_insert_id() </selectkey> </insert>
和1.2相比,这里的语句多了selectkey标签,其中:
- keycolumn:主键的数据库列名。
- resulttype:返回值类型。
- keyproperty:主键对应的属性名。
- order:该属性的设置和使用的数据库有关,如果使用的是mysql数据库,设置的值是after,因为当前记录的主键值在insert语句执行成功后才能获取到。如果使用的是oracle数据库,设置的值是before,因为oracle中需要先从序列获取值,然后将值作为主键插入到数据库中。
如果数据库是oracle的话,语句如下(因为环境问题,以下代码我并未验证,有兴趣的同学可以自己试下)。
<insert id="insertuseselectkey"> <selectkey keycolumn="id" resulttype="long" keyproperty="id" order="before"> select seq_id.nextval from dual </selectkey> insert into sys_user(id,user_name, user_password, user_email, user_info, head_img, create_time) values (#{id},#{username},#{userpassword},#{useremail},#{userinfo},#{headimg,jdbctype=blob},#{createtime,jdbctype=timestamp}) </insert>
2. update用法
假如我们现在希望通过主键id来更新用户信息,该如何操作呢?
首先,在接口sysusermapper中添加如下方法。
/** * 根据主键更新 * * @param sysuser * @return */ int updatebyid(sysuser sysuser);
然后,打开对应的sysusermapper.xml文件,添加如下代码。
<update id="updatebyid"> update sys_user set user_name = #{username}, user_password = #{userpassword}, user_email = #{useremail}, user_info = #{userinfo}, head_img = #{headimg,jdbctype=blob}, create_time = #{createtime,jdbctype=timestamp} where id = #{id} </update>
最后在sysusermappertest测试类中,添加如下测试方法。
@test public void testupdatebyid() { sqlsession sqlsession = getsqlsession(); try { sysusermapper sysusermapper = sqlsession.getmapper(sysusermapper.class); sysuser sysuser = sysusermapper.selectbyid(1l); assert.assertequals("admin", sysuser.getusername()); sysuser.setusername("admin_test"); sysuser.setuseremail("admin_test@mybatis.tk"); sysuser.setuserinfo("test info"); // 正常情况下应该读入一张图片保存到byte数组中 sysuser.setheadimg(new byte[]{1, 2, 3}); sysuser.setcreatetime(new date()); // 这里的返回值result是执行的sql影响的行数 int result = sysusermapper.updatebyid(sysuser); // 只更新1条数据 assert.assertequals(1, result); sysuser = sysusermapper.selectbyid(1l); assert.assertequals("admin_test", sysuser.getusername()); assert.assertequals("admin_test@mybatis.tk", sysuser.getuseremail()); } finally { sqlsession.rollback(); sqlsession.close(); } }
运行测试方法,测试通过,输出的部分日志如下。
debug [main] - ==> preparing: update sys_user set user_name = ?, user_password = ?, user_email = ?, user_info = ?, head_img = ?, create_time = ? where id = ?
debug [main] - ==> parameters: admin_test(string), 123456(string), admin_test@mybatis.tk(string), test info(string), java.io.bytearrayinputstream@78186a70(bytearrayinputstream), 2019-07-02 14:57:34.792(timestamp), 1(long)
debug [main] - <== updates: 1
3. delete用法
假如我们现在希望通过主键id来删除用户信息,该如何操作呢?
首先,在接口sysusermapper中添加如下方法。
/** * 根据主键删除 * * @param id * @return */ int deletebyid(long id); /** * 根据对象的主键删除 * * @param sysuser * @return */ int deletebysysuser(sysuser sysuser);
然后,打开对应的sysusermapper.xml文件,添加如下代码。
<delete id="deletebyid"> delete from sys_user where id = #{id} </delete> <delete id="deletebysysuser"> delete from sys_user where id = #{id} </delete>
最后在sysusermappertest测试类中,添加如下测试方法。
@test public void testdeletebyid() { sqlsession sqlsession = getsqlsession(); try { sysusermapper sysusermapper = sqlsession.getmapper(sysusermapper.class); sysuser sysuser = sysusermapper.selectbyid(1l); assert.assertnotnull(sysuser); // 这里是直接根据id删除 int result = sysusermapper.deletebyid(1l); // 只删除1条数据 assert.assertequals(1, result); assert.assertnull(sysusermapper.selectbyid(1l)); sysuser sysuser2 = sysusermapper.selectbyid(1001l); assert.assertnotnull(sysuser2); // 这里是根据对象的id属性删除 assert.assertequals(1, sysusermapper.deletebysysuser(sysuser2)); assert.assertnull(sysusermapper.selectbyid(1001l)); } finally { sqlsession.rollback(); sqlsession.close(); } }
运行测试方法,测试通过,输出的部分日志如下。
debug [main] - ==> preparing: delete from sys_user where id = ?
debug [main] - ==> parameters: 1(long)
debug [main] - <== updates: 1
4. 源码
源码地址:,欢迎下载。
5. 参考
刘增辉《mybatis从入门到精通》
上一篇: 学习第二天:总结
下一篇: Linux基础:uniq命令总结
推荐阅读
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select
-
MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select