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內置支持的數據庫主鍵策略:
- DB2KeyGenerator
- H2KeyGenerator
- KingbaseKeyGenerator
- OracleKeyGenerator
- 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