mybatis批量操作汇总

1.批量insert或update
在mapper中使用foreach来实现

2.同时批量insert和update
a.mysql
在mapper中使用foreach结合on duplicate update来实现。

b.Oracle
在mapper中使用foreach结合merge into来实现。

c.如果使用了mybatisplus
它提供了批量save或update,根据id。

d.在代码中使用mybatis的BATCH模式

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
public int batchSaveOrUpdate(List<FPlayerSuspend> list) {
if (null == list || list.isEmpty()) return 0;

SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
FPlayerSuspendMapper mapper = session.getMapper(FPlayerSuspendMapper.class);
try {
int size = list.size();
UpdateWrapper<FPlayerSuspend> wrapper = new UpdateWrapper<>();
for (int i = 0; i < size; i++) {
FPlayerSuspend item = list.get(i);
// 如果缓存或数据库存在,则判断是否变化 变化则更新 缓存或数据库不存在则插入
FPlayerSuspend cache = getFromDbIfCacheNotExist(item.getMatchId(),item.getPlayerId());

if (null == cache)
mapper.insert(item);
else {
// 数据变化则更新
if (isDataChange(item,cache)) {
wrapper.eq("schedule_id", item.getMatchId())
.eq("player_id", item.getPlayerId());
mapper.update(item, wrapper);
}
}
if (i % 1000 == 999 || i == size - 1) {
session.commit();
session.clearCache();
}
}
} catch (Exception e) {
log.error("批量插入或更新球探球员伤停数据出错", e);
session.rollback();
} finally {
session.close();
}

return 0;
}

上面的代码执行的是如果数据库有则更新,没有则插入的逻辑。实际上是有list.size()次数的数据库查询。可以将上面逻辑改为saveOrUpdate(在mapper中实现)。这样就避免了数据库查询,而是在提交到数据库之后才会去查询数据然后做相应处理。

如果使用java8,那么可以调整为下面的形式:
首先定义一个函数式接口

1
2
3
4
5
6
7
8
9
10
/**
* @author Donny
* @createTime 2019-07-10 15:05
* @description 批量操作数据库的函数式接口定义
*/
@FunctionalInterface
public interface BatchDbOperationInterface<A,B> {
// A为要操作的javabean类型,B为相应的Mybatis Mapper
void apply(A type,B mapper);
}

下面封装JDBC的批量操作

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
@Component
@Slf4j
public class BatchDBOperationImpl {
@Autowired
private SqlSessionTemplate sqlSessionTemplate;

public <A,B> int batchStatment(List<A> list, Class<B> mapperClass, BatchDbOperationInterface<A,B> function) {
if (null == list || list.isEmpty()) return 0;
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
B mapper = session.getMapper(mapperClass);
try {
int size = list.size();
for (int i = 0; i < size; i++) {
A item = list.get(i);
function.apply(item,mapper);
if (i % 1000 == 999 || i == size - 1) {
session.commit();
session.clearCache();
}
}

return size;
} catch (Exception e) {
log.error("批量插入或更新数据出错", e);
session.rollback();
} finally {
session.close();
}
return 0;
}
}

使用方:

1
2
3
4
5
6
@Autowired
private BatchDBOperationImpl batchDBOperation;

public int batchSaveIfNotExist(List<BEuropeOddsDetail> details) {
return batchDBOperation.batchStatment(details, BEuropeOddsDetailMapper.class,(item,mapper)->mapper.insertIfNotExist(item));
}

Donny wechat
欢迎关注我的个人公众号
打赏,是超越赞的一种表达。
Show comments from Gitment