MyBatis的五種批量插入詳解
MyBatis
MyBatis是一款半自動(dòng)的ORM持久層框架,具有較高的SQL靈活性,支持高級(jí)映射(一對(duì)一,一對(duì)多),動(dòng)態(tài)SQL,延遲加載和緩存等特性,但它的數(shù)據(jù)庫(kù)無(wú)關(guān)性較低
用mybatis進(jìn)行開(kāi)發(fā),需要手動(dòng)編寫(xiě)SQL語(yǔ)句。而全自動(dòng)的ORM框架,如hibernate,則不需要編寫(xiě)SQL語(yǔ)句。
用hibernate開(kāi)發(fā),只需要定義好ORM映射關(guān)系,就可以直接進(jìn)行CRUD操作了。
由于mybatis需要手寫(xiě)SQL語(yǔ)句,所以它有較高的靈活性,可以根據(jù)需要,自由地對(duì)SQL進(jìn)行定制,也因?yàn)橐謱?xiě)SQL,當(dāng)要切換數(shù)據(jù)庫(kù)時(shí),SQL語(yǔ)句可能就要重寫(xiě),因?yàn)椴煌臄?shù)據(jù)庫(kù)有不同的方言(Dialect),所以mybatis的數(shù)據(jù)庫(kù)無(wú)關(guān)性低。
一.直接循環(huán)插入
@RestController @RequestMapping("/mybatis3/user") @RequiredArgsConstructor public class UserController { private final IUserService iUserService; @GetMapping("/one") public Long one(){ return iUserService.add(); } } Long add(); @Service @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { private final UserMapper userMapper; @Override public Long add() { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { User user = new User(); user.setUsername("name"+i); user.setPassword("password"+i); userMapper.insertUsers(user); } long end = System.currentTimeMillis(); System.out.println("耗時(shí):"+( end - start ) + "ms"); return (end-start); } } Integer insertUsers(User user); <insert id="insertUsers" > insert into user(username,password) values (#{username}, #{password}) </insert>
最終耗時(shí):14s多
二.關(guān)閉MySql自動(dòng)提交,手動(dòng)進(jìn)行循環(huán)插入提交
@RestController @RequestMapping("/mybatis3/user") @RequiredArgsConstructor public class UserController { private final IUserService iUserService; @GetMapping("/one") public Long one(){ return iUserService.add(); } } Long add2(); @Service @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { private final UserMapper userMapper; // 手動(dòng)開(kāi)啟sql的批量提交 private final SqlSessionTemplate sqlSessionTemplate; @Override public Long add2(){ //關(guān)閉自動(dòng)提交 SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); UserMapper mapper = sqlSession.getMapper(UserMapper.class); long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { User user = new User(); user.setUsername("name"+i); user.setPassword("password"+i); mapper.insertUsers(user); } //自動(dòng)提交SQL sqlSession.commit(); long end = System.currentTimeMillis(); System.out.println("耗時(shí):"+( end - start ) + "ms"); return (end-start); } }
平均:0.12s
第三種:用List集合的方式插入數(shù)據(jù)庫(kù)(推薦)
@RestController @RequestMapping("/mybatis3/user") @RequiredArgsConstructor public class UserController { private final IUserService iUserService; @GetMapping("/one3") public Long one3(){ return iUserService.add3(); } } Long add3(); @Service @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { private final UserMapper userMapper; @Override public Long add3(){ long start = System.currentTimeMillis(); List<User> userList = new ArrayList<>(); User user; for (int i = 0; i < 10000; i++) { user = new User(); user.setUsername("name"+i); user.setPassword("password"+i); userList.add(user); } userMapper.insertUsersThree(userList); long end = System.currentTimeMillis(); System.out.println("耗時(shí):"+( end - start ) + "ms"); return (end-start); } } Integer insertUsersThree(List<User> userList); <insert id="insertUsersThree"> insert into user(username,password) values <foreach collection="userList" item="user" separator=","> (#{user.username},#{user.password}) </foreach> </insert>
第四種: MyBatis-Plus提供的SaveBatch方法
@RestController @RequestMapping("/mybatis3/user") @RequiredArgsConstructor public class UserController { private final IUserService iUserService; @GetMapping("/one4") public Long one4(){ return iUserService.add4(); } } Long add4(); @Service @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { private final UserMapper userMapper; @Override public Long add4() { long start = System.currentTimeMillis(); List<User> userList= new ArrayList<>(); User user ; for (int i = 0; i < 10000; i++) { user = new User(); user.setUsername("name"+i); user.setPassword("password"+i); userList.add(user); } saveBatch(userList); long end = System.currentTimeMillis(); System.out.println("耗時(shí):"+( end - start ) + "ms"); return (end-start); } }
直接報(bào)錯(cuò):
看報(bào)錯(cuò)信息:
長(zhǎng)串:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: com.huang.mybatis3.mapper.UserMapper.insert (batch index #1) failed. Cause: java.sql.BatchUpdateException: Data truncation: Out of range value for column ‘id’ at row 1 ; Data truncation: Out of range value for column ‘id’ at row 1; nested exception is java.sql.BatchUpdateException: Data truncation: Out of range value for column ‘id’ at row 1] with root cause
短串:Data truncation: Out of range value for column ‘id’ at row 1
翻譯一下:
可以發(fā)現(xiàn)就是我們的id超出范圍:
int類型改為bigint即可
故此我們可以得出一個(gè)結(jié)論:設(shè)置數(shù)據(jù)庫(kù)id的時(shí)候設(shè)置為bigint還是蠻好的哈
平均時(shí)間:0.2s
第五種 MyBatis-Plus提供的InsertBatchSomeColumn方法(推薦)
InsertBatchSomeColumn方法了解
這個(gè)類的注解就寫(xiě)的很明白
擴(kuò)展這個(gè)InsertBatchSomeColumn方法
@Slf4j public class EasySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) { // 注意:此SQL注入器繼承了DefaultSqlInjector(默認(rèn)注入器),調(diào)用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自帶方法 List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo); methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE)); log.info("擴(kuò)展的getMethodList方法被框架調(diào)用了"); return methodList; } }
擴(kuò)展的方法注入bean容器
/** * @author Stone * @date 2023/1/3 * @apiNote */ @Configuration public class MybatisPlusConfig { @Bean public EasySqlInjector sqlInjector(){ return new EasySqlInjector(); } }
創(chuàng)建一個(gè)Mapper去實(shí)現(xiàn)我們的擴(kuò)展的飛方法
public interface EasySqlInjectMapper<T> extends BaseMapper<T> { /** * 批量插入 僅適用于mysql * * @param entityList 實(shí)體列表 * @return 影響行數(shù) */ Integer insertBatchSomeColumn(Collection<T> entityList); }
業(yè)務(wù)層
@Override public Long add5() { long start = System.currentTimeMillis(); List<User> userList= new ArrayList<>(); User user ; for (int i = 0; i < 10000; i++) { user = new User(); user.setUsername("name"+i); user.setPassword("password"+i); userList.add(user); } userMapper.insertBatchSomeColumn(userList); long end = System.currentTimeMillis(); System.out.println("耗時(shí):"+( end - start ) + "ms"); return (end-start); }
耗時(shí): 0.2 s
到此這篇關(guān)于MyBatis的五種批量插入詳解的文章就介紹到這了,更多相關(guān)MyBatis的批量插入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
仿京東平臺(tái)框架開(kāi)發(fā)開(kāi)放平臺(tái)(包含需求,服務(wù)端代碼,SDK代碼)
現(xiàn)在開(kāi)放平臺(tái)越來(lái)越多了,下面針對(duì)仿京東開(kāi)放平臺(tái)框架,封裝自己的開(kāi)放平臺(tái),分享給大家。先感謝一下京東開(kāi)放平臺(tái)的技術(shù)大佬們,下面從開(kāi)放平臺(tái)需求,服務(wù)端代碼,SDK代碼三大塊進(jìn)行分享2021-06-06Java中byte[]、String、Hex字符串等轉(zhuǎn)換的方法
這篇文章主要介紹了Java中byte[]、String、Hex字符串等轉(zhuǎn)換的方法,代碼很簡(jiǎn)單,需要的朋友可以參考下2018-05-05SpringBoot中實(shí)現(xiàn)@Scheduled動(dòng)態(tài)定時(shí)任務(wù)
SpringBoot中的@Scheduled注解為定時(shí)任務(wù)提供了一種很簡(jiǎn)單的實(shí)現(xiàn),本文主要介紹了SpringBoot中實(shí)現(xiàn)@Scheduled動(dòng)態(tài)定時(shí)任務(wù),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式)
這篇文章主要介紹了基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11