最近在读刘增辉老师所著的《MyBatis从入门到精通》一书,颇有收获,因而将本身学习的过程以博客形式输出,若有错误,欢迎指正,如帮助到你,不胜荣幸!java
假如如今咱们想新增一个用户,该如何操做呢?git
首先,在接口SysUserMapper中添加以下方法。github
/** * 新增用户 * * @param sysUser * @return */ int insert(SysUser sysUser);
而后打开对应的SysUserMapper.xml文件,添加以下语句。sql
<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,就是二进制数据流。mybatis
3)因为数据库区分date、time、datetime类型,可是在Java中通常都使用java.util.Date类型。所以为了保证数据类型的正确,须要手动指定日期类型。date、time、datetime对应的JDBC类型分别为DATE、TIME、TIMESTAMP。app
在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.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.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标签,其中:
若是数据库是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>
假如咱们如今但愿经过主键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
假如咱们如今但愿经过主键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
源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。
刘增辉《MyBatis从入门到精通》