SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

前言

本章节开始介绍数据访问方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的ORM框架是很有必要的。目前,绝大部分公司都选择MyBatis框架作为底层数据库持久化框架。

多说几句

看着现在Mybatis框架的大行其道,让我不禁想起,大学时期,当时还是hibernate的时代,现在基本已经忘记了。而当时,Mybatis的前身iBatis还在书中的某个章节出现过。当时大学老师的意思是:目前国内基本没有使用iBatis的公司,所以这一章节略过,略,过。。。现在对这个还记忆犹新,看着现在Mybatis大行其道,不禁令人唏嘘呀。

Mybatis-Plus

Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官方网站:http://mp.baomidou.com

简单来说,Mybatis-Plus是Mybatis的增强工具包,其简化了CRUD操作,提供了代码生成器,强大的条件构造器(这是我最喜欢的一个),同时内置了多个实用插件:标配的分页插件、性能分析插件、全局拦截插件等。使得开发过程中,基本的范式代码都一句话解决了,省去了很多重复的操作(程序猿存在的意义呢,说好的让我们搬砖呢!)。

SpringBoot集成

这里选用的mybatis-plus版本为:2.1.9,
mybatisplus-spring-boot-starter版本为:1.0.5。
对应Mybatis版本为:3.4.5

0. 这里以user表为例子,数据库为mysql

DROP TABLE IF EXISTS `user`; 
CREATE TABLE `user` ( 
  `id` bigint(20) DEFAULT NULL COMMENT '唯一标示', 
  `code` varchar(20) DEFAULT NULL COMMENT '编码', 
  `name` varchar(64) DEFAULT NULL COMMENT '名称', 
  `status` char(1) DEFAULT '1' COMMENT '状态 1启用 0 停用', 
  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 
  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间' 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1. pom依赖:

 <!--mybatis plus --> 
<dependency> 
	<groupId>com.baomidou</groupId> 
	<artifactId>mybatisplus-spring-boot-starter</artifactId> 
	<version>1.0.5</version> 
</dependency> 
<dependency> 
	<groupId>com.baomidou</groupId> 
	<artifactId>mybatis-plus</artifactId> 
	<version>2.1.9</version> 
</dependency>

2. 配置文件([email protected]ation配置文件进行,详见官网)
spring-mybatis.xml

 

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" 
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 
 
    <!--创建jdbc数据源 这里直接使用阿里的druid数据库连接池 --> 
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> 
        <property name="driverClassName" value="${mysql.driver}"/> 
        <property name="url" value="${mysql.url}"/> 
        <property name="username" value="${mysql.username}"/> 
        <property name="password" value="${mysql.password}"/> 
        <!-- 初始化连接大小 --> 
        <property name="initialSize" value="0"/> 
        <!-- 连接池最大使用连接数量 --> 
        <property name="maxActive" value="20"/> 
        <!-- 连接池最大空闲 --> 
        <property name="maxIdle" value="20"/> 
        <!-- 连接池最小空闲 --> 
        <property name="minIdle" value="0"/> 
        <!-- 获取连接最大等待时间 --> 
        <property name="maxWait" value="60000"/> 
 
        <property name="validationQuery" value="${validationQuery}"/> 
        <property name="testOnBorrow" value="false"/> 
        <property name="testOnReturn" value="false"/> 
        <property name="testWhileIdle" value="true"/> 
 
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> 
        <property name="timeBetweenEvictionRunsMillis" value="60000"/> 
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> 
        <property name="minEvictableIdleTimeMillis" value="25200000"/> 
 
        <!-- 打开removeAbandoned功能 --> 
        <property name="removeAbandoned" value="true"/> 
        <!-- 1800秒,也就是30分钟 --> 
        <property name="removeAbandonedTimeout" value="1800"/> 
        <!-- 关闭abanded连接时输出错误日志 --> 
        <property name="logAbandoned" value="true"/> 
 
        <!-- 监控数据库 --> 
        <property name="filters" value="mergeStat"/> 
    </bean> 
 
    <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> 
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="dataSource" /> 
    </bean> 
 
    <!-- 可通过注解控制事务 --> 
    <tx:annotation-driven transaction-manager="transactionManager"/> 
 
    <!--mybatis--> 
    <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"> 
        <property name="dataSource" ref="dataSource"/> 
		<!-- 自动扫描mapper.xml文件,支持通配符 --> 
        <property name="mapperLocations" value="classpath:mapper/**/*.xml"/> 
		<!-- 配置文件,比如参数配置(是否启动驼峰等)、插件配置等 --> 
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/> 
		<!-- 启用别名,这样就无需写全路径类名了,具体可自行查阅资料 --> 
        <property name="typeAliasesPackage" value="cn.lqdev.learning.springboot.chapter9.biz.entity"/> 
        <!-- MP 全局配置注入 --> 
        <property name="globalConfig" ref="globalConfig"/> 
    </bean> 
    <bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> 
        <!-- 
            AUTO->`0`("数据库ID自增")QW 
             INPUT->`1`(用户输入ID") 
            ID_WORKER->`2`("全局唯一ID") 
            UUID->`3`("全局唯一ID") 
        --> 
        <property name="idType" value="3" /> 
    </bean> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
	<!-- 自动扫描包路径,接口自动注册为一个bean类 --> 
        <property name="basePackage" value="cn.lqdev.learning.springboot.chapter9.biz.dao"/> 
    </bean> 
 
</beans>

3. 编写启动类,应用启动时自动加载配置xml文件

/** 
 *  mybatisPlus 配置类,使其加载配置文件 
 * @author oKong 
 * 
 */ 
@Configuration 
@ImportResource(locations = {"classpath:/mybatis/spring-mybatis.xml"}) 
[email protected]("cn.lqdev.learning.springboot.chapter9.biz.dao") 
[email protected] 
public class MybatisPlusConfig { 
 
}

至此,mybatis-plus就配置完成了,接下来,利用代码生成器一次性创建所需的dao、mapper、通用CRUDservice类。

4. 编写代码生成器类

由于生成器依赖velocity模版引擎,故需要加入依赖:

<dependency> 
	<groupId>org.apache.velocity</groupId> 
	<artifactId>velocity-engine-core</artifactId> 
	<version>2.0</version> 
	<scope>test</scope> 
</dependency>

MysqlGenerator,此类较长,相关配置可根据实际情况信息修改替换。

public class MysqlGenerator { 
 
	private static final String PACKAGE_NAME = "cn.lqdev.learning.springboot.chapter9"; 
	private static final String MODULE_NAME = "biz"; 
	private static final String OUT_PATH = "D://develop//code"; 
	private static final String AUTHOR = "oKong"; 
 
	private static final String DRIVER = "com.mysql.jdbc.Driver"; 
	private static final String URL = "jdbc:mysql://127.0.0.1:3306/learning?useUnicode=true&characterEncoding=UTF-8"; 
	private static final String USER_NAME = "root"; 
	private static final String PASSWORD = "123456"; 
 
	/** 
	 * <p> 
	 * MySQL 生成演示 
	 * </p> 
	 */ 
	public static void main(String[] args) { 
		// 自定义需要填充的字段 
		List<TableFill> tableFillList = new ArrayList<TableFill>(); 
 
		// 代码生成器 
		AutoGenerator mpg = new AutoGenerator().setGlobalConfig( 
				// 全局配置 
				new GlobalConfig().setOutputDir(OUT_PATH)// 输出目录 
						.setFileOverride(true)// 是否覆盖文件 
						.setActiveRecord(true)// 开启 activeRecord 模式 
						.setEnableCache(false)// XML 二级缓存 
						.setBaseResultMap(false)// XML ResultMap 
						.setBaseColumnList(true)// XML columList 
						.setAuthor(AUTHOR) 
						// 自定义文件命名,注意 %s 会自动填充表实体属性! 
						.setXmlName("%sMapper").setMapperName("%sDao") 
		// .setServiceName("MP%sService") 
		// .setServiceImplName("%sServiceDiy") 
		// .setControllerName("%sAction") 
		).setDataSource( 
				// 数据源配置 
				new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型 
						.setTypeConvert(new MySqlTypeConvert() { 
							// 自定义数据库表字段类型转换【可选】 
							@Override 
							public DbColumnType processTypeConvert(String fieldType) { 
								System.out.println("转换类型:" + fieldType); 
								// if ( fieldType.toLowerCase().contains( "tinyint" ) ) { 
								// return DbColumnType.BOOLEAN; 
								// } 
								return super.processTypeConvert(fieldType); 
							} 
						}).setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL)) 
				.setStrategy( 
						// 策略配置 
						new StrategyConfig() 
								// .setCapitalMode(true)// 全局大写命名 
								.setDbColumnUnderline(true)// 全局下划线命名 
								// .setTablePrefix(new String[]{"unionpay_"})// 此处可以修改为您的表前缀 
								.setNaming(NamingStrategy.underline_to_camel)// 表名生成策略 
								// .setInclude(new String[] {"citycode_org"}) // 需要生成的表 
								// .setExclude(new String[]{"test"}) // 排除生成的表 
								// 自定义实体,公共字段 
								// .setSuperEntityColumns(new String[]{"test_id"}) 
								.setTableFillList(tableFillList) 
								// 自定义实体父类 
								// .setSuperEntityClass("com.baomidou.demo.common.base.BsBaseEntity") 
								// // 自定义 mapper 父类 
								// .setSuperMapperClass("com.baomidou.demo.common.base.BsBaseMapper") 
								// // 自定义 service 父类 
								// .setSuperServiceClass("com.baomidou.demo.common.base.BsBaseService") 
								// // 自定义 service 实现类父类 
								// .setSuperServiceImplClass("com.baomidou.demo.common.base.BsBaseServiceImpl") 
								// 自定义 controller 父类 
								// .setSuperControllerClass("com.baomidou.demo.TestController") 
								// 【实体】是否生成字段常量(默认 false) 
								// public static final String ID = "test_id"; 
								.setEntityColumnConstant(true) 
								// 【实体】是否为构建者模型(默认 false) 
								// public User setName(String name) {this.name = name; return this;} 
								.setEntityBuilderModel(true) 
								// 【实体】是否为lombok模型(默认 false)<a href="https://projectlombok.org/">document</a> 
								.setEntityLombokModel(true) 
				// Boolean类型字段是否移除is前缀处理 
				// .setEntityBooleanColumnRemoveIsPrefix(true) 
				// .setRestControllerStyle(true) 
				// .setControllerMappingHyphenStyle(true) 
				).setPackageInfo( 
						// 包配置 
						new PackageConfig().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)// 自定义包路径 
								.setController("controller")// 这里是控制器包名,默认 web 
								.setXml("mapper").setMapper("dao") 
 
				).setCfg( 
						// 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值 
						new InjectionConfig() { 
							@Override 
							public void initMap() { 
								Map<String, Object> map = new HashMap<String, Object>(); 
								map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp"); 
								this.setMap(map); 
							} 
						}.setFileOutConfigList( 
								Collections.<FileOutConfig>singletonList(new FileOutConfig("/templates/mapper.xml.vm") { 
									// 自定义输出文件目录 
									@Override 
									public String outputFile(TableInfo tableInfo) { 
										return OUT_PATH + "/xml/" + tableInfo.getEntityName() + "Mapper.xml"; 
									} 
								}))) 
				.setTemplate( 
						// 关闭默认 xml 生成,调整生成 至 根目录 
						new TemplateConfig().setXml(null) 
		// 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy 
		// 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置: 
		// .setController("..."); 
		// .setEntity("..."); 
		// .setMapper("..."); 
		// .setXml("..."); 
		// .setService("..."); 
		// .setServiceImpl("..."); 
		); 
 
		// 执行生成 
		mpg.execute(); 
	} 
 
}

运行后即可,省了多少事!

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

简单实例

简单演示下增删改查及分页的使用。

使用分页时,mybatis-config.xml需要加入分页插件:PerformanceInterceptor

<plugins> 
  <!-- 分页插件配置 --> 
  <plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin> 
</plugins>

编写控制层

/** 
 * 用户控制层 简单演示增删改查及分页 
 * @author oKong 
 * 
 */ 
@RestController 
@RequestMapping("/user") 
public class UserController { 
 
	@Autowired 
	IUserService userService; 
 
	@PostMapping("add") 
    //正常业务时, 需要在user类里面进行事务控制,控制层一般不进行业务控制的。 
	[email protected](rollbackFor = Exception.class) 
	public Map<String,String> addUser(@Valid @RequestBody UserReq userReq){ 
 
		User user = new User(); 
		user.setCode(userReq.getCode()); 
		user.setName(userReq.getName()); 
		//由于设置了主键策略 id可不用赋值 会自动生成 
		//user.setId(0L); 
		userService.insert(user); 
		Map<String,String> result = new HashMap<String,String>(); 
		result.put("respCode", "01"); 
		result.put("respMsg", "新增成功"); 
		//事务测试 
		//System.out.println(1/0); 
		return result; 
	} 
 
	@PostMapping("update") 
	public Map<String,String> updateUser(@Valid @RequestBody UserReq userReq){ 
 
		if(userReq.getId() == null || "".equals(userReq.getId())) { 
			throw new CommonException("0000", "更新时ID不能为空"); 
		} 
		User user = new User(); 
		user.setCode(userReq.getCode()); 
		user.setName(userReq.getName()); 
		user.setId(Long.parseLong(userReq.getId()));		 
		userService.updateById(user); 
		Map<String,String> result = new HashMap<String,String>(); 
		result.put("respCode", "01"); 
		result.put("respMsg", "更新成功"); 
		return result; 
	} 
 
	@GetMapping("/get/{id}") 
	public Map<String,Object> getUser(@PathVariable("id") String id){ 
		//查询 
		User user = userService.selectById(id); 
		if(user == null) { 
			throw new CommonException("0001", "用户ID:" + id + ",未找到"); 
		} 
		UserResp resp = UserResp.builder() 
				.id(user.getId().toString()) 
				.code(user.getCode()) 
				.name(user.getName()) 
				.status(user.getStatus()) 
				.build(); 
		Map<String,Object> result = new HashMap<String,Object>(); 
		result.put("respCode", "01"); 
		result.put("respMsg", "成功"); 
		result.put("data", resp); 
		return result; 
	} 
 
	@GetMapping("/page") 
	public Map<String,Object> pageUser(int current, int size){ 
		//分页 
		Page<User> page = new Page<>(current, size); 
		Map<String,Object> result = new HashMap<String,Object>(); 
		result.put("respCode", "01"); 
		result.put("respMsg", "成功"); 
		result.put("data", userService.selectPage(page)); 
		return result; 
	}		 
}

启动应用后,使用postman依次访问对应的url地址即可。

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

数据库:

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

分页

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

由于配置了分析插件,控制台会输出执行的sql语句

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

其他的就不一一贴图了。

关于事务

正常情况下,[email protected],事务相关的此章节不进行阐述,之后有机会会专门拿一个章节来说明下。

示例中为了方便,[email protected],正式开发过程中,强烈建议在服务层进行业务控制,控制层一般上是进行逻辑判断的!

实体对象字段为枚举类

可能在实际开发中,大家会碰到,为了方便,一些类型、状态字段会编写成枚举类型,比如启用状态:DISABLE(“0”),ENABLE(“1”)。此时可通过配置typeHandlers进行自定义类型的处理,这里简单以EnumOrdinalTypeHandler(存储enum类里的序号值)进行示例,当然也可根据需要进行自定义处理器的编写,比如编写一个通用的枚举转换器等,其他相关知识点,大家可自行谷歌。

StatusEnums

public enum StatusEnum { 
 
	DISABLE, 
	ENABLE; 
 
}

将user对象修改成枚举类型

/** 
 * 状态1 启用 0 停用 
 */ 
private StatusEnum status;

配置文件mybatis-config.xml加入处理类

<typeHandlers> 
   <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" 
     javaType="cn.lqdev.learning.springboot.chapter9.biz.entity.StatusEnum"/> 
</typeHandlers>

之后就会自动进行转换了。大家可下载示例,进行实际操作下。

SpringBoot | 第九章:Mybatis-plus的集成和使用详解编程语言

总结

本章节主要是对Mybatis-plus的集成和简单使用进行了说明,详细的用法,可到官网查看,官网有详细的使用指南,这里就不班门弄斧了。至此,对于一般的开发需求基本上都可以满足了。接下来的章节会重点讲解其他配套工具的使用,敬请期待!

最后

目前互联网上很多大佬都有springboot系列教程,如有雷同,请多多包涵了。本文是作者在电脑前一字一句敲的,每一步都是实践的。若文中有所错误之处,还望提出,谢谢。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/14082.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论