Skip to content

Commit 5c0efc3

Browse files
chentianming11abel533
authored andcommitted
渐进式处理Mapper
1 parent 6493164 commit 5c0efc3

1 file changed

Lines changed: 159 additions & 0 deletions

File tree

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package tk.mybatis.mapper.common.progressive;
2+
3+
import org.apache.ibatis.session.RowBounds;
4+
import tk.mybatis.mapper.annotation.RegisterMapper;
5+
import tk.mybatis.mapper.common.ExampleMapper;
6+
import tk.mybatis.mapper.common.rowbounds.SelectByExampleRowBoundsMapper;
7+
import tk.mybatis.mapper.entity.Example;
8+
import tk.mybatis.mapper.util.Assert;
9+
import tk.mybatis.mapper.util.Sqls;
10+
11+
import java.lang.reflect.Field;
12+
import java.lang.reflect.ParameterizedType;
13+
import java.lang.reflect.Type;
14+
import java.util.List;
15+
import java.util.function.Consumer;
16+
17+
/**
18+
* 渐进式处理Mapper,数据库必须包含id字段
19+
* @author 陈添明
20+
*/
21+
@RegisterMapper
22+
public interface ProgressiveMapper<T> extends ExampleMapper<T>, SelectByExampleRowBoundsMapper<T> {
23+
24+
/**
25+
* 渐进式记录处理
26+
* 数据表必须包含id字段
27+
* @param consumer 业务处理逻辑
28+
* @throws NoSuchFieldException 没有id字段会抛出此异常
29+
* @throws IllegalAccessException 无法访问id字段会抛出此异常
30+
*/
31+
default void handleRecordProgressive(Consumer<T> consumer) throws NoSuchFieldException, IllegalAccessException {
32+
Class<?> clz = getParameterType();
33+
long i = 0;
34+
while (true) {
35+
Example example = Example.builder(clz)
36+
.andWhere(Sqls.custom().andGreaterThan("id", i))
37+
.build();
38+
List<T> list = selectByExampleAndRowBounds(example, new RowBounds(0, 100));
39+
if (list.isEmpty()) {
40+
return;
41+
}
42+
for (T t : list) {
43+
consumer.accept(t);
44+
}
45+
T t = list.get(list.size() - 1);
46+
47+
Field idField = t.getClass().getDeclaredField("id");
48+
idField.setAccessible(true);
49+
i = (Long) idField.get(t);
50+
}
51+
52+
}
53+
54+
/**
55+
* 渐进式全量删除
56+
* 数据表必须包含id字段
57+
* 不会因为数据量大导致慢sql
58+
* @throws NoSuchFieldException 没有id字段会抛出此异常
59+
* @throws IllegalAccessException 无法访问id字段会抛出此异常
60+
*/
61+
default void deleteAllProgressive() throws NoSuchFieldException, IllegalAccessException {
62+
Class<?> parameterType = getParameterType();
63+
Long minimumId = getMinimumId();
64+
if (minimumId == null) {
65+
return;
66+
}
67+
68+
Long maxId = getMaxId();
69+
if (maxId == null) {
70+
return;
71+
}
72+
73+
for (Long i = minimumId; i <= maxId; ) {
74+
i = i + 10000;
75+
Example example = Example.builder(parameterType)
76+
.andWhere(Sqls.custom().andBetween("id", minimumId, i))
77+
.build();
78+
deleteByExample(example);
79+
}
80+
}
81+
82+
/**
83+
* 获取泛型参数Class
84+
*
85+
* @return 泛型参数Class
86+
*/
87+
default Class<?> getParameterType() {
88+
Type[] genericInterfaces = this.getClass().getGenericInterfaces();
89+
Class<?> rawClass = (Class<?>) genericInterfaces[0];
90+
Type[] rawClassGenericInterfaces = rawClass.getGenericInterfaces();
91+
Assert.isTrue(rawClassGenericInterfaces.length > 0, "Mapper类必须继承泛型Mapper");
92+
ParameterizedType mapperType = getParameterizedType(rawClassGenericInterfaces);
93+
Assert.notNull(mapperType, "未找到参数化Mapper类型!");
94+
return (Class<?>) mapperType.getActualTypeArguments()[0];
95+
}
96+
97+
/**
98+
* 获取ParameterizedType
99+
* @param rawClassGenericInterfaces 参数化接口
100+
* @return ParameterizedType
101+
*/
102+
default ParameterizedType getParameterizedType(Type[] rawClassGenericInterfaces) {
103+
for (Type genericInterface : rawClassGenericInterfaces) {
104+
if (genericInterface instanceof ParameterizedType) {
105+
return (ParameterizedType) genericInterface;
106+
}
107+
}
108+
return null;
109+
}
110+
111+
112+
/**
113+
* 获取最小id
114+
* @return 最小id
115+
* @throws NoSuchFieldException 没有id字段会抛出此异常
116+
* @throws IllegalAccessException 无法访问id字段会抛出此异常
117+
*/
118+
default Long getMinimumId() throws NoSuchFieldException, IllegalAccessException {
119+
Class<?> parameterType = getParameterType();
120+
Example example = Example.builder(parameterType)
121+
.select("id")
122+
.orderBy("id")
123+
.build();
124+
125+
List<T> list = selectByExampleAndRowBounds(example, new RowBounds(0, 1));
126+
if (list.isEmpty()) {
127+
return null;
128+
}
129+
T t = list.get(0);
130+
Field idField = t.getClass().getDeclaredField("id");
131+
idField.setAccessible(true);
132+
return (Long) idField.get(t);
133+
}
134+
135+
/**
136+
* 获取最大id
137+
* @return 最大id
138+
* @throws NoSuchFieldException 没有id字段会抛出此异常
139+
* @throws IllegalAccessException 无法访问id字段会抛出此异常
140+
*/
141+
default Long getMaxId() throws NoSuchFieldException, IllegalAccessException {
142+
Class<?> parameterType = getParameterType();
143+
Example example = Example.builder(parameterType)
144+
.select("id")
145+
.orderByDesc("id")
146+
.build();
147+
148+
List<T> list = selectByExampleAndRowBounds(example, new RowBounds(0, 1));
149+
if (list.isEmpty()) {
150+
return null;
151+
}
152+
T t = list.get(0);
153+
Field idField = t.getClass().getDeclaredField("id");
154+
idField.setAccessible(true);
155+
return (Long) idField.get(t);
156+
}
157+
158+
159+
}

0 commit comments

Comments
 (0)