----线程1
// 1、查询id为1的用户
User user = userDao.selectById(1L);
// 2、修改用户信息
user.setName("Gump111");
user.setEmail("3218289928@qq.com");

    //---------模拟另外一个线程执行了插队操作
    // 1、查询id为1的用户
    User user2 = userDao.selectById(1L);
    // 2、修改用户信息
    user2.setName("Gump222");
    user2.setEmail("3218289928@qq.com");
    // 线程2 执行更新操作
    userDao.updateById(user2);
    // 线程1执行更新操作
    userDao.updateById(user);//如果没有乐观锁,就会覆盖插队线程刚刚修改的值
}





### 五、分页查询

1、导入分页插件,在配置类中添加

```JAVA
// 扫描mapper文件夹
@MapperScan("cn.nongyanxia.mapper")
@EnableTransactionManagement //事务注解
@Configuration
public class MyBatisPlusConfig {
    //    注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
    
    //分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

2、直接使用Page对象

 //测试分页查询
    @Test
    public void testPage(){
        // 查询第一页的5条数据 参数1:当前页  参数2:一页几条
        Page<User> page = new Page<>(1,5);
        userDao.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
        // 总数
        System.out.println(page.getTotal());
    }

六、条件构造器Wrapper

十分重要!!!

我们写一些复杂的sql就可以用它来替代!

官方文档:https://baomidou.com/guide/wrapper.html

1、测试1

代码:

//测试查询1
    @Test
    void contextLoads() {
        // 查询name不为空的用户,并且游戏不为空的用户,并且年龄大于等于18岁的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")//名字不为空
                .isNotNull("email")//邮箱不为空
                .ge("age", 18);//大于等于
        userDao.selectList(wrapper).forEach(System.out::println);
    }

执行的SQL:

SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE deleted=0 AND (name IS NOT NULL AND email IS NOT NULL AND age >= ?) 

2、测试2

代码:

 @Test
    void test02(){
        //查询名字等于 Gump 的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name", "Gump");
        User user = userDao.selectOne(wrapper);
        System.out.println(user);
    }

SQL:

SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE deleted=0 AND (name = ?) 

3、测试3

代码:

@Test
    void test03(){
        //查询年龄在20~30岁之间的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age", 20, 30);
        Integer num = userDao.selectCount(wrapper);//查询结果数
        System.out.println(num);
    }

SQL:

SELECT COUNT( 1 ) FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?) 

4、测试4

代码:

 //模糊查询
    @Test
    void test04(){
        //查询名字中不包含 G  的用户,并且邮箱是以3开头的
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.notLike("name", "G")
        .likeRight("email", "3");
        List<Map<String, Object>> maps = userDao.selectMaps(wrapper);
        maps.forEach(System.out::println);

    }

SQL:

SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE deleted=0 AND (name NOT LIKE ? AND email LIKE ?) 

5、测试5

代码:

@Test
    void test05(){

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // id在子查询中查出来
        wrapper.inSql("id", "select id from user where id < 3");
        List<Object> objects = userDao.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }

SQL:

SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE deleted=0 AND (id IN (select id from user where id < 3)) 

6、测试6

代码:

@Test
    void test06(){

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // 通过id进行排序
        // 倒序  Asc 正序
        wrapper.orderByDesc("id");
        List<User> users = userDao.selectList(wrapper);
    }

SQL:

SELECT id,name,age,email,version,deleted,create_time,update_time FROM user WHERE deleted=0 ORDER BY id DESC 

七、代码自动生成器

​ AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

​ 由于MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖,由于我配置写了swagger,所以还需要导入swagger的依赖,以及lombok插件

1、pom.xml

<!--MyBatis_Plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <!--代码生成器依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.2</version>
        </dependency>
        <!--默认的模板引擎依赖-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>
        <!--swagger-->
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2、代码:

package cn.nongyanxia;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;

//代码自动生成器
public class GumpCode {
    public static void main(String[] args) {
        // 需要构建代码生成器对象
        AutoGenerator mpg = new AutoGenerator();
        //配置策略
        //---------1、全局配置
        GlobalConfig config = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        config.setOutputDir(projectPath+"/src/main/java");
        //设置作者
        config.setAuthor("Gump");
        //是否打开Windows文件夹
        config.setOpen(false);
        //是否覆盖
        config.setFileOverride(false);
        //去service的 i 前缀
        config.setServiceName("%sService");
        //主键生成策略
        config.setIdType(IdType.ASSIGN_UUID);
        //日期类型
        config.setDateType(DateType.ONLY_DATE);
        //是否配置swagger文档
        config.setSwagger2(true);
        mpg.setGlobalConfig(config);

        //--------2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("529122");
        //数据库类型 为MySQL
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        //----------3、包的配置
        PackageConfig pc = new PackageConfig();
        //模块名称
        pc.setModuleName("blog");
        //生成cn.nongyanxia.blog 的模块
        pc.setParent("cn.nongyanxia");
        //配置包的名称
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);

        //---------4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true); //自动lombok
        strategy.setLogicDeleteFieldName("deleted");//逻辑删除字段
        strategy.setRestControllerStyle(true);//开启restful的驼峰命名格式
        //自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
        tableFills.add(updateTime);
        strategy.setTableFillList(tableFills);
        //乐观锁配置
        strategy.setVersionFieldName("version");

        strategy.setControllerMappingHyphenStyle(true);//localhost:8080/hello_id_2
        mpg.setStrategy(strategy);

        mpg.execute();//执行
    }
}

3、运行后结果

image-20200820150710913

这样就算成功了!

Q.E.D.


理想三旬浓烟下,奔赴山海与荒野