小言_互联网的博客

MyBatis-Plus

274人阅读  评论(0)




一、概述

MyBatis-Plus 为简化开发而生

类似作用的还有JPA 、 tk-mapper、MyBatisPlus

官网:https://mp.baomidou.com

MyBatis简化JDBC,MyBatis Plus简化 MyBatis。



特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作



框架结构





二、快速入门

以下代码直接来自官网

1、新建数据库表结构及数据

-- 新建表结构
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)
);


-- 新建表数据
DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2、在SpringBoot项目的基础上,引入相关依赖

<!--后期编写实体类时使用 jar包 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<!--MyBatisPlus jar包 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

<!--连接mysql的驱动 jar包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

3、编写代码

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
   
    
    //使用数据库id自增,此时数据库表的该字段一定要设置为自增
    @TableId(type = IdType.AUTO)
	private Long id;
	private String name;
	private Integer age;
	private String email;
}
//主要是继承BaseMapper接口,并且将他的范型设置为我们的参数
@Repository
public interface UserMapper extends BaseMapper<User> {
   
}

4、主启动类添加扫描包

@MapperScan("pers.mobian.mybatisplus.mapper")
@SpringBootApplication
public class TestspringbootApplication {
   

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

5、编写自带的测试类

@SpringBootTest
class TestspringbootApplicationTests {
   

	@Autowired
	private UserMapper userMapper;

	@Test
	void contextLoads() {
   
        //直接调用baseMapper中的方法。此处我们的构造条件为空
		List<User> users = userMapper.selectList(null);
		users.forEach(System.out::println);
	}
}


6、测试结果





三、日志文件的配置

在我们的aplication.properties添加相关的日志配置即可。

跟绝这个配置我们应该明白,这是MyBatis Plus为我们提供的日志实现接口。直接将MyBatis的StdOutImpl日志配置使用

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl


至此我们就能够看到我们sql执行的细节了

为方便后面的学习测试,请务必将执行的细节打印出来






四、CRUD测试

4.1、insert新增数据

@Test
public void testInsert() {
   
    User user = new User();
    user.setName("mobian");
    user.setAge(13);
    user.setEmail("7099148@qq.com");

    //依然调用的是我们BaseMapper接口中的方法
    int result = userMapper.insert(user); // 帮我们自动生成id

    System.out.println(result); // 受影响的行数
    System.out.println(user);   // 新增的对象会自动回填
}

由于数据库表user的id字段为主键,所以我们在不指定主键的情况下,就会使用默认的主键生成策略(雪花算法)



4.2、delete删除数据

测试用例为三种不同的删除数据的方式

// 测试删除:根据id删除数据
@Test
public void testDelete() {
   
    // 删除id为1的数据
    int result = userMapper.deleteById(1); 
    
    // 受影响的行数
    System.out.println(result); 
}

// 测试删除:批量删除数据
@Test
public void testBatchDelete() {
   
    // 删除id为2,3,4的数据,传入参数为一个集合
    int i = userMapper.deleteBatchIds(Arrays.asList(2, 3, 4));
    
    // 受影响的行数
    System.out.println(i);
}

//测试删除:构造条件map删除数据
@Test
public void testDeleteByMap() {
   
    HashMap<String, Object> map = new HashMap<>();

    map.put("name","Billie");
    map.put("age",12);

    //删除name = Billie且age = 12的数据
    int i = userMapper.deleteByMap(map);
    System.out.println(i);
}



4.3、update更新数据

根据id更新

或者根据条件构造器更新数据

// 根据主键id,更新表中的数据
@Test
public void testUpdate() {
   
    User user = new User();
    user.setId(1L);
    user.setName("nihao mobian");
    user.setEmail("7099148@qq.com");
    //传入新对象,根据id进行修改
    int result = userMapper.updateById(user); 

    System.out.println(result); // 受影响的行数
    System.out.println(user);   // 新增的对象会自动回填
}

//直接更新所有的数据
@Test
public void testUpdate3() {
   
    User user = new User();
    user.setAge(27);
    user.setName("mobian");
    user.setEmail("7099148@qq.com");
    int result = userMapper.update(user,null);
    System.out.println(result); // 受影响的行数
    System.out.println(user);   // 新增的对象会自动回填
}

如果后面的wrapper构造器设置为null,类似于update的SQL语句的where过滤条件为空。

根据打印的SQL可以看出,是更新了所有的数据



4.4、select查询数据

//测试简单查询
@Test
public void testSelectById(){
   
    User user = userMapper.selectById(1L);
    System.out.println(user);
}


//测试批量查询
@Test
public void testSelectBatch(){
   
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    users.forEach(System.out::println);
}


//测试条件封装为map查询
@Test
public void testSelctByMap(){
   
    HashMap<String, Object> map = new HashMap<>();

    map.put("name","mobian");
    map.put("age",111);

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






五、其他操作

5.1、主键生成策略

MyBatis-Plus可以根据我们配置的策略,选择数据记录的主键字段以何种方式生成

雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味 着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯 一!

// 在数据库设置了主键自增的基础上,遵循数据库主键的生成策略,即主键自增
@TableId(type = IdType.AUTO)
private Long id;

主键生成策略的配置方法有:

@Getter
public enum IdType {
   
    /**
     * 数据库ID自增
     * 该类型请确保数据库设置了 ID自增 否则无效
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
     */
    NONE(1),
    /**
     * 用户输入ID
     * 该类型可以通过自己注册自动填充插件进行填充
     */
    INPUT(2),

    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 分配ID (主键类型为number或string),
     * 默认实现类(雪花算法)
     * @since 3.3.0
     */
    ASSIGN_ID(3),
    /**
     * 分配UUID (主键类型为 string)
     * 默认实现类(UUID.replace("-",""))
     */
    ASSIGN_UUID(4),
    /**
     * @deprecated 3.3.0 please use 
     */
    @Deprecated
    ID_WORKER(3),
    /**
     * @deprecated 3.3.0 please use 
     */
    @Deprecated
    ID_WORKER_STR(3),
    /**
     * @deprecated 3.3.0 please use 
     */
    @Deprecated
    UUID(4);

    private final int key;
    IdType(int key) {
   
        this.key = key;
    }
}

我测试MyBatis-Plus版本为3.4.2,在3.3.0版本中,部分枚举值已经被标记为过期。在使用雪花算法和UUID做主键策略时,注意新版枚举类型的变化。



5.2、自动填充值(日期)

我们希望添加和修改数据的时候能够自动更新相关的字段(创建时间和修改时间)

测试步骤分为三步:

1、第一步

实体类和数据库字段分别添加对应属性和字段。并且添加对应的TableField标识,创建时间在新增的时候修改,更新时间在插入和修改的时候修改。

@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

2、第二步

添加对应的修改策略。

新建一个Handler包,新建一个Handler类,实现MetaObjectHandler接口,重写对应的更新和插入方法。

@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
   
	@Override
	public void insertFill(MetaObject metaObject) {
   
		//使用插入注解的会处理的方法
		log.info("执行到了插入方法...");
		
		this.setFieldValByName("createTime", new Date(), metaObject);
		this.setFieldValByName("updateTime", new Date(), metaObject);

	}

	@Override
	public void updateFill(MetaObject metaObject) {
   
		//使用更新操作的会处理的方法
		log.info("执行到了更新方法...");

		this.setFieldValByName("updateTime", new Date(), metaObject);
	}
}

3、第三步

编写测试用例

// 测试插入数据时,创建时间和修改时间是否会自动添加
@Test
public void testInsert1() {
   
    User user = new User();
    user.setId(666L);
    user.setName("999");
    user.setEmail("67157@qq.com");

    int result = userMapper.insert(user); 
}


// 测试修改数据时,修改时间字段的数据是否会修改
@Test
public void test() {
   
    User user = new User();
    user.setId(666L);
    user.setName("222");
    
    int result = userMapper.updateById(user);
}



5.3、实现乐观锁

使用MyBatis-Plus实现乐观锁

1、第一步

实体类和数据库字段分别添加对应属性和字段。数据库的version字段可以给出一个默认值1,实体类属性添加@Vsersion注解

@Version
private Integer version;

2、第二步

新建一个config包,新建一个配置类。

新版本的MyBatis-Plus使用责任链的形式,替代了老版本的添加一个插件配置一个Bean的方法,这在后面处理分页是还会体现。

@Configuration
@EnableTransactionManagement
@MapperScan("pers.mobian.mybatisplus.mapper")
public class MybatisPlusConfig {
   
    
	@Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
		MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

		mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
		return mybatisPlusInterceptor;
	}
}

3、第三步

编写测试用例

//测试乐观锁
@Test
public void testVersionLock() {
   
    User user = userMapper.selectById(33L);

    user.setName("mobian");
    user.setEmail("2566148@qq.com");

    int i = userMapper.updateById(user);
    System.out.println(i);
}

当我们看到where后面除了跟id条件之外,还有version字段进行过滤时,就代表测试成功。查看数据库version数据自动+1




5.4、分页插件

使用MyBatis-Plus实现分页操作

1、第一步

编写对应的config,文件的目录结构与乐观锁的的目录结构相同。前文已经说到,分页与乐观锁的实现类似(新老版本配置方式有出入)

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

    // 注释了4.7中的乐观锁实现
    //mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    
    // 配置分页操作
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return mybatisPlusInterceptor;
}

2、第二步

编写测试用例

//测试分页查询
@Test
public void testSelectLimit() {
   

    // 参数一:当前页
    // 参数二:页面大小
    Page<User> userPage = new Page<>(1, 3);
    userMapper.selectPage(userPage, null);

    userPage.getRecords().forEach(System.out::println);
}

当打印的SQL中,含有limit参数时,代表我们的分页操作成功



5.5、逻辑删除

使用MyBatis-Plus实现逻辑删除操作

第一步

实体类和数据库字段分别添加对应属性和字段。

@TableLogic
private Integer deleted;

第二步

修改properties配置文件

#删除值为1
mybatis-plus.global-config.db-config.logic-delete-value=1

#未删除值为0
mybatis-plus.global-config.db-config.logic-not-delete-value=0

第三步

编写测试用例

//测试逻辑删除
@Test
public void test1() {
   
    User user = new User();
    user.setId(33L);
    userMapper.deleteById(user.getId());
}

根据其打印的SQL可以看出,此次的删除操作本质上是使用了修改操作,且修改方式根据我们配置的方式进行修改(由0变为1)






六、条件构造器(重点)

仅含有部分测试用例

1、测试like和isNotNull(等同于SQL中的like和is not null )

@Test
public void testSelect2() {
   

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
            .isNotNull("create_time")
            .like("name", "mo");

    userMapper.selectList(wrapper).forEach(System.out::println);
}

打印SQL

SELECT 
	id,
	name,
	age,
	email,
	create_time,
	update_time,
	version,
	deleted 
FROM user 

WHERE (create_time IS NOT NULL 
       AND 
       name LIKE ?)

-- 参数值
Parameters:%mo%(String)



2、测试between和子查询SQL(等同于SQL中的between和 in( xxx ))

@Test
public void testSelect2() {
   

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper
            .between("id",1,100)
    .inSql("age","select age from user where age > 20");

    userMapper.selectList(wrapper).forEach(System.out::println);
}

控制台打印的SQL

SELECT 
	id,
	name,
	age,email,
	create_time,
	update_time,
	version,
	deleted 
FROM user 
WHERE (id BETWEEN ? AND ? 
       AND 
       age IN (select age from user where age > 20))

-- 参数值
Parameters: 1(Integer), 100(Integer)



3、下列测试案例参照官网手册

更详情讲解,请参考官方文档






七、代码生成器

此功能需要引入两个maven依赖

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

测试代码

public class CodeConfig {
   

	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("默辨");
		gc.setOpen(false);
		gc.setFileOverride(false); // 是否覆盖
		gc.setServiceName("%sService"); // 去Service的I前缀
		gc.setIdType(IdType.AUTO); //设置生成的主键策略
		gc.setDateType(DateType.ONLY_DATE);//设置数据库时间类型的映射策略
		gc.setSwagger2(true); //设置是否开启swagger
		mpg.setGlobalConfig(gc);


		// 2、数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		dsc.setUrl("jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
		dsc.setDriverName("com.mysql.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.mobian");
		pc.setEntity("pojo");
		pc.setMapper("mapper");
		pc.setService("service");
		pc.setController("controller");
		mpg.setPackageInfo(pc);

		// 4、策略配置
		StrategyConfig strategy = new StrategyConfig();
		strategy.setInclude("product"); // 设置要映射的表名
		strategy.setNaming(NamingStrategy.underline_to_camel);
		strategy.setColumnNaming(NamingStrategy.underline_to_camel);
		strategy.setEntityLombokModel(true); // 自动lombok;
		strategy.setLogicDeleteFieldName("deleted");


		// 4.1、自动填充配置
		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);


		// 4.2、乐观锁配置
		strategy.setVersionFieldName("version");


		strategy.setRestControllerStyle(true);
		strategy.setControllerMappingHyphenStyle(true); //驼峰转连字符
		mpg.setStrategy(strategy);

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



生成的代码结构如图。

可以将该测试代码直接复制到自己的项目中,用于生成相关的目录结构,提高开发效率


转载:https://blog.csdn.net/qq_44377709/article/details/117111651
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场