先定义一个简单的测试表,执行脚本如下:
create table user(id bigint primary key auto_increment,name varchar(255) not null,age int not null default 0 check (age >= 0)
);
根据Spingboot+mybatisplus的结构根据表自行构建结构,大致如下:
增
Mapper Interface(Mapper层)
insert
// 插入一条记录
int insert(T entity);/*** Mapper层 提供的新增方法 insert() 方法:int insert(T entity)*/public void insert_test(User user) {int insert = userMapper.insert(user);// 受影响行数System.out.println("insert:" + insert);// 获取插入数据的主键 IDLong id = user.getId();System.out.println("id:" + id);}
功能描述: 插入一条记录。
返回值: int,表示插入操作影响的行数,通常为 1,表示插入成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Service Interface(Service层)
save
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);/***Service 层 提供的新增方法 save() 方法:boolean save(T entity)*/public void save_test(User user) {boolean save = this.save(user);//是否保存成功System.out.println("save:" + save);// 返回主键IDLong id = user.getId();System.out.println("主键 ID: " + id);}/*** Service 层 提供的批量新增方法 saveBatch() 方法:boolean saveBatch(Collection<T> entityList)* 伪批量插入,命名虽然包含了批量的意思,但这不是真的批量插入* @param userList*/public void savaBatch_test(List<User> userList) {boolean saveBatch = this.saveBatch(userList);System.out.println("saveBatch:" + saveBatch);}/*** 伪批量插入,int 表示批量提交数,默认为 1000* savaBatch(Collection<T>, int) : boolean* int 表示批量提交数,即多少 SQL 操作执行一次,默认为 1000* @param userList*/public void savaBatch_test2(List<User> userList) {boolean saveBatch = this.saveBatch(userList, 2);System.out.println("saveBatch:" + saveBatch);}
功能描述: 插入记录,根据实体对象的字段进行策略性插入。
返回值: boolean,表示插入操作是否成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Collection<T> | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
注意:savaBatch 伪批量插入,命名虽然包含了批量的意思,但这不是真的批量插入。
批量新增源码分析
这里用到了insert方法,再往executeBatch里看:
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {// 断言需要批处理数据集大小不等于1Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);// 判空数据集,若不为空,则开始执行批量处理return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, (sqlSession) -> {int size = list.size();// 将批处理大小与传入的操作集合大小进行比较,取最小的那个int idxLimit = Math.min(batchSize, size);int i = 1;// 迭代器循环for(Iterator var7 = list.iterator(); var7.hasNext(); ++i) {// 获取当前需要执行的数据库操作E element = var7.next();// 回调 sqlSession.insert() 方法consumer.accept(sqlSession, element);// 判断是否达到需要批处理的阀值if (i == idxLimit) {// 开始批处理,此方法执行并清除缓存在 JDBC 驱动类中的执行语句sqlSession.flushStatements();idxLimit = Math.min(idxLimit + batchSize, size);}}});}
相比较自己手动 for
循环执行插入,Mybatis Plus 这个伪批量插入性能会更好些,内部会将每次的插入语句缓存起来,等到达到 1000 条的时候,才会统一推给数据库,虽然最终在数据库那边还是一条一条的执行 INSERT,但还是在和数据库交互的 IO 上做了优化。
saveOrUpdate(增或改)
// TableId 注解属性值存在则更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
功能描述: 根据实体对象的主键 ID 进行判断,存在则更新记录,否则插入记录。
返回值: boolean,表示插入或更新操作是否成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
Wrapper<T> | updateWrapper | 实体对象封装操作类 UpdateWrapper |
Collection<T> | entityList | 实体对象集合 |
int | batchSize | 插入批次数量 |
例子:
/*** Service 层 提供的新增或更新方法 saveOrUpdate() 方法:boolean saveOrUpdate(T entity)* 保存或者更新。即当你需要执行的数据,数据库中不存在时,就执行插入操作* 如设置了主键 ID,因为主键 ID 必须是唯一的,Mybatis Plus 会先执行查询操作,判断数据是否存在,存在即执行更新,否则,执行插入操作* TableId 注解属性值存在则更新记录,否插入一条记录* @param user*/public void saveOrUpdate_test(User user){boolean saveOrUpdate = this.saveOrUpdate(user);System.out.println("saveOrUpdate:" + saveOrUpdate);}/*** Service 层 提供的新增或更新方法 boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);* updateWrapper 条件构造器* 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法* @param user*/public void saveOrUpdate_test2(User user){LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();wrapper.eq(User::getName, user.getName());boolean saveOrUpdate = this.saveOrUpdate(user, wrapper);System.out.println("saveOrUpdate:" + saveOrUpdate);}/*** Service 层 提供的批量新增或更新方法 saveOrUpdateBatch() 方法:boolean saveOrUpdateBatch(Collection<T> entityList)* @param userList*/public void saveOrUpdateBatch_test(List<User> userList){boolean saveOrUpdateBatch = this.saveOrUpdateBatch(userList);System.out.println("saveOrUpdateBatch:" + saveOrUpdateBatch);}/*** Service 层 提供的批量新增或更新方法 saveOrUpdateBatch() 方法:boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize)* int 表示批量提交数,即多少 SQL 操作执行一次,默认为 1000* @param userList*/public void saveOrUpdateBatch_test2(List<User> userList){boolean saveOrUpdateBatch = this.saveOrUpdateBatch(userList, 3);System.out.println("saveOrUpdateBatch:" + saveOrUpdateBatch);}