本文目录导读:

我来为你提供一个完整的MyBatis修改(更新)操作案例,包含从基础到进阶的开发方式。
基础环境准备
1 数据库表结构
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(100) NOT NULL, `email` varchar(100) DEFAULT NULL, `phone` varchar(20) DEFAULT NULL, `status` tinyint(4) DEFAULT '1', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2 Maven依赖
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.20</version>
</dependency>
</dependencies>
实体类定义
// User.java
public class User {
private Long id;
private String username;
private String password;
private String email;
private String phone;
private Integer status;
private Date createTime;
private Date updateTime;
// getters and setters... (省略具体实现)
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", status=" + status +
'}';
}
}
XML映射文件开发方式
1 Mapper接口
// UserMapper.java
public interface UserMapper {
// 根据ID更新
int updateById(User user);
// 选择性更新(只更新非空字段)
int updateSelective(User user);
// 批量更新
int batchUpdate(List<User> userList);
// 根据条件更新
int updateByCondition(@Param("user") User user,
@Param("condition") UserCondition condition);
}
2 XML映射文件
<!-- UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- 基础更新 -->
<update id="updateById">
UPDATE user
SET username = #{username},
password = #{password},
email = #{email},
phone = #{phone},
status = #{status},
update_time = NOW()
WHERE id = #{id}
</update>
<!-- 选择性更新(动态SQL) -->
<update id="updateSelective">
UPDATE user
<set>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="email != null">email = #{email},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="status != null">status = #{status},</if>
update_time = NOW()
</set>
WHERE id = #{id}
</update>
<!-- 批量更新 -->
<update id="batchUpdate">
<foreach collection="list" item="user" separator=";">
UPDATE user
<set>
<if test="user.username != null">username = #{user.username},</if>
<if test="user.password != null">password = #{user.password},</if>
<if test="user.email != null">email = #{user.email},</if>
<if test="user.phone != null">phone = #{user.phone},</if>
update_time = NOW()
</set>
WHERE id = #{user.id}
</foreach>
</update>
<!-- 根据条件更新 -->
<update id="updateByCondition">
UPDATE user
<set>
<if test="user.username != null">username = #{user.username},</if>
<if test="user.email != null">email = #{user.email},</if>
<if test="user.phone != null">phone = #{user.phone},</if>
update_time = NOW()
</set>
<where>
<if test="condition.id != null">AND id = #{condition.id}</if>
<if test="condition.username != null">AND username = #{condition.username}</if>
<if test="condition.status != null">AND status = #{condition.status}</if>
</where>
</update>
</mapper>
注解开发方式
// UserMapperAnnotation.java
public interface UserMapperAnnotation {
@Update("UPDATE user SET username=#{username}, email=#{email}, " +
"phone=#{phone}, update_time=NOW() WHERE id=#{id}")
int updateById(User user);
@Update({
"<script>",
"UPDATE user",
"<set>",
"<if test='username != null'>username=#{username},</if>",
"<if test='email != null'>email=#{email},</if>",
"<if test='phone != null'>phone=#{phone},</if>",
"update_time=NOW()",
"</set>",
"WHERE id=#{id}",
"</script>"
})
int updateSelective(User user);
@Update({
"<script>",
"<foreach collection='list' item='user' separator=';'>",
"UPDATE user",
"<set>",
"<if test='user.username != null'>username=#{user.username},</if>",
"<if test='user.email != null'>email=#{user.email},</if>",
"update_time=NOW()",
"</set>",
"WHERE id=#{user.id}",
"</foreach>",
"</script>"
})
int batchUpdate(List<User> userList);
}
Service层实现
// UserService.java
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 完整更新
public boolean updateUser(User user) {
if (user.getId() == null) {
throw new IllegalArgumentException("ID不能为空");
}
return userMapper.updateById(user) > 0;
}
// 选择性更新(推荐使用)
public boolean updateUserSelective(User user) {
if (user.getId() == null) {
throw new IllegalArgumentException("ID不能为空");
}
return userMapper.updateSelective(user) > 0;
}
// 批量更新
public int batchUpdateUsers(List<User> userList) {
if (CollectionUtils.isEmpty(userList)) {
return 0;
}
return userMapper.batchUpdate(userList);
}
// 带事务的更新
@Transactional(rollbackFor = Exception.class)
public boolean updateUserWithTransaction(User user) {
// 先更新
int result = userMapper.updateSelective(user);
// 记录日志(假设有日志表)
// logMapper.insertUpdateLog(user.getId(), "更新用户信息");
return result > 0;
}
}
完整测试案例
// MyBatisUpdateTest.java
@SpringBootTest
@RunWith(SpringRunner.class)
public class MyBatisUpdateTest {
@Autowired
private UserService userService;
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Test
public void testUpdateById() {
User user = new User();
user.setId(1L);
user.setUsername("新用户名");
user.setEmail("newemail@example.com");
user.setPhone("13800138000");
user.setStatus(1);
boolean success = userService.updateUser(user);
Assert.assertTrue("更新失败", success);
}
@Test
public void testUpdateSelective() {
// 只更新邮箱和电话
User user = new User();
user.setId(1L);
user.setEmail("updated@example.com");
user.setPhone("13900139000");
boolean success = userService.updateUserSelective(user);
Assert.assertTrue("更新失败", success);
}
@Test
public void testBatchUpdate() {
List<User> userList = new ArrayList<>();
User user1 = new User();
user1.setId(1L);
user1.setEmail("user1@example.com");
User user2 = new User();
user2.setId(2L);
user2.setEmail("user2@example.com");
userList.add(user1);
userList.add(user2);
int result = userService.batchUpdateUsers(userList);
Assert.assertEquals(2, result);
}
@Test
public void testUpdateWithTransaction() {
User user = new User();
user.setId(1L);
user.setUsername("事务更新测试");
user.setEmail("transaction@example.com");
boolean success = userService.updateUserWithTransaction(user);
Assert.assertTrue("事务更新失败", success);
}
@Test
public void testSqlSessionFactoryUpdate() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(1L);
user.setEmail("session@example.com");
int result = mapper.updateSelective(user);
sqlSession.commit();
Assert.assertEquals(1, result);
} finally {
sqlSession.close();
}
}
}
性能优化建议
1 批量更新优化
// 使用批量更新时,建议开启批量执行模式
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
// 配置批量执行器
org.apache.ibatis.session.Configuration configuration =
new org.apache.ibatis.session.Configuration();
configuration.setDefaultExecutorType(ExecutorType.BATCH);
sessionFactory.setConfiguration(configuration);
return sessionFactory.getObject();
}
}
2 使用批量更新语句
<!-- 使用CASE WHEN进行批量更新(更高效) -->
<update id="batchUpdateByCase">
UPDATE user
SET email = CASE id
<foreach collection="list" item="item">
WHEN #{item.id} THEN #{item.email}
</foreach>
END,
phone = CASE id
<foreach collection="list" item="item">
WHEN #{item.id} THEN #{item.phone}
</foreach>
END,
update_time = NOW()
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id}
</foreach>
</update>
注意事项
- 必须包含WHERE条件:避免误更新全表
- 选择性更新优势:使用
<set>标签只更新非空字段 - 版本控制:建议添加乐观锁字段防止并发问题
- 大数据量批量更新:避免一次性更新过多数据,建议分批处理
- 事务管理:涉及多条更新操作时,务必使用事务
这个案例涵盖了MyBatis修改操作的常见场景,你可以根据实际需求选择合适的方式。