mybatis plus 是基於mybatis 的一個增強包,比 mybatis 更加容易使用。
特點:
1.分頁支持
2.支持自定義查詢。
3.簡單的情況下,不需要寫map.xml 文件
4.支持租戶過濾
下面介紹一下 它的使用方法
1.引入jar包。
在 pom.xml 增加
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
2.配置使用數據源
spring: datasource: url: jdbc:mysql://localhost:3306/wuxianji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8 username: root password: root type: com.alibaba.druid.pool.DruidDataSource druid: # 下面為連接池的補充設置,應用到上面所有數據源中 # 初始化大小,最小,最大 initial-size: 5 min-idle: 5 max-active: 20 # 配置獲取連接等待超時的時間 max-wait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一個連接在池中最小生存的時間,單位是毫秒 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: false test-on-return: false # 打開PSCache,並且指定每個連接上PSCache的大小 pool-prepared-statements: true # 配置監控統計攔截的filters,去掉后監控界面sql無法統計,'wall'用於防火牆 max-pool-prepared-statement-per-connection-size: 20 filters: stat,wall use-global-data-source-stat: true # 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄 connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 配置監控服務器 stat-view-servlet: login-username: admin login-password: 123456 reset-enable: false url-pattern: /druid/* # 添加IP白名單 #allow: # 添加IP黑名單,當白名單和黑名單重復時,黑名單優先級更高 #deny: web-stat-filter: # 添加過濾規則 url-pattern: /* # 忽略過濾格式 exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
這里我們使用 druid 作為數據源
3.配置 mybatis plus
mybatis-plus: mapper-locations: classpath:/mapper/**/*.xml global-config: refresh: true # 刷新xml文件 db-config: logic-delete-value: 1 #默認值1 logic-not-delete-value: 0 #默認值0
這里指定了mapper xml 文件的位置。
4. 創建mybatis plus 配置java 文件
package com.example.config; import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.core.parser.ISqlParser; import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator; import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; import net.sf.jsqlparser.expression.LongValue; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import java.util.ArrayList; import java.util.List; @Configuration @MapperScan("com.example.demo.dao") public class MybatisPlusConfig { @Bean public PerformanceInterceptor performanceInterceptor(){ return new PerformanceInterceptor(); } @Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); } /** * 分頁插件 */ @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor= new PaginationInterceptor(); List<ISqlParser> sqlParserList = new ArrayList<>(); TenantSqlParser tenantSqlParser = new TenantSqlParser(); tenantSqlParser.setTenantHandler(new TenantHandler() { @Override public Expression getTenantId() { return new LongValue(1L); } @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public boolean doTableFilter(String tableName) { // 這里可以判斷是否過濾表 if ("User_".equals(tableName)) { return true; } return false; } }); sqlParserList.add(tenantSqlParser); paginationInterceptor.setSqlParserList(sqlParserList); return paginationInterceptor; } }
這里支持性能分析,邏輯刪除,租戶過濾,物理分頁。
5.下面以一個操作一個用戶表為例,介紹一下 具體的用法。
5.1 創建一個用戶表
CREATE TABLE `user_` ( `id_` bigint(11) NOT NULL DEFAULT '0', `name_` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `address` varchar(100) DEFAULT NULL, `isDelete` int(11) DEFAULT NULL, PRIMARY KEY (`id_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5.2 創建對應的User.java類
package com.example.demo.model; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; @TableName(value = "User_") public class User { @TableId(value="id_") private Long id; @TableField(value="name_") private String name; private Integer age; private String address; @TableLogic @TableField(value="isDelete") private Integer isDelete; }
這里去掉了get 和 set 方法。
5.3 創建 DAO操作數據庫
package com.example.demo.dao; import com.example.demo.model.*; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.Map; public interface UserMapper extends BaseMapper<User> { int updName(Map<String,Object> params); }
這個類繼承了 BaseMapper 接口,自動有增查改刪操作。
5.4 開始測試
1.列表查詢
private UserMapper userMapper; //@Test public void testSelect() { System.out.println(("----- selectAll method test ------")); List<User> userList = userMapper.selectList(null); Assert.assertEquals(5, userList.size()); userList.forEach(System.out::println); }
2.增加用戶
public void add() { User user=new User(); user.setId(14L); user.setName("關羽"); user.setAge(12); userMapper.insert(user); }
3.更新實體對象
public void upd() { User user=new User(); user.setId(13L); user.setName("zyg"); user.setAge(13); userMapper.updateById(user); }
4.自定義條件更新
public void updWrap() { User user=new User(); user.setAddress("廣州"); user.setAge(23); userMapper.update(user,new UpdateWrapper<User>().eq("name_","a").or().eq("name_","b")); }
這個意思是他會根據姓名 為 a 或 b 的用戶更新他的地址和年齡字段。
5.根據 MAP 傳值更新
public void updName() { Map<String,Object> params=new HashMap<>(); params.put("id",14); params.put("name","趙雲"); int i= userMapper.updName(params); System.err.println(i); }
這里我們需要在 User.xml 中增加
<update id="updName" parameterType="java.util.HashMap"> update user_ set name_=#{name} where id_=#{id} </update>
也需要在UserMapper 內中增加方法
int updName(Map<String,Object> params);
6.分頁獲取數據
public void getPage(){ Page<User> page = new Page<>(1, 5); IPage<User> userIPage = userMapper.selectPage(page, null); System.err.println(userIPage.getRecords()); }
這個需要配合MybatisPlusConfig 的分頁配置,才可以生效。
7.當分頁返回的數據不是 User 對象時,我們可以返回 Map對象。
public void getPageMap(){ Page page = new Page<>(1, 5); Wrapper wrapper=new QueryWrapper(); ((QueryWrapper) wrapper).ge("id_",2); IPage<Map<String,Object>> userIPage = userMapper.selectMapsPage(page,wrapper); System.err.println(userIPage.getRecords()); }
這里我們查詢Id_ 大於 2的用戶分頁列表。
8.邏輯刪除用戶
如果平台中數據不需要做實際刪除,我們可以配置邏輯刪除
配置方法如下:
MybatisPlusConfig 中指定了
@Bean public ISqlInjector sqlInjector() { return new LogicSqlInjector(); }
配置這個就支持邏輯刪除
application.yml配置如下:
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
refresh: true # 刷新xml文件
db-config:
logic-delete-value: 1 #默認值1
logic-not-delete-value: 0 #默認值0
這里指定邏輯刪除 刪除標記 為1 表示刪除 為0 表示正常。
User 對象 需要指定
@TableLogic
@TableField(value="isDelete")
指定邏輯刪除字段。
刪除代碼
public void delById(){ userMapper.deleteById(1L); }
這樣我們執行這個刪除時,后端並不執行刪除操作。
Time:9 ms - ID:com.example.demo.dao.UserMapper.deleteById
Execute SQL:UPDATE User_ SET isDelete = 1 WHERE id_ = 1 AND isDelete = 0
后端執行的語句為 將 刪除標記更新為1
9.分頁配置根據租戶查詢。
需要配置
List<ISqlParser> sqlParserList = new ArrayList<>(); TenantSqlParser tenantSqlParser = new TenantSqlParser(); tenantSqlParser.setTenantHandler(new TenantHandler() { @Override public Expression getTenantId() { return new LongValue(1L); } @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public boolean doTableFilter(String tableName) { // 這里可以判斷是否過濾表 if ("User_".equals(tableName)) { return true; } return false; } }); sqlParserList.add(tenantSqlParser); paginationInterceptor.setSqlParserList(sqlParserList);
1.指定租戶ID字段
2.返回租戶ID值
@Override public Expression getTenantId() { return new LongValue(1L); }
3.允許表過濾
有些表是不需要通過租戶過濾的,可以修改方法
@Override public boolean doTableFilter(String tableName) { // 這里可以判斷是否過濾表 if ("User_".equals(tableName)) { return true; } return false; }
10.樂觀鎖支持
樂觀鎖的原理是,每一條數據都帶有一個版本。
比如當前都版本為1.
在更新數據時,會將版本加一進行更新,如果A 進行更新,那么這個時候版本變為 2,如果B 同A一起發起更新,那么這個時候就更新不到,給出提示。
配置方法:
@Version private Integer version;
User 類中增加一個字段 為 version
配置增加樂觀鎖
@Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
編寫更新代碼
public void upd() { User user=new User(); user.setId(13L); user.setName("zyg"); user.setAge(13); user.setVersion(1); if( userMapper.updateById(user)>0){ System.err.println("更新成功"); } else { System.err.println("被其他人更新"); } }
執行上面的代碼
Time:7 ms - ID:com.example.demo.dao.UserMapper.updateById Execute SQL:UPDATE User_ SET name_ = 'zyg', age = 13, version = 2 WHERE id_ = 13 AND version = 1
這里我們可以看到他會自動將版本字段加1,如果執行成功就變成了2,當第二個人執行更新的時候,還是用版本1 進行更新,數據就更新不到了。