mp概括
MyBatis Plus 是 MyBatis 的增强工具,旨在简化开发、提高效率,并提供一系列开箱即用的功能。它不仅继承了 MyBatis 的灵活性和强大功能,还通过添加自动化代码生成、内置 CRUD 操作、分页插件等特性进一步增强了开发者体验。
mybatis-plus
mybatis-x使用
使用mybatis-x插件可以让我们快速的构建与数据表映射的java对象
使用步骤:
- 使用idea database链接数据库

- 鼠标右击显示MybatisX-Generator

- 点击MybatisX-Generator

- 生成代码选择

一般来说使用这些就足够了
Mybatis-plus进行持久化操作
IService
IService 接口中的方法命名遵循了一定的规范,如 get 用于查询单行,remove 用于删除,list 用于查询集合,page 用于分页查询
save
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);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);saveOrUpdate[感觉不太行,执行两条命令,mysql8之后存在该命令]
Student student = Student.builder().id(1).age(18).name("aaa").build();
studentService.saveOrUpdate(student);remove
这个平时用来比较少
// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);update
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);get
这个主要使用getone 和list方法对于数据查询
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);getMap
Student student = Student.builder().id(1).age(18).name("aaa").build();
Map<String, Object> id = studentService.getMap(Wrappers.<Student>query().eq("id", 1));
// 数据返回结果,以map的形式存储比如student中有id,age,name三个字段
{
id:"1",
age:18,
name:"111"
}getObj
Student student = Student.builder().id(1).age(18).name("aaa").build();
QueryWrapper<Student> query =new QueryWrapper<>();
query.eq("id",1);
Integer obj1 = studentService.getObj(query, obj ->(Integer) obj);
System.out.println("obj = " + obj1);这部分与官方文档所说内容并不一致,只是返回第一个字段,或者说是查询字段。
list
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);这部分平时使用会相对多一些
listObjs
Student student = Student.builder().id(1).age(18).name("aaa").build();
QueryWrapper<Student> query =new QueryWrapper<>();
query.ge("id",1);
List<Integer> list = studentService.listObjs(query, x -> ((Integer) x));
System.out.println("list = " + list);还是只能获得第一个字段的数据
page
这部分平时也会经常用到
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);使用一般也就是page
page
QueryWrapper<Student> query =new QueryWrapper<>();
query.ge("id",1);
IPage<Student> page = new Page<>();
IPage<Student> page1 = studentService.page(page, query);
System.out.println("list = " +page1 );pageMaps
QueryWrapper<Student> query =new QueryWrapper<>();
query.ge("id",1);
IPage<Map<String,Object>> page = new Page<>();
IPage<Map<String, Object>> mapIPage = studentService.pageMaps(page, query);
System.out.println("list = " +mapIPage );将原先完整的数据student变成map存储
count
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
//自3.4.3.2开始,返回值修改为long
// 查询总记录数
long count();
// 根据 Wrapper 条件,查询总记录数
long count(Wrapper<T> queryWrapper);Mapper Interface
BaseMapper 是 Mybatis-Plus 提供的一个通用 Mapper 接口,它封装了一系列常用的数据库操作方法,包括增、删、改、查等。通过继承 BaseMapper,开发者可以快速地对数据库进行操作,而无需编写繁琐的 SQL 语句。
insert
// 插入一条记录
int insert(T entity);delete
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);update
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);select
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);selectMaps
QueryWrapper<Student> query =new QueryWrapper<>();
query.ge("id",1);
BaseMapper<Student> baseMapper = studentService.getBaseMapper();
List<Map<String, Object>> maps = baseMapper.selectMaps(query);
System.out.println("list = " +maps );同样是将数据映射成map
chain
Chain 是 Mybatis-Plus 提供的一种链式编程风格,它允许开发者以更加简洁和直观的方式编写数据库操作代码。Chain 分为
query和update两大类,分别用于查询和更新操作。每类又分为普通链式和 lambda 链式两种风格,其中 lambda 链式提供了类型安全的查询条件构造
**query ** && update
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();demo
LambdaQueryChainWrapper<Student> lambdaQueryChainWrapper =
new LambdaQueryChainWrapper<>(studentService.getBaseMapper());
List<Student> list = lambdaQueryChainWrapper.ge(Student::getId, 1).list();
Student one = lambdaQueryChainWrapper.eq(Student::getId, 1).one();目前感觉不是很有用
ActiveRecord
ActiveRecord 模式是一种设计模式,它允许实体类直接与数据库进行交互,实体类既是领域模型又是数据访问对象。在 Mybatis-Plus 中,实体类只需继承
Model类即可获得强大的 CRUD 操作能力。ActiveRecord 是一种对象关系映射(ORM)模式,由 Rails 最早提出,广泛应用于动态语言如 PHP 和 Ruby 中。它遵循标准的 ORM 模型:表映射到记录,记录映射到对象,字段映射到对象属性。ActiveRecord 的主要思想是每一个数据库表对应一个类,类的每一个对象实例对应于数据库中表的一行记录12。
个人见解:就是将数据表完全映射成一个对象
删除

insert

select

update

经典的增删差改
SimpleQuery
SimpleQuery 是 Mybatis-Plus 提供的一个工具类,它对
selectList查询后的结果进行了封装,使其可以通过Stream流的方式进行处理,从而简化了 API 的调用。SimpleQuery 的一个特点是它的
peeks参数,这是一个可变参数,类型为Consumer...,意味着你可以连续添加多个操作,这些操作会在查询结果被处理时依次执行。
QueryWrapper<Student> query =new QueryWrapper<>();
query.ge("id",1);
List<String> names = new ArrayList<>();
SimpleQuery.list(Wrappers.lambdaQuery(Student.class),// 查询条件
Student::getName,// 提取字段
System.out::println,// peek操作
student -> names.add(student.getName())); // peek
System.out.println("names = " + names);keymap
// 假设有一个 User 实体类和对应的 BaseMapper
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, "active"); // 查询状态为 "active" 的用户
// 使用 keyMap 方法查询并封装结果
Map<String, User> userMap = SimpleQuery.keyMap(
queryWrapper, // 查询条件构造器
User::getUsername, // 使用用户名作为键
user -> System.out.println("Processing user: " + user.getUsername()) // 打印处理的用户名
);
// 遍历结果
for (Map.Entry<String, User> entry : userMap.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}map
// 假设有一个 User 实体类和对应的 BaseMapper
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, "active"); // 查询状态为 "active" 的用户
// 使用 map 方法查询并封装结果
Map<String, Integer> userMap = SimpleQuery.map(
queryWrapper, // 查询条件构造器
User::getUsername, // 使用用户名作为键
User::getAge, // 使用年龄作为值
user -> System.out.println("Processing user: " + user.getUsername()) // 打印处理的用户名
);
// 遍历结果
for (Map.Entry<String, Integer> entry : userMap.entrySet()) {
System.out.println("Username: " + entry.getKey() + ", Age: " + entry.getValue());
}group
// 假设有一个 User 实体类和对应的 BaseMapper
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, "active"); // 查询状态为 "active" 的用户
// 使用 group 方法查询并封装结果,按照用户名分组
Map<String, List<User>> userGroup = SimpleQuery.group(
queryWrapper, // 查询条件构造器
User::getUsername, // 使用用户名作为分组键
user -> System.out.println("Processing user: " + user.getUsername()) // 打印处理的用户名
);
// 遍历结果
for (Map.Entry<String, List<User>> entry : userGroup.entrySet()) {
System.out.println("Username: " + entry.getKey());
for (User user : entry.getValue()) {
System.out.println(" - User: " + user);
}
}list
// 假设有一个 User 实体类和对应的 BaseMapper
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, "active"); // 查询状态为 "active" 的用户
// 使用 list 方法查询并封装结果,提取所有用户的用户名
List<String> userNames = SimpleQuery.list(
queryWrapper, // 查询条件构造器
User::getUsername, // 提取用户名作为列表元素
user -> System.out.println("Processing user: " + user.getUsername()) // 打印处理的用户名
);
// 遍历结果
for (String username : userNames) {
System.out.println("Username: " + username);
}Db Kit
Db Kit 是 Mybatis-Plus 提供的一个工具类,它允许开发者通过静态调用的方式执行 CRUD 操作,从而避免了在 Spring 环境下可能出现的 Service 循环注入问题,简化了代码,提升了开发效率。
正如概括所说这是一个工具,可以静态调用crud操作
Student byId = Db.getById(1, Student.class);
System.out.println("byId = " + byId);
Db.update(Student.builder().id(1).name("222").age(18).build(),
Wrappers.<Student>lambdaUpdate().eq(Student::getId,1));条件构造器(wrapper)
mybatis-plus部分构造器关系图

对于平时开发主要使用还是lambdawrapper 和 wrapper
wrapper
alleq
通过使用map构造all eq 条件
适用于:
- LambdaWrapper【LambdaQueryWrapper,LambdaUpdateWrapper】
- Wrapper【QueryWrapper,UpdateWrapper】
// 设置所有字段的相等条件,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(Map<String, Object> params)
allEq(Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, Map<String, Object> params, boolean null2IsNull)
// 设置所有字段的相等条件,通过filter过滤器决定哪些字段应该被包含,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(BiPredicate<String, Object> filter, Map<String, Object> params)
allEq(BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)参数说明
params:一个Map,其中key是数据库字段名,value是对应的字段值。null2IsNull:如果设置为true,当Map中的value为null时,会调用isNull方法;如果设置为false,则会忽略value为null的键值对。filter:一个BiPredicate,用于过滤哪些字段应该被包含在查询条件中。condition:一个布尔值,用于控制是否应用这些条件。
eq
gt、ge、lt、le、ne、between、notbetween、like、likelift、likeright、isNull、in
这些都差不多
设置eq条件
作用范围all
// 设置指定字段的相等条件
eq(R column, Object val)
// 根据条件设置指定字段的相等条件
eq(boolean condition, R column, Object val)sql
inSql、notinSql、eqSql、geSql、leSql
允许使用sql的形式进行查询条件的构造
groupBy
用来进行分组查询的sql
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.select("name", "count(*)"); // 假设'id'是主键列名,你可根据实际情况调整
queryWrapper.groupBy("name");
BaseMapper<Student> mapper = studentService.getBaseMapper();
List<Map<String, Object>> maps = mapper.selectMaps(queryWrapper);SELECT name, max(age) as ages FROM
studentGROUP BYname
// 设置 HAVING 子句,使用 SQL 语句和参数
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)order
用来进行数据排序
// 设置升序排序条件,使用字段名
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
// 设置降序排序条件,使用字段名
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
// 设置排序条件,使用字段名和排序方向
orderBy(boolean condition, boolean isAsc, R... columns)func
func方法是 MyBatis-Plus 中用于构建查询条件的高级方法之一,它提供了一种在链式调用中根据条件执行不同查询操作的机制。通过传入一个Consumer函数式接口,func方法允许你在不中断链式调用的情况下,根据条件执行不同的查询构建逻辑。
使用范围同上
这个还是挺有意思的
Student build = Student.builder().age(25).build();
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.func(i -> {
if (build.getAge()>25){
i.ge("age",25);
}else {
i.le("age",25);
}
});
List<Student> list = this.studentService.list(queryWrapper);or and
这个用的比较多,使用起来也比较简单。
nested
允许你在wrapper构造一个独立的查询条件
apply
apply 方法是 MyBatis-Plus 中用于构建查询条件的高级方法之一,它允许你直接拼接 SQL 片段到查询条件中。这个方法特别适用于需要使用数据库函数或其他复杂 SQL 构造的场景。
exists
exists方法是 MyBatis-Plus 中用于构建查询条件的高级方法之一,它用于在查询中添加一个 EXISTS 子查询。通过调用exists方法,可以将一个完整的 SQL 子查询作为 EXISTS 条件添加到主查询中。
普通 Wrapper (QueryWrapper):
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.exists("select id from table where age = 1");Lambda Wrapper (LambdaQueryWrapper):
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.exists("select id from table where age = 1");生成的 SQL
-- 普通 Wrapper 和 Lambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE EXISTS (select id from table where age = 1)select
select方法是 MyBatis-Plus 中用于构建查询条件的高级方法之一,它用于设置查询的字段。通过调用select方法,可以指定在查询结果中包含哪些字段,从而实现字段级别的查询定制。
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age","18");
queryWrapper.select("id,name");
List<Student> list = this.studentService.list(queryWrapper);Wrappers
MyBatis-Plus 提供了 Wrappers 类,它是一个静态工厂类,用于快速创建 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 的实例。使用 Wrappers 可以减少代码量,提高开发效率。
流式查询
MyBatis-Plus 从 3.5.4 版本开始支持流式查询,这是 MyBatis 的原生功能,通过 ResultHandler 接口实现结果集的流式查询。这种查询方式适用于数据跑批或处理大数据的业务场景。
在 BaseMapper 中,新增了多个重载方法,包括 selectList, selectByMap, selectBatchIds, selectMaps, selectObjs,这些方法可以与流式查询结合使用。
Page<Student> page = new Page<>(1, 1000);
BaseMapper<Student> baseMapper = this.studentService.getBaseMapper();
AtomicInteger count = new AtomicInteger(0);
baseMapper.selectList(page, Wrappers.emptyWrapper(), new ResultHandler<Student>() {
@Override
public void handleResult(ResultContext<? extends Student> resultContext) {
Student resultObject = resultContext.getResultObject();
if (resultObject.getAge()>18){
count.incrementAndGet();
}
}
});自动填充字段数据
MyBatis-Plus 提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。以下是如何使用这一功能的详细说明。
demo
entity
@TableName(value ="t_user")
@Data
@Builder
@RequiredArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
private String nickName;
/**
* 用户名
*/
@TableField(select = false)
private String username;
/**
* 用户密码
*/
private String password;
/**
* 用户描述
*/
private String description;
/**
* 用户创建时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date createTime;
/**
* 用户修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
/**
* 用户删除标识,0:正常,1:已删除
*/
@TableField(fill = FieldFill.INSERT)
private Integer delFlag;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}config
/**
* @author lss
* @description mybatis plus 配置
* @createDate 2024/12/6-11:33
*/
@Configuration
public class MPConfig {
/**
* MyBatis-Plus MySQL 分页插件
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
/**
* MyBatis-Plus 源数据自动填充类
*/
@Bean
@Primary
public MyMetaObjectHandler myMetaObjectHandler() {
return new MyMetaObjectHandler();
}
/**
* MyBatis-Plus 源数据自动填充类
* todo 自己傻逼了,这个使用需要添加注解,下次请先看文档
*/
static class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
strictInsertFill(metaObject, "createTime", Date::new, Date.class);
strictInsertFill(metaObject, "updateTime", Date::new, Date.class);
strictInsertFill(metaObject, "delFlag", () -> 0, Integer.class);
}
@Override
public void updateFill(MetaObject metaObject) {
strictInsertFill(metaObject, "updateTime", Date::new, Date.class);
}
}
}主键生成策率
概述
主键生成策略必须使用 INPUT 类型,这意味着主键值需要由用户在插入数据时提供。MyBatis-Plus 支持在父类中定义 @KeySequence 注解,子类可以继承使用。
从版本 3.3.0 开始,MyBatis-Plus 会自动识别主键类型,因此不再需要手动指定主键类型。
MyBatis-Plus 内置支持多种数据库的主键生成策略,包括:
- DB2KeyGenerator
- H2KeyGenerator
- KingbaseKeyGenerator
- OracleKeyGenerator
- PostgreKeyGenerator
如果内置的主键生成策略不能满足需求,可以通过实现 IKeyGenerator 接口来扩展自定义的主键生成策略。
springboot配置
@Bean
public IKeyGenerator keyGenerator() {
return new H2KeyGenerator();
}
// 这个可以进行自定义处理
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return plusProperties -> plusProperties.getGlobalConfig().getDbConfig().setKeyGenerator(new H2KeyGenerator());
}SQL注入器
MyBatis-Plus 提供了灵活的机制来注入自定义的 SQL 方法,这通过 sqlInjector 全局配置实现。通过实现 ISqlInjector 接口或继承 AbstractSqlInjector 抽象类,你可以注入自定义的通用方法到 MyBatis 容器中。
- 可以添加自定义的sql语句
- 可以扩展basemapper
使用步骤
sqlInjector配置
public interface ISqlInjector {
/**
* 检查SQL是否已经注入(已经注入过不再注入)
*
* @param builderAssistant mapper 构建助手
* @param mapperClass mapper 接口的 class 对象
*/
void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
}步骤 1: 定义SQL
首先,你需要定义自定义方法的SQL语句。这通常在继承了AbstractMethod的类中完成,例如MysqlInsertAllBatch。
对于这部分本质上就是‘mybatis’的sql语句
public class MysqlInsertAllBatch extends AbstractMethod {
protected MysqlInsertAllBatch(String methodName) {
super(methodName);
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
// 动态构建SQL语句
String sql = "INSERT INTO " + tableInfo.getTableName() + "(" + StringUtils.join(tableInfo.getFieldList(), ",") + ") VALUES " +
"(#{list[0].id}, #{list[0].name}, #{list[0].age}), " +
"(#{list[1].id}, #{list[1].name}, #{list[1].age})";
// 创建 SqlSource 对象
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
// 注册自定义的批量插入方法到Mapper中
return this.addInsertMappedStatement(mapperClass, modelClass, "mysqlInsertAllBatch", sqlSource, new NoKeyGenerator(), null, null);
}
}todo::好像不支持动态sql语句
步骤 2: 注册自定义方法
接下来,你需要创建一个类来继承DefaultSqlInjector,并重写getMethodList方法来注册你的自定义方法。
对定义的method进行注册
public class MyLogicSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(configuration, mapperClass, tableInfo);
methodList.add(new MysqlInsertAllBatch("mysqlInsertAllBatch"));
return methodList;
}
}步骤 3: 定义BaseMapper
然后,你需要在你的BaseMapper接口中定义自定义的方法。
public interface MyBaseMapper<T> extends BaseMapper<T> {
int mysqlInsertAllBatch(@Param("list") List<T> batchList);
}步骤 4: 配置SqlInjector
最后,你需要在配置文件中指定你的自定义SQL注入器。
这个地方从原来的yaml配置改为了spring配置
@Configuration
public class SqlInjectorConfig {
@Bean
public DefaultSqlInjector addSqlInjector(){
return new MyLogicSqlInjector();
}
}