MyBatis的五種批量插入詳解
MyBatis
MyBatis是一款半自動的ORM持久層框架,具有較高的SQL靈活性,支持高級映射(一對一,一對多),動態(tài)SQL,延遲加載和緩存等特性,但它的數(shù)據(jù)庫無關(guān)性較低
用mybatis進行開發(fā),需要手動編寫SQL語句。而全自動的ORM框架,如hibernate,則不需要編寫SQL語句。
用hibernate開發(fā),只需要定義好ORM映射關(guān)系,就可以直接進行CRUD操作了。
由于mybatis需要手寫SQL語句,所以它有較高的靈活性,可以根據(jù)需要,自由地對SQL進行定制,也因為要手寫SQL,當(dāng)要切換數(shù)據(jù)庫時,SQL語句可能就要重寫,因為不同的數(shù)據(jù)庫有不同的方言(Dialect),所以mybatis的數(shù)據(jù)庫無關(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("耗時:"+( end - start ) + "ms"); return (end-start); } } Integer insertUsers(User user); <insert id="insertUsers" > insert into user(username,password) values (#{username}, #{password}) </insert>
最終耗時:14s多
二.關(guān)閉MySql自動提交,手動進行循環(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; // 手動開啟sql的批量提交 private final SqlSessionTemplate sqlSessionTemplate; @Override public Long add2(){ //關(guān)閉自動提交 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); } //自動提交SQL sqlSession.commit(); long end = System.currentTimeMillis(); System.out.println("耗時:"+( end - start ) + "ms"); return (end-start); } }
平均:0.12s
第三種:用List集合的方式插入數(shù)據(jù)庫(推薦)
@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("耗時:"+( 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("耗時:"+( end - start ) + "ms"); return (end-start); } }
直接報錯:
看報錯信息:
長串: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即可
故此我們可以得出一個結(jié)論:設(shè)置數(shù)據(jù)庫id的時候設(shè)置為bigint還是蠻好的哈
平均時間:0.2s
第五種 MyBatis-Plus提供的InsertBatchSomeColumn方法(推薦)
InsertBatchSomeColumn方法了解
這個類的注解就寫的很明白
擴展這個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("擴展的getMethodList方法被框架調(diào)用了"); return methodList; } }
擴展的方法注入bean容器
/** * @author Stone * @date 2023/1/3 * @apiNote */ @Configuration public class MybatisPlusConfig { @Bean public EasySqlInjector sqlInjector(){ return new EasySqlInjector(); } }
創(chuàng)建一個Mapper去實現(xiàn)我們的擴展的飛方法
public interface EasySqlInjectMapper<T> extends BaseMapper<T> { /** * 批量插入 僅適用于mysql * * @param entityList 實體列表 * @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("耗時:"+( end - start ) + "ms"); return (end-start); }
耗時: 0.2 s
到此這篇關(guān)于MyBatis的五種批量插入詳解的文章就介紹到這了,更多相關(guān)MyBatis的批量插入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
仿京東平臺框架開發(fā)開放平臺(包含需求,服務(wù)端代碼,SDK代碼)
現(xiàn)在開放平臺越來越多了,下面針對仿京東開放平臺框架,封裝自己的開放平臺,分享給大家。先感謝一下京東開放平臺的技術(shù)大佬們,下面從開放平臺需求,服務(wù)端代碼,SDK代碼三大塊進行分享2021-06-06Java中byte[]、String、Hex字符串等轉(zhuǎn)換的方法
這篇文章主要介紹了Java中byte[]、String、Hex字符串等轉(zhuǎn)換的方法,代碼很簡單,需要的朋友可以參考下2018-05-05SpringBoot中實現(xiàn)@Scheduled動態(tài)定時任務(wù)
SpringBoot中的@Scheduled注解為定時任務(wù)提供了一種很簡單的實現(xiàn),本文主要介紹了SpringBoot中實現(xiàn)@Scheduled動態(tài)定時任務(wù),具有一定的參考價值,感興趣的可以了解一下2024-01-01基于Mybatis實現(xiàn)CRUD操作過程解析(xml方式)
這篇文章主要介紹了基于Mybatis實現(xiàn)CRUD操作過程解析(xml方式),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-11-11