<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Mybatis-plus常用API全套教程,看完沒有不懂的

          共 20833字,需瀏覽 42分鐘

           ·

          2021-03-25 11:49

          來自:今日頭條,作者:java架構師阿松

          鏈接:https://www.toutiao.com/i6869621037831717387

          前言

          官網:

          https://baomidou.com/

          創(chuàng)建數據庫

          數據庫名為mybatis_plus

          創(chuàng)建表

          創(chuàng)建user表

          DROP TABLE IF EXISTS user;
          CREATE TABLE user
          (
          id BIGINT(20NOT NULL COMMENT '主鍵ID',
          name VARCHAR(30NULL DEFAULT NULL COMMENT '姓名',
          age INT(11NULL DEFAULT NULL COMMENT '年齡',
          email VARCHAR(50NULL DEFAULT NULL COMMENT '郵箱',
          PRIMARY KEY (id)
          );
          INSERT INTO user (idname, age, email) VALUES
          (1'Jone'18'[email protected]'),
          (2'Jack'20'[email protected]'),
          (3'Tom'28'[email protected]'),
          (4'Sandy'21'[email protected]'),
          (5'Billie'24'[email protected]');

          注意:-- 真實開發(fā)中往往都會有這四個字段,version(樂觀鎖)、deleted(邏輯刪除)、gmt_create(創(chuàng)建時間)、gmt_modified(修改時間)

          初始化項目

          使用SpringBoot器 初始化!

          導入依賴

          <!-- 數據庫驅動 -->
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
          </dependency>
          <!-- lombok -->
          <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
          </dependency>
          <!-- mybatis-plus -->
          <!-- mybatis-plus 是自己開發(fā),并非官方的! -->
          <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
          </dependency>

          注意:盡量不要同時導入 mybatis 和 mybatis-plus!避免版本的差異造成無法預知的問題。

          連接數據庫

          創(chuàng)建application.yml

          spring:
            profiles:
              active: dev
            datasource:
          # 驅動不同 mysql 5  com.mysql.jdbc.Driver
          #         mysql 8  com.mysql.cj.jdbc.Driver、需要增加時區(qū)的配置serverTimezone=GMT%2B8
              url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
              driver-class-name: com.mysql.cj.jdbc.Driver
              username: root
              password: root

          業(yè)務代碼

          實體類

          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          public class User {
            private Long id;
            private String name;
            private Integer age;
            private String email;

          mapper接口

          import com.baomidou.mybatisplus.core.mapper.BaseMapper;
          import com.kuang.pojo.User;
          import org.springframework.stereotype.Repository;
          // 在對應的Mapper上面繼承基本的類 BaseMapper
          @Repository // 代表持久層
          public interface UserMapper extends BaseMapper<User{
            // 所有的CRUD操作都已經編寫完成了
          }

          注意點,我們需要在主啟動類上去掃描我們的mapper包下的所有接口 @MapperScan(“com.kwhua.mapper”)

          測試

          @SpringBootTest
          class MybatisPlusApplicationTests {
            // 繼承了BaseMapper,所有的方法都來自己父類
            // 我們也可以編寫自己的擴展方法!
            @Autowired
            private UserMapper userMapper;
            @Test
            void contextLoads() {
              // 參數是一個 Wrapper ,條件構造器,這里我們先設置條件為空,查詢所有。
              List<User> users = userMapper.selectList(null);
              users.forEach(System.out::println);
           }

          所有數據輸出

          配置日志

          我們所有的sql現在是不可見的,我們希望知道它是怎么執(zhí)行的,所有我們要配置日志的輸出 application.yml文件添加日志配置

          #配置日志
          mybatis-plus:
            configuration:
              log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

          查看執(zhí)行sql的日志信息

          三.Mybatis-plus的CRUD

          插入操作

          // 測試插入
              @Test
              public void testInsert(){
                  User user = new User();
                  user.setName("kwhua_mybatis-plus_insertTest");
                  user.setAge(15);
                  user.setEmail("[email protected]");

                  int result = userMapper.insert(user); // 幫我們自動生成id
                  System.out.println(result); // 受影響的行數
                  System.out.println(user); // 看到id會自動填充。    }  

          看到id會自動填充。數據庫插入的id的默認值為:全局的唯一id

          主鍵生成策略

          1)主鍵自增 1、實體類字段上 @TableId(type = IdType.AUTO)

          2、數據庫id字段設置為自增!

          3、再次測試(可以看到id值比上次插入的大1)id的生成策略源碼解釋

          圖片
          public enum IdType {
            AUTO(0), // 數據庫id自增
            NONE(1), // 未設置主鍵
            INPUT(2), // 手動輸入
            ID_WORKER(3), // 默認的方式,全局唯一id
            UUID(4), // 全局唯一id uuid
            ID_WORKER_STR(5); //ID_WORKER 字符串表示法
          }

          以上不再逐一測試。

          更新操作

           @Test
              public void testUpdate(){
                  User user = new User();
                  // 通過條件自動拼接動態(tài)sql
                  user.setId(1302223874217295874L);
                  user.setName("kwhua_mybatis-plus_updateTest");
                  user.setAge(20);
                  // 注意:updateById 但是參數是一個對象!
                  int i = userMapper.updateById(user);
                  System.out.println(i);
              }
          圖片

          自動填充

          創(chuàng)建時間、修改時間!這兩個字段操作都是自動化完成的,我們不希望手動更新!阿里巴巴開發(fā)手冊:所有的數據庫表都要配置上gmt_create、gmt_modified!而且需要自動化!

          方式一:數據庫級別(工作中一般不用)

          1、在表中新增字段 gmt_create, gmt_modified

          2、把實體類同步

          private Date gmtCreate;
          private Date gmtModified;

          3、再次查看

          方式二:代碼級別 1、刪除數據庫的默認值、更新操作!

          2、實體類字段屬性上需要增加注解

              // 字段添加填充內容
              @TableField(fill = FieldFill.INSERT)
              private Date gmt_create;

              @TableField(fill = FieldFill.INSERT_UPDATE)
              private Date gmt_modified;

          3、編寫處理器來處理這個注解即可!

          @Slf4j
          @Component // 一定不要忘記把處理器加到IOC容器中!
          public class MyMetaObjectHandler implements MetaObjectHandler {
              // 插入時的填充策略
              @Override
              public void insertFill(MetaObject metaObject) {
                  log.info("start insert fill.....");
                  // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject
                  this.setFieldValByName("gmt_create",new Date(),metaObject);
                  this.setFieldValByName("gmt_modified",new Date(),metaObject);
              }

              // 更新時的填充策略
              @Override
              public void updateFill(MetaObject metaObject) {
                  log.info("start update fill.....");
                  this.setFieldValByName("gmt_modified",new Date(),metaObject);
              }
          }

          4、測試插入和更新,檢查時間變化。

          樂觀鎖

          樂觀鎖 : 顧名思義,十分樂觀,它總是認為不會出現問題,無論干什么不去上鎖!如果出現了問題, 再次更新值測試 悲觀鎖:顧名思義,十分悲觀,它總是認為總是出現問題,無論干什么都會上鎖!再去操作!

          樂觀鎖實現方式:

          取出記錄時,獲取當前version 更新時,帶上這個version 執(zhí)行更新時, set version = newVersion where version = oldVersion 如果version不對,就更新失敗

          樂觀鎖:1、先查詢,獲得版本號 version = 1

          -- A
          update user set name = "kwhua"version = version + 1
          where id = 2 and version = 1
          -- B 線程搶先完成,這個時候 version = 2,會導致 A 修改失敗!
          update user set name = "kwhua"version = version + 1
          where id = 2 and version = 1

          樂觀鎖測試

          1、給數據庫中增加version字段!

          圖片

          2、實體類加對應的字段

              @Version //樂觀鎖Version注解
              private Integer version;

          3、注冊組件

          // 掃描我們的 mapper 文件夾
          @MapperScan("com.kwhua.mapper")
          @EnableTransactionManagement
          @Configuration // 配置類
          public class MyBatisPlusConfig {
              // 注冊樂觀鎖插件
              @Bean
              public OptimisticLockerInterceptor optimisticLockerInterceptor() {
                  return new OptimisticLockerInterceptor();
              }
             }

          4、測試

          // 測試樂觀鎖成功!
              @Test
              public void testOptimisticLocker(){
                  // 1、查詢用戶信息
                  User user = userMapper.selectById(1L);
                  // 2、修改用戶信息
                  user.setName("kwhua");
                  user.setEmail("[email protected]");
                  // 3、執(zhí)行更新操作
                  userMapper.updateById(user);
              }

          version字段已經由1變成了2

          // 測試樂觀鎖失敗!多線程下
              @Test
              public void testOptimisticLocker2(){

                  // 線程 1
                  User user = userMapper.selectById(1L);
                  user.setName("kwhua111");
                  user.setEmail("[email protected]");

                  // 模擬另外一個線程執(zhí)行了插隊操作
                  User user2 = userMapper.selectById(1L);
                  user2.setName("kwhua222");
                  user2.setEmail("[email protected]");
                  userMapper.updateById(user2);

                  // 自旋鎖來多次嘗試提交!
                  userMapper.updateById(user); // 如果沒有樂觀鎖就會覆蓋插隊線程的值!
              }

          圖片

          可以看到線程1執(zhí)行更新失敗

          查詢操作

          // 測試查詢
              @Test
              public void testSelectById(){
                  User user = userMapper.selectById(1L);
                  System.out.println(user);
              }

              // 測試批量查詢!
              @Test
              public void testSelectByBatchId(){
                  List<User> users = userMapper.selectBatchIds(Arrays.asList(123));
                  users.forEach(System.out::println);
              }

              // 按條件查詢之一使用map操作
              @Test
              public void testSelectByBatchIds(){
                  HashMap<String, Object> map = new HashMap<>();
                  // 自定義要查詢
                  map.put("name","kwhua");
                  map.put("age",15);

                  List<User> users = userMapper.selectByMap(map);
                  users.forEach(System.out::println);
              }

          1、配置攔截器組件

          // 分頁插件
          @Bean
          public PaginationInterceptor paginationInterceptor() {
            return  new PaginationInterceptor();
          }

          2、直接使用Page對象即可!

          // 測試分頁查詢
          @Test
          public void testPage(){
            // 參數一:當前頁
            // 參數二:頁面大小
            Page<User> page = new Page<>(2,5);
            userMapper.selectPage(page,null);
            page.getRecords().forEach(System.out::println);
            System.out.println(page.getTotal());
          }

          物理刪除

          // 測試刪除
              @Test
              public void testDeleteById(){
                  userMapper.deleteById(1L);
              }

              // 通過id批量刪除
              @Test
              public void testDeleteBatchId(){
                  userMapper.deleteBatchIds(Arrays.asList(2L,3L));
              }

              // 通過map刪除
              @Test
              public void testDeleteMap(){
                  HashMap<String, Object> map = new HashMap<>();
                  map.put("name","kwhua");
                  userMapper.deleteByMap(map);
              }

          邏輯刪除

          物理刪除 :從數據庫中直接移除 邏輯刪除 :在數據庫中沒有被移除,而是通過一個變量來讓它失效!deleted = 0 => deleted = 1 管理員可以查看被刪除的記錄!防止數據的丟失,類似于回收站!

          1、在數據表中增加一個 deleted 字段2、實體類中增加屬性

           @TableLogic //邏輯刪除
           private Integer deleted;

          3、配置

          // 邏輯刪除組件!
              @Bean
              public ISqlInjector sqlInjector() {
                  return new LogicSqlInjector();
              }

          配置文件配置

           global-config:
              db-config:
                logic-delete-value: 1
                logic-not-delete-value: 0

          4、測試 測試刪除

          圖片

          字段值也從0修改成了1測試查詢

          圖片

          性能分析插件

          作用:性能分析攔截器,用于輸出每條 SQL 語句及其執(zhí)行時間 MP也提供性能分析插件,如果超過這個時間就停止運行!1、導入插件

             /**
               * SQL執(zhí)行效率插件
               */

              @Bean
              @Profile({"dev","test"})// 設置 dev test 環(huán)境開啟,保證我們的效率
              public PerformanceInterceptor performanceInterceptor() {
                  PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
                  performanceInterceptor.setMaxTime(100); //ms 設置sql執(zhí)行的最大時間,如果超過了則不執(zhí)行
                  performanceInterceptor.setFormat(true);
                  return performanceInterceptor;
              }

          圖片

          條件構造器(Wrapper)

          isNotNull .gt

          @Test
              void contextLoads() {
                  // 查詢name不為空的用戶,并且郵箱不為空的用戶,年齡大于等于12
                  QueryWrapper<User> wrapper = new QueryWrapper<>();
                  wrapper
                          .isNotNull("name"//不為空
                          .isNotNull("email")
                          .ge("age",18);
                  userMapper.selectList(wrapper).forEach(System.out::println); // 和我們剛才學習的map對比一下
              }
          圖片

          .eq

           @Test
              void test2(){
                  // 查詢名字kwhua
                  QueryWrapper<User> wrapper = new QueryWrapper<>();
                  wrapper.eq("name","kwhua");
                  User user = userMapper.selectOne(wrapper); // 查詢一個數據用selectOne,查詢多個結果使用List 或者 Map
                  System.out.println(user);
              }

          其他方法可以自己測試...

          代碼自動生成器

          // 代碼自動生成器
          public class generateCode {
             public static void main(String[] args) {
              // 需要構建一個 代碼自動生成器 對象
              AutoGenerator mpg = new AutoGenerator();
              // 配置策略
              // 1、全局配置
              GlobalConfig gc = new GlobalConfig();
              String projectPath = System.getProperty("user.dir");
              gc.setOutputDir(projectPath+"/src/main/java");
              gc.setAuthor("kwhua");//作者名稱
              gc.setOpen(false);
              gc.setFileOverride(false); // 是否覆蓋
              gc.setIdType(IdType.ID_WORKER);
              gc.setDateType(DateType.ONLY_DATE);
              gc.setSwagger2(true);//實體屬性 Swagger2 注解

              // 自定義文件命名,注意 %s 會自動填充表實體屬性!
              gc.setServiceName("%sService"); 
              gc.setControllerName("%sController");
              gc.setServiceName("%sService");
              gc.setServiceImplName("%sServiceImpl");
              gc.setMapperName("%sMapper");
              gc.setXmlName("%sMapper");

              mpg.setGlobalConfig(gc);

              //2、設置數據源
              DataSourceConfig dsc = new DataSourceConfig();
              dsc.setUrl("jdbc:mysql://localhost:3306/kwhua_test?
          useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"
          );
              dsc.setDriverName("com.mysql.cj.jdbc.Driver");
              // dsc.setDriverName("com.mysql.jdbc.Driver"); //mysql5.6以下的驅動
              dsc.setUsername("root");
              dsc.setPassword("root");
              dsc.setDbType(DbType.MYSQL);
              mpg.setDataSource(dsc);
              //3、包的配置
              PackageConfig pc = new PackageConfig();
              pc.setParent("com.kwhua"); //包名
              pc.setModuleName("model"); //模塊名
              pc.setEntity("entity");
              pc.setMapper("mapper");
              pc.setService("service");
              pc.setController("controller");
              mpg.setPackageInfo(pc);

              //4、策略配置
              StrategyConfig strategy = new StrategyConfig();
              strategy.setInclude("user","course"); // 設置要映射的表名
              strategy.setNaming(NamingStrategy.underline_to_camel);
              strategy.setColumnNaming(NamingStrategy.underline_to_camel);
              strategy.setEntityLombokModel(true); // 自動lombok;
              strategy.setLogicDeleteFieldName("deleted");
              // 自動填充配置
              TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
              TableFill gmtModified = new TableFill("gmt_modified",FieldFill.INSERT_UPDATE);
              ArrayList<TableFill> tableFills = new ArrayList<>();
              tableFills.add(gmtCreate);
              tableFills.add(gmtModified);
              strategy.setTableFillList(tableFills);
              // 樂觀鎖
              strategy.setVersionFieldName("version");
              //根據你的表名來建對應的類名,如果你的表名沒有下劃線,比如test,那么你就可以取消這一步
              strategy.setTablePrefix("t_");
              strategy.setRestControllerStyle(true); //rest請求
              //自動轉下劃線,比如localhost:8080/hello_id_2
              strategy.setControllerMappingHyphenStyle(true); 
              mpg.setStrategy(strategy);
              mpg.execute(); //執(zhí)行
           }
          }

          執(zhí)行主方法即可生成對應代碼

          END


          順便給大家推薦一個GitHub項目,這個 GitHub 整理了上千本常用技術PDF,絕大部分核心的技術書籍都可以在這里找到,

          GitHub地址:https://github.com/javadevbooks/books

          Gitee地址:https://gitee.com/javadevbooks/books

          電子書已經更新好了,你們需要的可以自行下載了,記得點一個star,持續(xù)更新中..



          瀏覽 44
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧洲日本在线 | 男人天堂b | 天堂网中文字幕在线观看 | 青娱乐欧美精品 | 黄色电影网站社区视频 |