MyBatis從入門到精通(四):MyBatis XML方式的基本用法之增刪改

最近在讀劉增輝老師所著的《MyBatis從入門到精通》一書,頗有收穫,因而將本身學習的過程以博客形式輸出,若有錯誤,歡迎指正,如幫助到你,不勝榮幸!java

1. insert用法

1.1 簡單的insert方法

假如如今咱們想新增一個用戶,該如何操做呢?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.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. 源碼

源碼地址:https://github.com/zwwhnly/mybatis-action.git,歡迎下載。

5. 參考

劉增輝《MyBatis從入門到精通》

相關文章
相關標籤/搜索