本节示例代码在 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)
没有数据了,符合预期 😆