近日在公司項(xiàng)目中,使用到spring+mybatis的架構(gòu),特對(duì)mybatis的batch模式做了相關(guān)研究,得出以下結(jié)論:
1.Mybatis內(nèi)置的ExecutorType有3種,默認(rèn)的是simple,該模式下它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句,單條提交sql;而batch模式重復(fù)使用已經(jīng)預(yù)處理的語(yǔ)句,
1.Mybatis內(nèi)置的ExecutorType有3種,默認(rèn)的是simple,該模式下它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句,單條提交sql;而batch模式重復(fù)使用已經(jīng)預(yù)處理的語(yǔ)句,
并且批量執(zhí)行所有更新語(yǔ)句,顯然batch性能將更優(yōu);
2.但batch模式也有自己的問題,比如在Insert操作時(shí),在事務(wù)沒有提交之前,是沒有辦法獲取到自增的id,這在某型情形下是不符合業(yè)務(wù)要求的;
3. 在測(cè)試中使用simple模式提交10000條數(shù)據(jù),時(shí)間為18248 毫秒,batch模式為5023 ,性能提高70%;
4.通過走碼和研讀spring相關(guān)文件發(fā)現(xiàn),在同一事務(wù)中batch模式和simple模式之間無(wú)法轉(zhuǎn)換,由于本項(xiàng)目一開始選擇了simple模式,所以碰到需要批量更新時(shí),只能在單獨(dú)的事務(wù)中進(jìn)行;
5.在代碼中使用batch模式可以使用以下方式:
//從spring注入原有的sqlSessionTemplate
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
public void testInsertBatchByTrue() {
//新獲取一個(gè)模式為BATCH,自動(dòng)提交為false的session
//如果自動(dòng)提交設(shè)置為true,將無(wú)法控制提交的條數(shù),改為最后統(tǒng)一提交,可能導(dǎo)致內(nèi)存溢出
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(
ExecutorType.BATCH, false);
//通過新的session獲取mapper
fooMapper = session.getMapper(FooMapper.class);
int size = 10000;
try {
for (int i = 0; i < size; i++) {
Foo foo = new Foo();
foo.setName(String.valueOf(System.currentTimeMillis()));
fooMapper.insert(foo);
if (i % 1000 == 0 || i == size - 1) {
//手動(dòng)每1000個(gè)一提交,提交后無(wú)法回滾
session.commit();
//清理緩存,防止溢出
session.clearCache();
}
}
} catch (Exception e) {
//沒有提交的數(shù)據(jù)可以回滾
session.rollback();
} finally {
session.close();
}
}
6.上述代碼沒有使用spring的事務(wù),改動(dòng)手動(dòng)控制,如果和原spring事務(wù)一起使用,將無(wú)法回滾,必須注意,最好單獨(dú)使用;