MyBatis-Plus 使用指南

[toc]java

介紹

MyBatis 是一個java的半自動化ORM框架,而MyBatis-Plus是對它的二次封裝,簡化MyBatais的使用,簡單的說, 能夠儘量少的手寫增刪改查的sql語句 。mysql

官方文檔地址:mp.baomidou.com/guidegit

文檔是中文的, 喜歡本身看文檔的同窗能夠直接照官方文檔來操做學習。 我這篇文章主要是記錄本身的學習過程,最後會提供本身的代碼及測試的數據庫環境部署。不想本身弄這些步驟的同窗能夠參照我這篇文章部署好環境來學習。github

部署數據庫

  • 啓動數據庫容器 使用docker容器在虛擬機中部署數據庫很簡單,只須要一個docker-compose.yml文件, 下面是docker-compose.yml完整文件內容:
version: '3.1'
services:
  mysql:
    restart: always
    image: mysql:5.7.22
    container_name: mysql
    ports:
      - 3306:3306
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: 123456
    command:
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1
      --max_allowed_packet=128M
      --sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
    volumes:
      - ./data:/var/lib/mysql
複製代碼

不會使用docker容器能夠參考 這篇文章 來學習web

Spring Boot 整合 MyBatis-Plus

項目是基於Spring Boot的, 建立項目後,添加各項依賴,完整pom.xml文件以下:spring

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.domain</groupId>
    <artifactId>hello-mybatisplus</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-mybatisplus</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!--mysql start-->
        <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>
            <scope>runtime</scope>
        </dependency>

        <!--mysql end-->

        <!--lombok start-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--lombok end -->


        <!--mybatisplus start-->


        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.2</version>
        </dependency>


        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.1</version>
        </dependency>


        <!--mybatisplus end-->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>


        </plugins>
    </build>

</project>

複製代碼

主要添加了數據庫鏈接、和MyBatis-Plus的依賴。sql

鏈接數據庫

在application.yml中添加數據庫鏈接配置:docker

spring:
  datasource:
    druid:
      url: jdbc:mysql://192.168.65.130:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      # MySQL 8.x: com.mysql.cj.jdbc.Driver
      driver-class-name: com.mysql.jdbc.Driver
      test-while-idle: true
      
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
複製代碼

主要配置了數據庫的地址,用戶名,密碼, 和打開mybatis-plus的sql日誌, 這樣待會測試的時候日誌就會打印出當前數據庫操做的sql語句,便於學習和排錯。數據庫

代碼生成器

MyBatis-Plus 提供了代碼生成器的功能,能自動幫咱們生成mapper.xmlMapper.java POJO 等文件。運行一下代碼來生成這些文件:apache

package com.domain.hello.mybatisplus;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CodeGenerator {

    /**
     * <p>
     * 讀取控制檯內容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("請輸入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("請輸入正確的" + tip + "!");
    }

    public static void main(String[] args) {
        // 代碼生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("domain");
        gc.setOpen(false);
//        gc.setSwagger2(true); //實體屬性 Swagger2 註解
        mpg.setGlobalConfig(gc);

        // 數據源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://192.168.65.130:3306/myshop?useUnicode=true&useSSL=false&characterEncoding=utf8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
//        pc.setModuleName(scanner("模塊名"));
        pc.setParent("com.domain.hello.mybatisplus");
        mpg.setPackageInfo(pc);

        // 自定義配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 若是模板引擎是 freemarker
//        String templatePath = "/templates/mapper.xml.ftl";
        // 若是模板引擎是 velocity
         String templatePath = "/templates/mapper.xml.vm";

        // 自定義輸出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定義配置會被優先輸出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定義輸出文件名 , 若是你 Entity 設置了先後綴、此處注意 xml 的名稱會跟着發生變化!!
                return projectPath + "/src/main/resources/mapper/" /*+ pc.getModuleName()*/
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });



        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判斷自定義文件夾是否須要建立
                checkDir("調用默認方法建立的目錄");
                return false;
            }
        });
        */
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定義輸出模板
        //指定自定義模板路徑,注意不要帶上.ftl/.vm, 會根據使用的模板引擎自動識別
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        strategy.setSuperEntityClass("com.domain.hello.mybatisplus.common.BaseEntity");
        strategy.setEntityLombokModel(true);
//        strategy.setRestControllerStyle(true);
        // 公共父類
//        strategy.setSuperControllerClass("com.domain.hello.mybatisplus.common.BaseController");
        // 寫於父類中的公共字段
        strategy.setSuperEntityColumns("id");
//        strategy.setInclude(scanner("表名,多個英文逗號分割").split(","));
        strategy.setInclude(new String[] { "tb_user", "tb_item_cat","tb_content"});
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);


//        strategy.setRestControllerStyle(false);
//        strategy.setSuperServiceClass(null);


//        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
//        mpg.setTemplateEngine(new VelocityTemplateEngine());
        mpg.execute();
    }

}

複製代碼

CRUD 操做

在單元測試來執行MyBatis-Plus提供的CRUD操做

/**
     * 測試插入數據
     */
    @Test
    public void testInsert() {
        // 構造一條測試數據
        for (int i = 0; i < 3; i++) {

            TbUser tbUser = new TbUser();
            tbUser.setUsername("domain" + RandomUtils.nextDouble());
            tbUser.setPassword("123456" + RandomUtils.nextDouble());
            tbUser.setPhone("130" + RandomUtils.nextInt());
            tbUser.setEmail("topsale@vip.qq.com" + RandomUtils.nextDouble());
            tbUser.setCreated(new Date());
            tbUser.setUpdated(new Date());

            // 插入數據
            tbUserMapper.insert(tbUser);
        }
    }
複製代碼

@Test
    public void testDelete() {

        UpdateWrapper updateWrapper = new UpdateWrapper<TbUser>();

        HashMap<String, Object> params = new HashMap<>();
        params.put("id", 7);
        params.put("username", "zhangsan");

        updateWrapper.allEq(params);

        tbUserMapper.delete(updateWrapper);

//        tbUserMapper.deleteById("46");
//        ArrayList<Integer> ids = new ArrayList<Integer>();
//        ids.add(47);
//        tbUserMapper.deleteBatchIds(ids);

    }
複製代碼

@Test
    public void testUpdate() {

        UpdateWrapper<TbUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("username", "domain111");

        TbUser tbUser = new TbUser();
        tbUser.setUsername("domain");

        tbUserMapper.update(tbUser, updateWrapper);

    }
複製代碼

@Test
    public void testSelect() {
        UpdateWrapper<TbUser> wrapper = new UpdateWrapper<>();
        wrapper.eq("username", "domain"); //等於

        List<TbUser> tbUsers = tbUserMapper.selectList(wrapper);
        for (TbUser tbUser : tbUsers) {
            System.out.println("\n" + tbUser.getUsername());
        }
    }
複製代碼

分頁

MyBatis-Plus 也支持分頁, 只須要簡單配置便可以使用

Config.java配置

package com.domain.hello.mybatisplus.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement
@Configuration
@MapperScan("com.domain.hello.mybatisplus.mapper.*.mapper*")
public class MybatisPlusConfig {
    /**
     * 分頁插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

複製代碼

添加mapper 方法

mapper.java

@Repository
public interface TbUserMapper extends BaseMapper<TbUser> {

     List<TbUser> getAll();
     /**
      * <p>
      * 查詢 : 根據state狀態查詢用戶列表,分頁顯示
      * 注意!!: 若是入參是有多個,須要加註解指定參數名才能在xml中取值
      * </p>
      *
      * @param page 分頁對象,xml中能夠從裏面進行取值,傳遞參數 Page 即自動分頁,必須放在第一位(你能夠繼承Page實現本身的分頁對象)
      * @param state 狀態
      * @return 分頁對象
      */
     IPage<TbUser> selectPageVo(Page page, @Param("city") String city);

}
複製代碼

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.domain.hello.mybatisplus.mapper.TbUserMapper">

    <select id="selectPageVo" resultType="com.domain.hello.mybatisplus.entity.TbUser">
    SELECT id,username FROM tb_user WHERE city=#{city}
    </select>

</mapper>

複製代碼

測試分頁

@Test
    public void testPage() {

        // 不進行 count sql 優化,解決 MP 沒法自動優化 SQL 問題,這時候你須要本身查詢 count 部分
        // page.setOptimizeCountSql(false);
        // 當 total 爲小於 0 或者設置 setSearchCount(false) 分頁插件不會進行 count 查詢
        // 要點!! 分頁返回的對象與傳入的對象是同一個

        //頁碼下標
        Integer pageIndex = 1;
        //每頁數量
        Integer pageSize = 2;

        IPage<TbUser> iPage = tbUserMapper.selectPageVo(new Page(pageIndex * pageSize, pageSize), "gz");


        List<TbUser> tbUsers = iPage.getRecords();

        for (TbUser tbUser : tbUsers) {
            System.out.println("\n" + tbUser.getUsername());
        }
    }
複製代碼

條件構造器

MyBatis-Plus 提供了條件構造器來構建sql語句的條件。

@Test
    public void testSelect() {

        UpdateWrapper<TbUser> wrapper = new UpdateWrapper<>();
//        wrapper.eq("password","195d91be1e3ba6f1c857d46f24c5a454"); //等於
//        wrapper.ne("username","domain");//不等於
//        wrapper.gt("age",18); //大於
//        wrapper.ge("age",22); //大於等於
//        wrapper.lt("age", 22); //小於
//        wrapper.le("age", 22); //小於等於
//        wrapper.between("age","22","25"); //between value1 和 value2之間
//        wrapper.notBetween("age","22","25");//not between value1 和 value2之間, null 不會查出來
//        wrapper.like("username","domain"); %value%
//        wrapper.likeLeft("username","1");  %value
//        wrapper.likeRight("username","zhangsan"); value%
//        wrapper.isNull("age"); //age == null 的數據
//        wrapper.in("age","31","33"); age 是 31 33 的
//        wrapper.notIn("age","22","23");age 不是 22 22的, age爲null的 不會查出來
//        wrapper.inSql("id", "select id from tb_user where id > 3"); // id 爲 後面語句中查出來的id集合的 記錄 至關於 where id in (4,5,6);       SELECT username,password,phone,email,created,updated FROM tb_user WHERE id IN (select id from tb_user where id > 3)
//        wrapper.notInSql("id","select id from tb_user where id < 22");//id 不小於 22 的記錄
//        wrapper.notInSql("id","select id from tb_user where id < 22");//id 不小於 22 的記錄,null 也查出來, 由於null 不在小於22的範圍內
//        wrapper.groupBy("age"); //經過 age 分組,age相同爲一組, 一組只有一條記錄就是組的第一條記錄
//        wrapper.orderByAsc("id","age");//以id,age 升序排序,先對id排序, id相同, 對age排序
//        wrapper.orderBy(true,true,"id","age"); //和上面效果相同
//        wrapper.orderByDesc("id","age");//以id,age 降序排序,先對id排序, id相同, 對age排序


        //having
        //    須要注意的是,
        //
        //    having 子句中的每個元素也必須出如今select列表中。有些數據庫例外,如oracle.
        //            having子句和where子句均可以用來設定限制條件以使查詢結果知足必定的條件限制。
        //    having子句限制的是組,而不是行。where子句中不能使用匯集函數,而having子句中能夠。
        //    當加上其餘sql語句時,執行順序以下:
        //    S-F-W-G-H-O 組合
        //
        //    select –>where –> group by–> having–>order by
        //
        //    順序是不能改變的

//
//        SELECT
//                username,
//                city,
//        SUM(price)
//        FROM
//                tb_user
//        GROUP BY
//        city
//                HAVING
//        SUM(price) > 2000

//        wrapper.groupBy("city").having("sum(price)>2000");

//        wrapper.having("sum(age)>22");


//        wrapper.eq("username","domain").or().eq("age","22");  username = domain 或者 age = 22

        //OR 嵌套
//        wrapper.eq("username", "domain")
//                .or(i -> i.eq("age", "22").eq("phone", "13333333334"));// username = domain 或者 (age = 22 and phone = 13333333334)

        //and 嵌套
//        wrapper.eq("age","22")
//                .and(i -> i.eq("phone","13333333333").or().eq("phone","13333333334"));// age ==22 and (phone =13333333333 or phone = 13333333334)

        //nested ,正常嵌套 username=domain 或者 age<22
//        wrapper.nested(i -> i.eq("username","domain").or().lt("age","22"));


        wrapper.set("username", "domain").eq("username", "niuniu");

        List<TbUser> tbUsers = tbUserMapper.selectList(wrapper);


        /**
         * QueryWrapper, 能夠指定要查詢哪些字段
         */
//        QueryWrapper<TbUser> queryWrapper = new QueryWrapper<>();
//        queryWrapper.select("username","password","phone");
//        queryWrapper.eq("username","domain");
//        List<TbUser> tbUsers = tbUserMapper.selectList(queryWrapper);

        /**
         * 自定義 sql
         */
//        List<TbUser> tbUsers = tbUserMapper.getAll();


        for (TbUser tbUser : tbUsers) {
            System.out.println("\n" + tbUser.getUsername());
        }

    }
複製代碼

自定義sql

若是MyBatis-Plus 提供的CRUD方法沒辦法知足需求, 這時候就要本身手寫sql來知足需求了。

好比查詢 用戶所在城市的的總金額大於2000 的記錄。

mapper.java 定義方法

@Repository
public interface TbUserMapper extends BaseMapper<TbUser> {

     List<TbUser> getAll();
}
複製代碼

mapper.xml 定義sql

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.domain.hello.mybatisplus.mapper.TbUserMapper">

    <select id="getAll" resultType="com.domain.hello.mybatisplus.entity.TbUser">
        SELECT
            username,
            city,
            SUM(price) as amount
        FROM
            tb_user
        GROUP BY
            city
        HAVING
            SUM(price) > 2000

    </select>
</mapper>
複製代碼

測試自定義sql

@Test
    public void testSelect() {

        /**
         * 自定義 sql
         */
        List<TbUser> tbUsers = tbUserMapper.getAll();


        for (TbUser tbUser : tbUsers) {
            System.out.println("\n" + tbUser.getUsername());
        }
        
    }
複製代碼

完整代碼

完整代碼地址:github.com/domain9065/…

相關文章
相關標籤/搜索