MyBatis 中,如何实现逻辑删除?
在 MyBatis 中,可以通过两种方式实现逻辑删除:
- 使用 UPDATE 语句,将删除标志位置为已删除
在数据库表中增加一个标志列,通常取名为 delete_flag
,表示该行记录是否被删除。在执行删除操作时,不是真正地删除记录,而是将 delete_flag
的值设置为已删除状态。通过在查询语句中加入 delete_flag
的判断,就可以实现逻辑删除的效果。
例如,在一个用户表中添加 delete_flag
字段表示删除标志:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标志',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
在 mapper 的配置文件中,可以定义一个 UPDATE 语句来将指定的用户记录的 delete_flag
字段更新为已删除状态:
<update parameterType="int">
update user set delete_flag=1 where id=#{id}
</update>
在查询用户时,需要加入对 delete_flag
的判断:
<select parameterType="int" resultMap="userMap">
select * from user where id=#{id} and delete_flag=0
</select>
<select resultMap="userMap">
select * from user where delete_flag=0
</select>
- 使用拦截器,拦截 DELETE 语句并修改为更新语句
这种方式使用拦截器实现,可以自动将 DELETE 语句转换为 UPDATE 语句,并将记录状态修改为已删除状态。
在拦截器中覆盖 Executor
的 delete
方法,在方法中自定义 DELETE 语句的转换,然后调用 update
方法执行修改操作。
在 mapper 的配置文件中,仍然定义 DELETE 语句,但实际执行的操作是 UPDATE 语句:
<delete parameterType="int">
delete from user where id=#{id} and delete_flag=0
</delete>
需要注意的是,使用拦截器的方式有一定的风险,需要慎重考虑是否使用,并避免影响到其他的 DELETE 操作。
MyBatis 中,如何处理悲观锁和乐观锁?
在 MyBatis 中,可以使用悲观锁和乐观锁来保证数据的并发安全。
- 悲观锁
悲观锁就是在操作数据之前先锁住数据,以防止其他的并发操作。在 MyBatis 中,可以使用以下方式实现悲观锁:
- 在查询语句中使用 FOR UPDATE,需要手动去申请锁,MyBatis 不会自动去加锁。例如:
<select resultType="User">
select * from user where id = #{id} for update
</select>
- 使用 Mysql 的隐式加行锁,只需要在配置文件中设置对应的参数,例如:
<settings>
<setting name="cacheEnabled" value="false" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="autoMappingBehavior" value="FULL" />
<setting name="defaultStatementTimeout" value="25000" />
<setting name="defaultFetchSize" value="100" />
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="LOG4J"/>
<setting name="mysql" value="true"/>
</settings>
- 乐观锁
乐观锁是指在操作数据时,通过版本号或时间戳等方式来判断是否有其他操作并发修改,如果有,则不进行更新操作,否则进行操作。在 MyBatis 中,可以通过以下方式实现乐观锁:
- 在实体类中增加一个版本字段,用于记录数据更新的版本号或时间戳等信息。例如:
public class User {
private Long id;
private String name;
private int version; // 版本号
// getter 和 setter 方法
}
在更新操作时,先查询并锁定行,然后比较版本号或时间戳,如果一致则更新数据并增加版本号或时间戳的值,如果不一致则不进行更新。
例如,利用 UPDATE
语句实现乐观锁:
<update parameterType="User">
update user
set name = #{name}, version = #{version} + 1
where id = #{id} and version = #{version}
</update>
在执行更新操作时,在业务层代码中获取原始数据的版本号或时间戳,然后在执行更新操作时,设置新的版本号或时间戳,并将旧的版本号或时间戳作为更新的条件,判断是否受到并发操作的影响。如果更新失败,则需要处理并发操作失败的情况。
以上就是 MyBatis 中处理悲观锁和乐观锁的方法,可以根据实际需求选择合适的方法。