bboyjing's blog

MybatisGenerator插件开发六【逻辑删除】

逻辑删除在项目中也是很常见的,比较常见的方式是添加一个deleted的标记位,当然也有其他的实现方式。本章节的插件针对的是添加标记位的方式来实现逻辑删除的。如果说没有和deleted标记位一起的唯一联合索引,那是很容易实现的,标志位只要两个值:0、1,然后通过updateByExampleSelective修改就可以了。但是往往我们表中会有唯一索引在,比如说名字不能重复之类的。这个时候我们采取的简单的处理方式是set deleted = deleted + 1来避免无法删除已经删除过的数据的问题。索性这个插件就提供了两个方法:logicDeletelogicDeleteWithUIndex

修改Mapper接口和SqlMap文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
public class LogicDeletePlugin extends PluginAdapter {
@Override
public boolean validate(List<String> list) {
return true;
}
/**
* 修改Mapper类
*/
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
addLogicDeleteMethod(interfaze);
return true;
}
private void addLogicDeleteMethod(Interface interfaze) {
// 方法的返回值
FullyQualifiedJavaType returnTypeInt = FullyQualifiedJavaType.getIntInstance();
Method logicDeleteMethod = new Method();
// 1.设置方法可见性
logicDeleteMethod.setVisibility(JavaVisibility.PUBLIC);
// 2.设置返回值类型 int类型
logicDeleteMethod.setReturnType(returnTypeInt);
// 3.设置方法名
logicDeleteMethod.setName("logicDelete");
// 4.设置参数列表
FullyQualifiedJavaType paramType = PrimitiveTypeWrapper.getLongInstance();
logicDeleteMethod.addParameter(new Parameter(paramType, "id"));
interfaze.addMethod(logicDeleteMethod);
Method logicDeleteWithUIndexMethod = new Method();
// 1.设置方法可见性
logicDeleteWithUIndexMethod.setVisibility(JavaVisibility.PUBLIC);
// 2.设置返回值类型 int类型
logicDeleteWithUIndexMethod.setReturnType(returnTypeInt);
// 3.设置方法名
logicDeleteWithUIndexMethod.setName("logicDeleteWithUIndex");
// 4.设置参数列表
FullyQualifiedJavaType paramTypeSelective = PrimitiveTypeWrapper.getLongInstance();
logicDeleteWithUIndexMethod.addParameter(new Parameter(paramTypeSelective, "id", "@Param(\"id\")"));
logicDeleteWithUIndexMethod.addParameter(new Parameter(FullyQualifiedJavaType.getStringInstance(), "uIndexes", "@Param(\"uIndexes\")", true));
interfaze.addMethod(logicDeleteWithUIndexMethod);
}
/**
* 修改Mapper.xml
*/
@Override
public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
addLogicDeleteXml(document, introspectedTable);
addLogicDeleteWithUIndexXml(document, introspectedTable);
return true;
}
private void addLogicDeleteXml(Document document, IntrospectedTable introspectedTable) {
XmlElement logicDeleteElement = new XmlElement("update");
logicDeleteElement.addAttribute(new Attribute("id", "logicDelete"));
logicDeleteElement.addAttribute(new Attribute("parameterType", "java.lang.Long"));
logicDeleteElement.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()));
logicDeleteElement.addElement(new TextElement("set deleted = 1, update_time = REPLACE(unix_timestamp(current_timestamp(3)),'.','') where id = #{id,jdbcType=BIGINT}"));
document.getRootElement().addElement(logicDeleteElement);
}
private void addLogicDeleteWithUIndexXml(Document document, IntrospectedTable introspectedTable) {
XmlElement logicDeleteWithUIndexElement = new XmlElement("update");
logicDeleteWithUIndexElement.addAttribute(new Attribute("id", "logicDeleteWithUIndex"));
logicDeleteWithUIndexElement.addAttribute(new Attribute("parameterType", "map"));
logicDeleteWithUIndexElement.addElement(new TextElement("update " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime() + " A,"));
logicDeleteWithUIndexElement.addElement(new TextElement("(select C.deleted from " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime() + " C,"));
logicDeleteWithUIndexElement.addElement(new TextElement("(select"));
XmlElement foreachElement = new XmlElement("foreach");
foreachElement.addAttribute(new Attribute("collection", "uIndexes"));
foreachElement.addAttribute(new Attribute("index", "index"));
foreachElement.addAttribute(new Attribute("item", "column"));
foreachElement.addAttribute(new Attribute("separator", ","));
foreachElement.addElement(new TextElement("${column}"));
logicDeleteWithUIndexElement.addElement(foreachElement);
logicDeleteWithUIndexElement.addElement(new TextElement("from " + introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime() + " where id = #{id,jdbcType=BIGINT}) D"));
XmlElement whereElement = new XmlElement("where");
XmlElement whereForachElement = new XmlElement("foreach");
whereForachElement.addAttribute(new Attribute("collection", "uIndexes"));
whereForachElement.addAttribute(new Attribute("index", "index"));
whereForachElement.addAttribute(new Attribute("item", "column"));
whereForachElement.addElement(new TextElement(" and C.${column} = D.${column}"));
whereElement.addElement(whereForachElement);
logicDeleteWithUIndexElement.addElement(whereElement);
logicDeleteWithUIndexElement.addElement(new TextElement("order by C.deleted desc limit 1) B"));
logicDeleteWithUIndexElement.addElement(new TextElement("set A.deleted = B.deleted + 1, A.update_time = REPLACE(unix_timestamp(current_timestamp(3)),'.','')"));
logicDeleteWithUIndexElement.addElement(new TextElement("where A.id = #{id,jdbcType=BIGINT}"));
logicDeleteWithUIndexElement.addElement(new TextElement("and A.deleted = 0"));
document.getRootElement().addElement(logicDeleteWithUIndexElement);
}
}

逻辑比较简单,就是在Mapper接口和SqlMap文件中添加方法和对应的sql语句就可以了。

查看生成文件

将插件添加到项目中,并且运行完MybatisGenerator,我们来查看下生成的相关文件:

1
2
3
4
5
public interface AdministratorMapper {
...
int logicDelete(Long id);
int logicDeleteWithUIndex(@Param("id") Long id, @Param("uIndexes") String ... uIndexes);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<update id="logicDelete" parameterType="java.lang.Long">
update administrator
set deleted = 1, update_time = REPLACE(unix_timestamp(current_timestamp(3)),'.','') where id = #{id,jdbcType=BIGINT}
</update>
<update id="logicDeleteWithUIndex" parameterType="map">
update administrator A,
(select C.deleted from administrator C,
(select
<foreach collection="uIndexes" index="index" item="column" separator=",">
${column}
</foreach>
from administrator where id = #{id,jdbcType=BIGINT}) D
<where>
<foreach collection="uIndexes" index="index" item="column">
and C.${column} = D.${column}
</foreach>
</where>
order by C.deleted desc limit 1) B
set A.deleted = B.deleted + 1, A.update_time = REPLACE(unix_timestamp(current_timestamp(3)),'.','')
where A.id = #{id,jdbcType=BIGINT}
and A.deleted = 0
</update>

如何使用

使用方式如下:

这里同样用到了之前添加到Model类中的表字段枚举。

1
administratorMapper.logicDeleteWithUIndex(id, Administrator.COLUMNS.MOBILE.getColumn()

本章节就到这里了。以后要用插件来实现一些特殊的Sql,应该可以举一反三了。