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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章