MyBatis:添加、删除、修改数据


#Java Mybatis#


本节示例代码在 mybatis-demo-009

数据准备

MyBatis:数据准备

项目结构

使用 IDEA 创建 gradle 项目,最终结构如下:

添加数据

在 UserMapper 接口中定义方法:

/**
 * 根据 id 查询用户
 */
User findById(Long id);

在 UserMapper.xml 中编写映射:

<!--insertUser-->
<insert id="insertUser" parameterType="bean.User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO blog_db.user (name, email, password)
    VALUES (#{name}, #{email}, #{password})
</insert>

<insert> 中id为insertUser,和方法对应UserMapper接口中方法一致。parameterType和方法insertUser的参数类型一致。

我们的SQL语句,只插入了User的name、email、password,主键id依靠数据库的自动生成。在官方文档《Mapper XML 文件》中如下介绍useGeneratedKeys和keyProperty属性:

useGeneratedKeys:(仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。

keyProperty: (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

不太明白为什么会对update有用。先不管。

通过设置useGeneratedKeys和keyProperty属性,可以将生成的id注入到user对象的id字段中。

在Main类中编写示例代码:

import java.io.IOException;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import bean.User;
import mapper.UserMapper;
import org.junit.Test;


@Slf4j
public class Main {

    @Test
    public void test_insertUser() throws IOException {
        SqlSession sqlSession = getSqlSession(false);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setName("xiaowei");
        user.setEmail("xiaowei@111.com");
        user.setPassword("456");

        try {
            int result = userMapper.insertUser(user);
            log.info("result: {}, user: {}", result, user);
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
    }

    private SqlSession getSqlSession(boolean autoCommit) throws IOException {
        SqlSessionFactory sessionFactory;
        sessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsReader("mybatis-config.xml"));
        return sessionFactory.openSession(autoCommit);
    }

}

创建sqlSession时,我们新增了一个布尔参数 autoCommit。如字面意思,如为true,则开启自动commit,也就是每个insert、update、delete操作都会确确实实的将数据修改写入数据库中。而如果是false,则必须在一系列操作后,加上sqlSession.commit(),才能将数据修改真正写入数据库。

运行 test_insertUser 函数,结果:

 INFO [main] - result: 1, user: User(id=3, name=xiaowei, email=xiaowei@111.com, password=456)

新添加的记录id为3。

查看数据库:

mysql> select * from user;
+----+---------+-----------------+----------+
| id | name    | email           | password |
+----+---------+-----------------+----------+
|  1 | letian  | letian@111.com  | 123      |
|  2 | xiaosi  | xiaosi@111.com  | 123      |
|  3 | xiaowei | xiaowei@111.com | 456      |
+----+---------+-----------------+----------+
3 rows in set (0.00 sec)

根据 id 更新密码

在 UserMapper 接口中定义方法:

/**
 * 根据 id 更新密码
 * @return 影响的行数
 */
int updateUserPasswordById(User user);

在 UserMapper.xml 增加映射:

<update id="updateUserPasswordById" parameterType="bean.User">
    UPDATE blog_db.user
    SET password=#{password}
    WHERE id=#{id}
</update>

updateUserPasswordById 方法的参数是User类,在xml映射中User的变量会被解析出来,所以可以用占位符#{password}#{id}

在Main类中编写示例代码:

@Test
public void test_updateUserPasswordById() throws IOException {
    SqlSession sqlSession = getSqlSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = new User();
    user.setId(3L);
    user.setPassword("123456");

    try {
        int result = userMapper.updateUserPasswordById(user);
        log.info("result: {}, user: {}", result, user);
        sqlSession.commit();
    } finally {
        sqlSession.close();
    }
}

运行结果:

 INFO [main] - result: 1, user: User(id=3, name=null, email=null, password=123456)

查看数据库:

mysql> select * from user;
+----+---------+-----------------+----------+
| id | name    | email           | password |
+----+---------+-----------------+----------+
|  1 | letian  | letian@111.com  | 123      |
|  2 | xiaosi  | xiaosi@111.com  | 123      |
|  3 | xiaowei | xiaowei@111.com | 123456   |
+----+---------+-----------------+----------+
3 rows in set (0.00 sec)

可以看到 id为3的记录的密码从456变成了123456。

删除指定 id 的记录

在 UserMapper 接口中定义方法:

/**
 * 删除指定id的记录
 * @return 影响的行数
 */
int deleteById(Long id);

在 UserMapper.xml 增加映射:

<delete id="deleteById" parameterType="Long">
    DELETE FROM blog_db.user WHERE id=#{id}
</delete>

在Main类中编写示例代码,删除id为3的记录:

@Test
public void test_deleteById() throws IOException {
    SqlSession sqlSession = getSqlSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    try {
        int result = userMapper.deleteById(3L);
        log.info("result: {}", result);
        sqlSession.commit();
    } finally {
        sqlSession.close();
    }
}

运行结果:

 INFO [main] - result: 1

因为id为3的记录已经被删除了,所以若再运行一次,结果为:

 INFO [main] - result: 0

查看数据库:

mysql> select * from user;
+----+--------+----------------+----------+
| id | name   | email          | password |
+----+--------+----------------+----------+
|  1 | letian | letian@111.com | 123      |
|  2 | xiaosi | xiaosi@111.com | 123      |
+----+--------+----------------+----------+
2 rows in set (0.00 sec)

删除指定 id 范围的记录

在 UserMapper 接口中定义方法:

/**
 * 删除id在 [minId, maxId] 范围内的记录
 * @return 影响的行数
 */
int deleteByIdRange(Long minId, Long maxId);

在 UserMapper.xml 增加映射:

<delete id="deleteByIdRange">
    <![CDATA[
        DELETE FROM blog_db.user WHERE id >= #{param1} and id <= #{param2}
    ]]>
</delete>

在Main类中编写示例代码,删除id为1到2的记录:

@Test
public void test_deleteByIdRange() throws IOException {
    SqlSession sqlSession = getSqlSession(false);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    try {
        int result = userMapper.deleteByIdRange(1L, 2L);
        log.info("result: {}", result);
        sqlSession.commit();
    } finally {
        sqlSession.close();
    }
}

运行结果:

 INFO [main] - result: 2

查看数据库:

mysql> select * from user;
Empty set (0.00 sec)

没有数据了,符合预期 😆


( 本文完 )