Mybatis Plus_指南

文章目录

  • 快速入门
  • 代码生成器
  • CRUD
    • insert
    • delete、deleteById
    • updateById、update
    • selectOne、selectList、selectBatchIds、selectByMap
    • orderBy、orderByLambda
    • SelectMaxId
    • GroupBy
  • 条件构造器
    • 普通查询eq
    • 带子查询(sql注入)inSql
    • 带嵌套查询nested、or、and、ge
    • isNotNull
    • between
    • 模糊查询like、notLike、likeRight、likeLeft
    • 排序 orderByAsc
  • 分页插件
    • baseMapper自带
  • 性能分析
  • 乐观锁
  • 公共字段自动填充
  • 逻辑删除
  • 枚举注入

快速入门

  • 数据库建表SQL
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
INSERT INTO user (id, name, 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]');
-- 真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified
  • 依赖

<dependency>
  <groupId>mysqlgroupId>
  <artifactId>mysql-connector-javaartifactId>
dependency>

<dependency>
  <groupId>org.projectlombokgroupId>
  <artifactId>lombokartifactId>
dependency>


<dependency>
  <groupId>com.baomidougroupId>
  <artifactId>mybatis-plus-boot-starterartifactId>
  <version>3.0.5version>
dependency>
  • 配置文件
spring:
  # 设置开发环境
  profiles:
    active: dev
  
  # 数据源
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456

# Logger Config
logging:
  level:
    com.baomidou.mybatisplus.samples.quickstart: debug
  • entity类
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  • Mapper
public interface UserMapper extends BaseMapper<User> {}
  • 主启动类
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class QuickstartApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuickstartApplication.class, args);
    }

}
  • 测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {

    @Resource
    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);
    }
}

代码生成器

// 代码自动生成器
public class KuangCode {
  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("cl");
    gc.setOpen(false);
    gc.setFileOverride(false); // 是否覆盖
    gc.setServiceName("%sService"); // 去Service的I前缀
    gc.setIdType(IdType.ID_WORKER);
    gc.setDateType(DateType.ONLY_DATE);
    gc.setSwagger2(true);
    mpg.setGlobalConfig(gc);
    //2、设置数据源
    DataSourceConfig dsc = new DataSourceConfig();
    dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
    dsc.setDriverName("com.mysql.cj.jdbc.Driver");
    dsc.setUsername("root");
    dsc.setPassword("123456");
    dsc.setDbType(DbType.MYSQL);
    mpg.setDataSource(dsc);
    //3、包的配置
    PackageConfig pc = new PackageConfig();
    pc.setModuleName("blog");
    pc.setParent("com.cl");
    pc.setEntity("entity");
    pc.setMapper("mapper");
    pc.setService("service");
    pc.setController("controller");
    mpg.setPackageInfo(pc);
    //4、策略配置
    StrategyConfig strategy = new StrategyConfig();
  
 strategy.setInclude("blog_tags","course","links","sys_settings","user_record","
user_say"); // 设置要映射的表名
    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");
    strategy.setRestControllerStyle(true);
    strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
    mpg.setStrategy(strategy);
    mpg.execute(); //执行
 }
}

CRUD

insert

@Test
public void aInsert() {
    User user = new User();
    user.setName("小羊");
    user.setAge(3);
    user.setEmail("[email protected]");
    assertThat(mapper.insert(user)).isGreaterThan(0);
    // 成功直接拿会回写的 ID
    assertThat(user.getId()).isNotNull();
	
	//active record
	Assert.assertTrue(user.insert());
    // 成功直接拿会写的 ID
    System.err.println("\n插入成功 ID 为:" + user.getId());
}

delete、deleteById

@Test
public void bDelete() {
    assertThat(mapper.deleteById(3L)).isGreaterThan(0);
    // 删除名字为Sandy的User
    assertThat(mapper.delete(new QueryWrapper<User>()
            .lambda().eq(User::getName, "Sandy"))).isGreaterThan(0);
    // 根据id批量删除
    mapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
	// 通过Map删除
	HashMap<String, Object> map = new HashMap<>();
  	map.put("name","Sandy");
  	mapper.deleteByMap(map);

	// active record
	Assert.assertTrue(new User().setId(3L).deleteById());
    Assert.assertTrue(new User().delete(new QueryWrapper<User>()
            .lambda().eq(User::getName, "Sandy")));
}

updateById、update

@Test
public void cUpdate() {
	// 将id为1的用户邮箱更新
    assertThat(mapper.updateById(new User().setId(1L).setEmail("[email protected]"))).isGreaterThan(0);
    // 将id为2的用户名字更改为mp,年龄更改为3
    assertThat(
            mapper.update(
                    new User().setName("mp"),
                    Wrappers.<User>lambdaUpdate()
                            .set(User::getAge, 3)
                            .eq(User::getId, 2)
            )
    ).isGreaterThan(0);
    User user = mapper.selectById(2);
    assertThat(user.getAge()).isEqualTo(3);
    assertThat(user.getName()).isEqualTo("mp");
	// 将id为2 的用户的邮箱置空
    mapper.update(
            null,
            Wrappers.<User>lambdaUpdate().set(User::getEmail, null).eq(User::getId, 2)
    );
    assertThat(mapper.selectById(1).getEmail()).isEqualTo("[email protected]");
    user = mapper.selectById(2);
    assertThat(user.getEmail()).isNull();
    assertThat(user.getName()).isEqualTo("mp");
	// 将id为2 的用户邮箱更新
    mapper.update(
            new User().setEmail("[email protected]"),
            new QueryWrapper<User>()
                    .lambda().eq(User::getId, 2)
    );
    user = mapper.selectById(2);
    assertThat(user.getEmail()).isEqualTo("[email protected]");
	// 将id为2的用户邮箱更新,年龄置空
    mapper.update(
            new User().setEmail("[email protected]"),
            Wrappers.<User>lambdaUpdate()
                    .set(User::getAge, null)
                    .eq(User::getId, 2)
    );
    user = mapper.selectById(2);
    assertThat(user.getEmail()).isEqualTo("[email protected]");
    assertThat(user.getAge()).isNull();
	// active record
	Assert.assertTrue(new User().setId(1L).setEmail("[email protected]").updateById());
    Assert.assertTrue(new User().update(new UpdateWrapper<User>().lambda()
                    .set(User::getAge, 3).eq(User::getId, 2)));
}

selectOne、selectList、selectBatchIds、selectByMap

@Test
public void dSelect() {
	// 插入一条数据
    mapper.insert(
            new User().setId(10086L)
                    .setName("miemie")
                    .setEmail("[email protected]")
                    .setAge(3));
    assertThat(mapper.selectById(10086L).getEmail()).isEqualTo("[email protected]");
    // 查询用户id为10086的数据
    User user = mapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 10086));
    assertThat(user.getName()).isEqualTo("miemie");
    assertThat(user.getAge()).isEqualTo(3);
	// 查询所有用户的id
    mapper.selectList(Wrappers.<User>lambdaQuery().select(User::getId))
            .forEach(x -> {
                assertThat(x.getId()).isNotNull();
                assertThat(x.getEmail()).isNull();
                assertThat(x.getName()).isNull();
                assertThat(x.getAge()).isNull();
            });
    // 查询所有用户的id和name
    mapper.selectList(new QueryWrapper<User>().select("id", "name"))
            .forEach(x -> {
                assertThat(x.getId()).isNotNull();
                assertThat(x.getEmail()).isNull();
                assertThat(x.getName()).isNotNull();
                assertThat(x.getAge()).isNull();
            });
    // 查询id为1、2、3的三个用户
	mapper.selectBatchIds(Arrays.asList(1,2,3)).forEach(System.out::println);
	// 自定义Map查询
	HashMap<String, Object> map = new HashMap<>();
  	map.put("name","Sandy");
  	map.put("age",3);
  	List<User> users = mapper.selectByMap(map);
	
	//active record
	Assert.assertEquals("[email protected]", new User().setId(1L).selectById().getEmail());
    User user = new User().selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 2));
}

orderBy、orderByLambda

@Test
public void orderBy() {
    List<User> users = mapper.selectList(Wrappers.<User>query().orderByAsc("age"));
	List<User> users = mapper.selectList(Wrappers.<User>lambdaQuery().orderByAsc(User::getAge));
}

SelectMaxId

@Test
public void testSelectMaxId() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.select("max(id) as id");
    User user = mapper.selectOne(wrapper);
}

GroupBy

@Test
public void testGroup() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.select("age, count(*)")
            .groupBy("age");
    List<Map<String, Object>> maplist = mapper.selectMaps(wrapper);
    for (Map<String, Object> mp : maplist) {
        System.out.println(mp);
    }
    /**
     * lambdaQueryWrapper groupBy orderBy
     */
    LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda()
            .select(User::getAge)
            .groupBy(User::getAge)
            .orderByAsc(User::getAge);
    for (User user : mapper.selectList(lambdaQueryWrapper)) {
        System.out.println(user);
    }
}

条件构造器

普通查询eq

List<User> plainUsers = userMapper.selectList(new QueryWrapper<User>().eq("role_id", 2L));
List<User> lambdaUsers = userMapper.selectList(new QueryWrapper<User>().lambda().eq(User::getRoleId, 2L));

带子查询(sql注入)inSql

// select * from role where id in (select id from role where id = 2) ;
List<User> plainUsers2 = userMapper.selectList(new LambdaQueryWrapper<User>()
        .inSql(User::getRoleId, "select id from role where id = 2"));
List<User> lambdaUsers2 = userMapper.selectList(new QueryWrapper<User>().lambda()
        .inSql(User::getRoleId, "select id from role where id = 2"));

带嵌套查询nested、or、and、ge

// select * from role where (id =2 or id =3) and age>=20;
List<User> plainUsers3 = userMapper.selectList(new LambdaQueryWrapper<User>()
        .nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
        .and(i -> i.ge(User::getAge, 20)));
List<User> lambdaUsers3 = userMapper.selectList(new QueryWrapper<User>().lambda()
        .nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
        .and(i -> i.ge(User::getAge, 20)));
/**
 * SELECT id,name,age,email,role_id FROM user
 * WHERE ( 1 = 1 ) AND ( ( name = ? AND age = ? ) OR ( name = ? AND age = ? ) )
 */
QueryWrapper<User> w = new QueryWrapper<>();
w.and(i -> i.eq("1", 1))
        .nested(i ->
                i.and(j -> j.eq("name", "a").eq("age", 2))
                        .or(j -> j.eq("name", "b").eq("age", 2)));
userMapper.selectList(w);

isNotNull

QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
 .isNotNull("name")
 .isNotNull("email")
 .ge("age",12);
userMapper.selectList(wrapper).forEach(System.out::println); 

between

// 查询年龄在 20 ~ 30 岁之间的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",20,30); 
// 查询结果数
Integer count = userMapper.selectCount(wrapper);

模糊查询like、notLike、likeRight、likeLeft

QueryWrapper<User> wrapper = new QueryWrapper<>();
// 左和右 t%
wrapper
   .notLike("name","e")
   .likeRight("email","t");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);

排序 orderByAsc

QueryWrapper<User> wrapper = new QueryWrapper<>();
// 通过id进行排序
wrapper.orderByAsc("id");
List<User> users = userMapper.selectList(wrapper);

分页插件

baseMapper自带

  • 配置
@Configuration
@MapperScan("com.baomidou.mybatisplus.samples.pagination.mapper")
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        // 开启 count 的 join 优化,只针对 left join !!!
        return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
    }
}
// select * from user where age=20 and name=jack limit 0,5 
Page<User> page = new Page<>(1, 5);
page.addOrder(OrderItem.asc("age"));
Page<User> userIPage = mapper.selectPage(page, Wrappers.<User>lambdaQuery().eq(User::getAge, 20).like(User::getName, "Jack"));
assertThat(page).isSameAs(userIPage);
log.error("总条数 -------------> {}", userIPage.getTotal());
log.error("当前页数 -------------> {}", userIPage.getCurrent());
log.error("当前每页显示数 -------------> {}", userIPage.getSize());
List<User> records = userIPage.getRecords();

性能分析

  • pom
<dependency>
   <groupId>p6spygroupId>
   <artifactId>p6spyartifactId>
dependency>
  • properties
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

乐观锁

  • 配置
@Configuration
public class MybatisPlusOptLockerConfig {

    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
@Order(0)
@Test
public void testUpdateByIdSucc() {
    User user = new User();
    user.setAge(18);
    user.setEmail("[email protected]");
    user.setName("optlocker");
    user.setVersion(1);
    userMapper.insert(user);
    Long id = user.getId();

    User userUpdate = new User();
    userUpdate.setId(id);
    userUpdate.setAge(19);
    userUpdate.setVersion(1);
    assertThat(userMapper.updateById(userUpdate)).isEqualTo(1);
    assertThat(userUpdate.getVersion()).isEqualTo(2);
}

@Order(1)
@Test
public void testUpdateByIdSuccFromDb() {
    User user = userMapper.selectById(1);
    int oldVersion = user.getVersion();
    int i = userMapper.updateById(user);
    assertThat(i).isEqualTo(1);
    assertThat(oldVersion + 1).isEqualTo(user.getVersion());
}

@Order(2)
@Test
public void testUpdateByIdFail() {
    User user = new User();
    user.setAge(18);
    user.setEmail("[email protected]");
    user.setName("optlocker");
    user.setVersion(1);
    userMapper.insert(user);
    Long id = user.getId();

    User userUpdate = new User();
    userUpdate.setId(id);
    userUpdate.setAge(19);
    userUpdate.setVersion(0);
    Assert.assertEquals("Should update failed due to incorrect version(actually 1, but 0 passed in)", 0, userMapper.updateById(userUpdate));
}

@Order(3)
@Test
public void testUpdateByIdSuccWithNoVersion() {
    User user = new User();
    user.setAge(18);
    user.setEmail("[email protected]");
    user.setName("optlocker");
    user.setVersion(1);
    userMapper.insert(user);
    Long id = user.getId();

    User userUpdate = new User();
    userUpdate.setId(id);
    userUpdate.setAge(19);
    userUpdate.setVersion(null);
    Assert.assertEquals("Should update success as no version passed in", 1, userMapper.updateById(userUpdate));
    User updated = userMapper.selectById(id);
    Assert.assertEquals("Version not changed", 1, updated.getVersion().intValue());
    Assert.assertEquals("Age updated", 19, updated.getAge().intValue());
}

/**
 * 批量更新带乐观锁
 * 

* update(et,ew) et:必须带上version的值才会触发乐观锁 */ @Order(4) @Test public void testUpdateByEntitySucc() { QueryWrapper<User> ew = new QueryWrapper<>(); ew.eq("version", 1); int count = userMapper.selectCount(ew); User entity = new User(); entity.setAge(28); entity.setVersion(1); Assert.assertEquals("updated records should be same", count, userMapper.update(entity, null)); ew = new QueryWrapper<>(); ew.eq("version", 1); Assert.assertEquals("No records found with version=1", 0, userMapper.selectCount(ew).intValue()); ew = new QueryWrapper<>(); ew.eq("version", 2); Assert.assertEquals("All records with version=1 should be updated to version=2", count, userMapper.selectCount(ew).intValue()); }

公共字段自动填充

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "operator", String.class, "Jetty");
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "operator", String.class, "Tom");
    }
}

逻辑删除

@Data
@Accessors(chain = true)
public class Common {

    private Long id;

    private String name;

	/**
	* 未删除1,删除0
	*/
    @TableLogic(delval = "0", value = "1")
    private Integer deleted;
}
@Data
@Accessors(chain = true)
public class Null1 {

    private Long id;

    private String name;

	/**
	* 未删除1,删除null
	*/
    @TableLogic(delval = "null", value = "1")
    private Integer deleted;
}
@Data
@Accessors(chain = true)
public class Null2 {

    private Long id;

    private String name;
	/**
	* 未删除null,删除now()
	*/
    @TableLogic(delval = "now()", value = "null")
    private LocalDateTime delTime;
}

枚举注入

mybatis-plus:
  type-enums-package: com.baomidou.mybatisplus.samples.enums.enums
  configuration:
    # 3.0.8之前版本问题默认将枚举注册为EnumOrdinalTypeHandler,这是错误的方式,默认是 org.apache.ibatis.type.EnumTypeHandler
    # 如果项目之中实体统一使用IEnum或注解的方式,可配置成 com.baomidou.mybatisplus.extension.handlers.EnumTypeHandler,也可省略上面的type-enums-package配置
    # 配置type-enums-package只对注解方式的枚举处理能提前加载缓存.
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
  • 方式一:枚举实现IEnum接口
public enum AgeEnum implements IEnum<Integer> {
  ONE(1, "一岁"),
  TWO(2, "二岁"),
  THREE(3, "三岁");

  private int value;
  private String desc;

  AgeEnum(final int value, final String desc) {
    this.value = value;
    this.desc = desc;
  }

  @Override
  public Integer getValue() {
    return value;
  }
}
  • 方式二:使用@EnumValue注解
@Getter
public enum GradeEnum {

    PRIMARY(1, "小学"),
    SECONDORY(2, "中学"),
    HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    @EnumValue
    private final int code;
    private final String descp;
}

你可能感兴趣的:(MyBatis,mybatis,java,数据库,mysql)