MyBatis-Plus为简化开发而生的高效数据库操作工具

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。有意愿的可以去官方文档学习。

目录

MyBatis-Plus AutoGenerator自动生成代码
MyBatis-Plus CRUD接口
MyBatis-Plus AbstractWrapper条件构造器
MyBatis-Plus 分页插件
MyBatis-Plus Sequence主键
MyBatis-Plus 自定义ID生成器
MyBatis-Plus 逻辑删除
MyBatis-Plus 通用枚举

一、AutoGenerator

AutoGenerator代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

1.准备数据

CREATE TABLE `user` (
  `id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'id\r\n身份标识号',
  `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `gender` varchar(6) DEFAULT NULL COMMENT '性别',
  `age` varchar(3) DEFAULT NULL COMMENT '年龄',
  `email` varchar(25) DEFAULT NULL COMMENT '邮箱',
  `address` varchar(255) DEFAULT NULL COMMENT '住址',
  `nick_name` varchar(50) DEFAULT NULL COMMENT '昵称',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `account` varchar(50) DEFAULT NULL COMMENT '账号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

2.依赖

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖

        <!-- mybatisplus自动生成orm代码三件套 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <!--Freemarker模板引擎-->
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>

<!--MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl三种模板,但springboot1.4版本以上不再支持velocity-->
<!--        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.1</version>
        </dependency>-->
<!--        <dependency>
            <groupId>com.ibeetl</groupId>
            <artifactId>beetl-framework-starter</artifactId>
            <version>1.2.10.RELEASE</version>
        </dependency>-->

3.配置和执行AutoGenerator 代码生成器

@Slf4j
public class MysqlGenerator {
    public static void main(String[] args) {
        //全局策略配置
        GlobalConfig config = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        config.setActiveRecord(true)
                //作者注释
                .setAuthor("LeeJack")
                //输出路径
                .setOutputDir(projectPath + "/mybatis-plus-autogenerator/src/main/java")
                //覆盖已有文件,默认false
                .setFileOverride(true)
                //是否打开输出目录窗口。默认true
                .setOpen(false)
                //是否在xml中添加二级缓存配置。默认false
                //.setEnableCache(true)
                //开启kotlin模式,默认false
                //.setKotlin(false)
                //开启swagger2模式
                .setSwagger2(true)
                //开启ActiveRecord模式
                .setActiveRecord(true)
                //mapper添加restMap
                .setBaseResultMap(true)
                //mapper添加Base_Column_List
                .setBaseColumnList(true)
                //时间类型对应策略,默认time_pack
                //.setDateType(DateType.TIME_PACK)
                .setMapperName("%sDao")
                .setServiceName("%sService")
                .setServiceImplName("%sServiceImpl");
                //.setIdType(IdType.ASSIGN_ID)


        //数据源配置
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL)
                .setDriverName("com.mysql.cj.jdbc.Driver")
                .setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai")
                .setUsername("root")
                .setPassword("root");
        //数据库信息查询类,默认由dbType类型决定,实现IDbQuery接口可自定义数据库查询sql
        //.setDbQuery()
        //不知道干嘛的,官网写的是public,我改成其他都没有发现变化
        //.setSchemaName("private")
        //内置转换类型,默认由dbType类型决定。可实现或重写实现了 IColumnType 接口的类,自定义转换为自己需要的 java 类型
        //.setTypeConvert(new MySqlTypeConvert())

        //数据库表配置,通过该配置,可指定需要生成哪些表或者排除哪些表
        StrategyConfig strategyConfig = new StrategyConfig();
        //是否大写命名
        strategyConfig.setCapitalMode(true)
                //是否跳过视图
                .setSkipView(true)
                //数据库表映射到实体的命名策略
                .setNaming(NamingStrategy.underline_to_camel)
                //数据库表字段映射到实体的命名策略,未指定按照naming执行
                //.setColumnNaming(NamingStrategy.no_change)
                //生成表
                .setInclude("operate_log", "user")
                .setEntityBuilderModel(true)
                .setEntityLombokModel(true)
                .setRestControllerStyle(true)
                .setEntityTableFieldAnnotationEnable(true);

        //包名配置
        PackageConfig packageConfig = new PackageConfig();
        //父包名
        packageConfig.setParent("com.ljj")
                .setMapper("dao")
                .setService("service")
                .setController("controller")
                .setEntity("entity")
                .setXml("mapper");

        //自定义模板配置
        //TemplateConfig templateConfig = new TemplateConfig();
        //templateConfig.setEntity("/templates/entity.java");

        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(config)
                .setStrategy(strategyConfig)
                .setDataSource(dataSourceConfig)
                .setTemplateEngine(new FreemarkerTemplateEngine())
                .setPackageInfo(packageConfig);

        autoGenerator.execute();
        log.info("=============代码生成成功================");
    }
}

二、CRUD接口

引入mybatis-plus(MP)依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>
                <!-- mybatis-plus现在最新版 -->
        <!--        <dependency>
                    <groupId>com.baomidou</groupId>
                    <artifactId>mybatis-plus</artifactId>
                    <version>3.3.0</version>
                </dependency>-->
<!-- mybatisplus-mysql-druid 数据持久化三件套 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

配置

application.yml


spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.druid.username=root
spring.datasource.druid.password=root
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver

logging.level.com.ljj.dao=debug

在springboot启动类添加@MapperScan

@MapperScan("com.ljj.dao")

entity

@Data
@ToString
@Builder
public class User {
    private String id;
    private String realName;
    private String gender;
    private String age;
    private String email;
    private String address;
    private String nickName;
    private String account;
    private String password;
}

使用

MP提供了2种封装完成了的CRUD接口供我们直接调用

1.Mapper CRUD接口

@Component
public interface UserDao extends BaseMapper<User> {
}

这就是mybatis-plus的重点,User是泛型。BaseMapper里面封装里一些数据库操作的常用方法。

public interface BaseMapper<T> extends Mapper<T> {
    int insert(T entity);

    int deleteById(Serializable id);

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

    int delete(@Param("ew") Wrapper<T> wrapper);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    int updateById(@Param("et") T entity);

    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

    T selectById(Serializable id);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

    T selectOne(@Param("ew") Wrapper<T> queryWrapper);

    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}

直接注入使用即可

 
    @Autowired
    private UserDao userDao;

测试

1.int insert(T entity);


int row = userDao.insert(User.builder().account("545430111").address("广东省xx市xx区" + count).age("21").email("[email protected]").nickName("空想").password("{OP:JHYGGTYUUKOK").realName("妲己").gender(UserSex.MAN.getCode()).build());
        
log.info("插入用户数据成功------------->返回row:{}", count);

当然为了测试需要有更多的数据

		int count = 0;
        for (int i = 0; i < 10; i++) {
            count += userDao.insert(User.builder().account("545430111").address("广东省xx市xx区" + count).age("21").email(
                    "[email protected]").nickName("空想" + count).password("{OP:JHYGGTYUUKOK").realName("妲己" +count).gender(UserSex.MAN.getCode()).build());
        }
        log.info("插入用户数据成功------------->返回row:{}", count);

2.int deleteById(Serializable id);

int row = userDao.deleteById("1215901606834593794");
log.info("删除用户数据成功------------->返回row:{}", count);

3.int deleteByMap(@Param(“cm”) Map<String, Object> columnMap);

Map<String, Object> map = new HashMap<String, Object>();
map.put("nick_name", "空想2");
int row = userDao.deleteByMap(map);
log.info("删除用户数据成功------------->返回row:{}", count);

4.int delete(@Param(“ew”) Wrapper wrapper);

int row = userDao.delete(new QueryWrapper<User>().eq("real_name","甄姬"));
log.info("删除用户数据成功------------->返回row:{}", count);

5.int deleteBatchIds(@Param(“coll”) Collection<? extends Serializable> idList);

List<String> list = new ArrayList<>();
list.add("1215902267827527682");
list.add("1215902272369958914");
int row = userDao.deleteBatchIds(list);

6.int updateById(@Param(“et”) T entity);

int count = userDao.updateById(User.builder().realName("甄姬").id("1215900383502876673").build());
log.info("更新用户数据成功------------->返回row:{}", count);

7.int update(@Param(“et”) T entity, @Param(“ew”) Wrapper updateWrapper);

int row = userDao.update(User.builder().realName("王昭君").build(), new QueryWrapper<User>().gt("id","1215900383502876673"));
log.info("更新用户数据成功------------->返回row:{}", count);

8.T selectById(Serializable id);

User user = userDao.selectById("1215900383502876673");
log.info("获取id为1215900383502876673的账号信息:{}",user.toString());

9.List selectBatchIds(@Param(“coll”) Collection<? extends Serializable> idList);

List<String> idlist = new ArrayList<>();
        idlist.add("1215900383502876673");
        idlist.add("1215901606834593794");
        idlist.add("1215902267827527682");
        idlist.add("1215902272369958914");
        idlist.add("1215902272395124737");
        idlist.add("1215902272407707650");
        idlist.add("1215902272424484866");
        List<User> userList = userDao.selectBatchIds(idlist);
        for (User user : userList) {
            log.info("获取id为{}的账号信息:{}", user.getId(), user.toString());
        }

10.List selectByMap(@Param(“cm”) Map<String, Object> columnMap);

 Map<String, Object> colum = new HashMap<>();
        colum.put("real_name","妲己");
        colum.put("id","1215902272508370946");
        List<User> userList = userDao.selectByMap(colum);
        for (User user : userList) {
            log.info("获取id为{}的账号信息:{}", user.getId(), user.toString());
        }

11.T selectOne(@Param(“ew”) Wrapper queryWrapper);

User user = userDao.selectOne(new QueryWrapper<User>().eq("id", "1215900383502876673"));
log.info("获取id为{}的账号信息:{}", user.getId(), user.toString());

12.Integer selectCount(@Param(“ew”) Wrapper queryWrapper);

Integer count = userDao.selectCount(new QueryWrapper<User>().gt("id", "1215900383502876673"));
log.info("统计用户数据成功------------->返回row:{}", count);

13.List selectList(@Param(“ew”) Wrapper queryWrapper);

List<User> userList = userDao.selectList(new QueryWrapper<User>().gt("id", "1215900383502876673"));
for (User user : userList) {
    log.info("获取id为{}的账号信息:{}", user.getId(), user.toString());
}

14.List<Map<String, Object>> selectMaps(@Param(“ew”) Wrapper queryWrapper);

List<Map<String, Object>> maps = userDao.selectMaps(new QueryWrapper<User>().gt("id", "1215900383502876673"));

for (Map<String, Object> map : maps) {
    log.info("获取id为{}的账号信息:{}", map.get("id"), map.toString());
}

15.List selectObjs(@Param(“ew”) Wrapper queryWrapper);

//只会返回第一个字段的值,无法转User类
List<Object> selectObjs = userDao.selectObjs(new QueryWrapper<User>().gt("id", "1215900383502876673"));

for (Object obj : selectObjs) {
    log.info("获取的账号的id信息:{}", obj.toString());
}

16.<E extends IPage> E selectPage(E page, @Param(“ew”) Wrapper queryWrapper);

IPage<User> userIPage = new Page<>(1, 3);
IPage<User> pageList = userDao.selectPage(userIPage, new QueryWrapper<User>().gt("id","1215900383502876673"));
for (User record : pageList.getRecords()) {
    log.info("获取id为{}的账号信息:{}",record.getId(),record.toString());
}

17.<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(“ew”) Wrapper queryWrapper);

IPage<Map<String, Object>> userIPage = new Page<>(1, 3);

IPage<Map<String, Object>> pageList = userDao.selectMapsPage(userIPage, new QueryWrapper<User>().gt("id","1215900383502876673"));

for (Map<String, Object> map : pageList.getRecords()) {
    log.info("获取id为{}的账号信息:{}", map.get("id"), map.toString());
}

2.Service CRUD 接口

public interface UserService extends IService<User> {

}
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

}

使用方法同basemapper

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);

Remove

// 根据 entity 条件,删除记录
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);
// 根据 whereEntity 条件,更新记录
boolean update(T entity, Wrapper<T> updateWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

Get

// 根据 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);

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);

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);

Count

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

Chain

#query
// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery(); 

// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
#update
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin 
LambdaUpdateChainWrapper<T> lambdaUpdate();

// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);

三、AbstractWrapper

条件构造器AbstractWrapper是QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

List<User> users = userDao.selectList(new QueryWrapper<User>().eq("real_name","王昭君"));
        
log.info("----------user:{}", users);

AbstractWrapper下的方法及使用

方法名 说明 使用
allEq(Map<R, V> params) 全部=(或个别isNull) allEq(params,true)
eq = eq(“real_name”,“王昭君”)
ne <> ne(“nick_name”,“空想4”)
gt > gt(“age”,21)
ge >= ge(“age”,22)
lt < lt(“age”,22)
le <= le(“age”,21")
between cloum between ? and ? between(“age”,0,21)
notBetween cloum between ? and ? notBetween(“age”,0,21)
like cloum like ‘%王%’ like(“real_name”,“王”)
notLike not like ‘%王%’ notLike(“real_name”,“王”)
likeLeft like ‘%王’ likeLeft(“real_name”,“昭”)
likeRight like ‘王%’ likeRight(“real_name”,“昭”)
isNull is null isNull(“gender”)
isNotNull is not null isNotNull(“gender”)
in in (1,2,3) in(“nick_name”,lists)
notIn age not in (1,2,3) notIn(“nick_name”,lists)
inSql age in (1,2,3,4,5,6) inSql(“nick_name”,"‘空想4’,‘空想5’,‘空想6’")
notInSql age not in (1,2,3,4,5,6) notInSql(“nick_name”,"‘空想4’,‘空想5’,‘空想6’")
groupBy group by id,name groupBy(“nick_name”,“age”)
orderByAsc order by id ASC,name ASC orderByAsc(“nick_name”,“age”)
orderByDesc order by id DESC,name DESC orderByDesc(“age”)
orderBy order by id ASC,name ASC orderBy(true,true,“age”)
having having sum(age) > 10 having(“sum(age) > 10”)
or id = 1 or name = ‘老王’ eq(“nick_name”,“空想4”).or(i->i.eq(“age”,21) eq(“nick_name”,“空想4”).or().eq(“nick_name”,“空想5”)
and and (name = ‘李白’ and status <> ‘活着’) and(i->i.eq(“age”,21))
nested (name = ‘李白’ and status <> ‘活着’) nested(i->i.eq(“age”,21).eq(“nick_name”,“空想4”))
apply id = 1 apply(“nick_name = ‘空想4’”)
last 最后添加多个以最后的为准,有sql注入风险 last(“limit 1”)
exists 拼接 EXISTS ( sql语句 ) exists(“select id from table where age = 1”)
notExists 拼接 NOT EXISTS ( sql语句 ) notExists(“select id from table where age = 1”)

QueryWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取

方法名 说明 使用
select select(i -> i.getProperty().startsWith(“test”)) select(“id”, “name”, “age”)

UpdateWrapper

继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!

方法名 说明 使用
set set(“name”, “老李头”) set(“name”, “”)
setSql setSql(“name = ‘老李头’”) setSql(String sql)

自定义SQL使用Wrapper

方案一 注解方式 Mapper.java

@Select("select * from mysql_data ${ew.customSqlSegment}")
List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);

方案二 XML形式 Mapper.xml

<select id="getAll" resultType="MysqlData">
	SELECT * FROM mysql_data ${ew.customSqlSegment}
</select>

四、分页插件

分页配置

1.spring xml方式

<!-- spring xml 方式 -->
<property name="plugins">
    <array>
        <bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
            <property name="sqlParser" ref="自定义解析类、可以没有"/>
            <property name="dialectClazz" value="自定义方言类、可以没有"/>
            <!-- COUNT SQL 解析.可以没有 -->
            <property name="countSqlParser" ref="countSqlParser"/>
        </bean>
    </array>
</property>

<bean id="countSqlParser" class="com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize">
    <!-- 设置为 true 可以优化部分 left join 的sql -->
    <property name="optimizeJoin" value="true"/>
</bean>

2.spring boot方式

@EnableTransactionManagement
@Configuration
@MapperScan("com.ljj.dao")
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor interceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        interceptor.setLimit(5);
        // 开启 count 的 join 优化,只针对部分 left join
        interceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return interceptor;
    }
}

xml自定义分页

UserDao .java

@Component
public interface UserDao {
    IPage<User> selectPageVo(Page<?> page,String realName);
}

UserMapper.xml

    <select id="selectPageVo" resultType="User">
	SELECT * FROM user where real_name = #{realName}
    </select>

使用

        Page<User> page = new Page<>(1, 10);
        IPage<User> iPage = userDao.selectPageVo(page,"王昭君");

五、Sequence主键

MP内置支持的数据库主键策略:

  1. DB2KeyGenerator
  2. H2KeyGenerator
  3. KingbaseKeyGenerator
  4. OracleKeyGenerator
  5. PostgreKeyGenerator

mybatis plus 实体类主键策略有3种( 注解 > 全局 > 默认 )

注解使用

public class User extends Model<User> {

    @TableId(value = "id", type = IdType.AUTO)
    private String id;

    @TableField("real_name")
    private String realName;
}

IdType

AUTO:数据库ID自增
INPUT:用户输入ID
NONE:该类型为未设置主键类型,注解里等于跟随全局,全局里约等于 INPUT
ASSIGN_ID:使用雪花算法分配ID,主键类型为Number(Long和Integer)或String
ASSIGN_UUID:分配UUID,主键类型为String
ID_WORKER:分布式全局唯一ID 长整型类型,已弃用
UUID:UUID:32位UUID字符串,已弃用
ID_WORKER_STR:分布式全局唯一ID 字符串类型,已弃用

spring boot

支持主键类型指定(3.3.0开始自动识别主键类型)

方式一:使用配置类

@Bean
public IKeyGenerator keyGenerator() {
    return new H2KeyGenerator();
}

方式二:通过MybatisPlusPropertiesCustomizer自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().getDbConfig().setKeyGenerator(new H2KeyGenerator());
}

Spring

方式一: XML配置

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
   <property name="dbConfig" ref="dbConfig"/>
</bean>

<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
   <property name="keyGenerator" ref="keyGenerator"/>
</bean>


<bean id="keyGenerator" class="com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator"/>

方式二:注解配置

@Bean
public GlobalConfig globalConfig() {
	GlobalConfig conf = new GlobalConfig();
	conf.setDbConfig(new GlobalConfig.DbConfig().setKeyGenerator(new H2KeyGenerator()));
	return conf;
}

六、自定义ID生成器

MP自3.3.0开始,默认使用雪花算法+UUID(不含中划线)

Spring-Boot

方式一:声明为Bean供Spring扫描注入

@Component
public class CustomIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
      	//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
      	String bizKey = entity.getClass().getName();
        //根据bizKey调用分布式ID生成
        long id = ....;
      	//返回生成的id值即可.
        return id;
    }
}

方式二:使用配置类

@Bean
public IdentifierGenerator idGenerator() {
    return new CustomIdGenerator();
}
#方式三:通过MybatisPlusPropertiesCustomizer自定义
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}
#

Spring

方式一: XML配置

<bean name="customIdGenerator" class="com.baomidou.samples.incrementer.CustomIdGenerator"/>

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
		<property name="identifierGenerator" ref="customIdGenerator"/>
</bean>

方式二:注解配置

@Bean
public GlobalConfig globalConfig() {
	GlobalConfig conf = new GlobalConfig();
	conf.setIdentifierGenerator(new CustomIdGenerator());
	return conf;
}

七、逻辑删除

逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案。使用一个状态来表示数据是否已被删除。

SpringBoot 配置方式:

application.yml 加入配置(如果你的默认值和mp默认的一样,该配置可无):

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  #全局逻辑删除字段值 3.3.0开始支持,详情看下面。
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

注册 Bean(3.1.1开始不再需要这一步):

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfiguration {

    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }
}

实体类字段上加上@TableLogic注解

@TableLogic
private Integer deleted;

效果: 使用mp自带方法删除和查找都会附带逻辑删除功能 (自己写的xml不会)

example
删除时 update user set deleted=1 where id =1 and deleted=0
查找时 select * from user where deleted=0

全局逻辑删除: 3.3.0开始支持

如果公司代码比较规范,比如统一了全局都是flag为逻辑删除字段。

使用此配置则不需要在实体类上添加 @TableLogic。

但如果实体类上有 @TableLogic 则以实体上的为准,忽略全局。 即先查找注解再查找全局,都没有则此表没有逻辑删除。

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  #全局逻辑删除字段值

八、通用枚举

1.枚举类

有2种使用方法

(1)注解@EnumValue

public enum GenderEnum {
    MEN(0, "男"),
    WOMEN(1, "女");

    GenderEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    @EnumValue
    private final int code;

    private String desc;
}

(2)实现 IEnum

public enum GenderIEnum implements IEnum<Integer> {

    MEN(0, "男"),
    WOMEN(1, "女");

    private  int code;
    private String desc;

    GenderIEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    @Override
    public Integer getValue() {
        return this.code;
    }
}

2.修改实体类

public class User extends Model<User> {

    。。。

    @TableField("gender")
    private GenderEnum gender;

	。。。

}

3.配置扫描通用枚举

mybatis-plus.type-enums-package=com.ljj.entity.enums

发布了29 篇原创文章 · 获赞 0 · 访问量 368

猜你喜欢

转载自blog.csdn.net/qq_43399077/article/details/103974505
今日推荐