持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
前言
orm持久层层现在我们用的比较多的框架是MyBatis,自动生成dao层代码,简化了开发的复杂性,动态sql可以自由实现业务逻辑,一级、二级缓存、分页、批量操作,如果还觉得不够,还想偷懒的话,那么就可以用 MyBatis-Plus简称 MP是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus 可以不需要写SQL语句就能快速完成单表的操作,MyBatis-Plus的愿景就是成为 MyBatis 最好的搭档。
快速构建项目
1.导入MyBatis-Plus(baomidou)核心依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.5.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.5.6</version>
</dependency>
2.yml配置文件DB配置
spring:
cloud:
#配置数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/qns_bms_bill?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
username: root
password: root
3.实体类、mapper、mapper.xml通过Generator自动生成
public void run() {
Properties props = this.getProperties();
AutoGenerator mpg = new AutoGenerator();
GlobalConfig gc = new GlobalConfig();
String outputDir = this.getOutputDir();
String author = props.getProperty(“author”);
gc.setOutputDir(outputDir);
gc.setAuthor(author);
gc.setFileOverride(true);
gc.setOpen(false);
gc.setActiveRecord(false);
gc.setEnableCache(false);
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
gc.setMapperName(“%sMapper”);
gc.setXmlName(“%sMapper”);
gc.setServiceName(“%sService”);
gc.setServiceImplName(“%sServiceImpl”);
gc.setControllerName(“%sController”);
gc.setSwagger2(this.isSwagger2);
//定义生成的实体类中日期类型
gc.setDateType(DateType./ONLY_DATE/);
mpg.setGlobalConfig(gc);
DataSourceConfig dsc = new DataSourceConfig();
String driverName = Func./toStr/(this.driverName, props.getProperty(“spring.datasource.driver-class-name”));
if (StringUtil./containsAny/(driverName, new CharSequence[]{DbType./MYSQL/.getDb()})) {
dsc.setDbType(DbType./MYSQL/);
dsc.setTypeConvert(new MySqlTypeConvert());
} else if (StringUtil./containsAny/(driverName, new CharSequence[]{DbType./POSTGRE_SQL/.getDb()})) {
dsc.setDbType(DbType./POSTGRE_SQL/);
dsc.setTypeConvert(new PostgreSqlTypeConvert());
} else {
dsc.setDbType(DbType./ORACLE/);
dsc.setTypeConvert(new OracleTypeConvert());
}
dsc.setDriverName(driverName);
dsc.setUrl(Func./toStr/(this.url, props.getProperty(“spring.datasource.url”)));
dsc.setUsername(Func./toStr/(this.username, props.getProperty(“spring.datasource.username”)));
dsc.setPassword(Func./toStr/(this.password, props.getProperty(“spring.datasource.password”)));
mpg.setDataSource(dsc);
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy./underline_to_camel/);
strategy.setColumnNaming(NamingStrategy./underline_to_camel/);
strategy.setTablePrefix(this.tablePrefix);
if (this.includeTables.length > 0) {
strategy.setInclude(this.includeTables);
}
if (this.excludeTables.length > 0) {
strategy.setExclude(this.excludeTables);
}
if (this.hasSuperEntity) {
if (StringUtil./isNotBlank/(this.superEntityClass)) {
strategy.setSuperEntityClass(this.superEntityClass);
} else {
strategy.setSuperEntityClass(“org.springblade.core.mp.base.BaseEntity”);
}
strategy.setSuperEntityColumns(this.superEntityColumns);
if (StringUtil./isNotBlank/(this.superServiceClass)) {
strategy.setSuperServiceClass(this.superServiceClass);
} else {
strategy.setSuperServiceClass(“org.springblade.core.mp.base.BaseService”);
}
if (StringUtil./isNotBlank/(this.superServiceImplClass)) {
strategy.setSuperServiceImplClass(this.superServiceImplClass);
} else {
strategy.setSuperServiceImplClass(“org.springblade.core.mp.base.BaseServiceImpl”);
}
} else {
if (StringUtil./isNotBlank/(this.superServiceClass)) {
strategy.setSuperServiceClass(this.superServiceClass);
} else {
strategy.setSuperServiceClass(“com.baomidou.mybatisplus.extension.service.IService”);
}
if (StringUtil./isNotBlank/(this.superServiceImplClass)) {
strategy.setSuperServiceImplClass(this.superServiceImplClass);
} else {
strategy.setSuperServiceImplClass(“com.baomidou.mybatisplus.extension.service.impl.ServiceImpl”);
}
}
strategy.setSuperControllerClass(“org.springblade.core.boot.ctrl.BladeController”);
strategy.setEntityBuilderModel(false);
strategy.setEntityLombokModel(true);
strategy.setControllerMappingHyphenStyle(true);
mpg.setStrategy(strategy);
PackageConfig pc = new PackageConfig();
pc.setModuleName((String) null);
pc.setParent(this.packageName);
pc.setController(“controller”);
pc.setEntity(“entity”);
pc.setXml(“mapper”);
mpg.setPackageInfo(pc);
mpg.setCfg(this.getInjectionConfig());
mpg.execute();
}
Dao层,mapper接口
//**/
/ */
/ *//
public interface SupplierBillStatementMapper extends MyBaseMapper<SupplierBillStatement> {
//**/
/ * 自定义分页/
/ */
/ */*@param*/page/
/ */*@param*/supplierBillStatementDTO/
/ */*@return*
/*//
IPage<SupplierBillStatementVO> selectSupplierBillStatementPage(@Param(“page”) IPage page, @Param(“dto”) SupplierBillStatementDTO supplierBillStatementDTO);
}
注意:正常mapper继承的是BaseMapper ,所有的crud已经在BaseMapper里面简单实现,但是批量添加、更新还是没有去实现,所以在BaseMapper的基础上在封装了一层MyBaseMapper
我们的service实现类会去继承BaseServiceImpl,里面会去继承BaseMapper 封装批量添加、更新方法,但是在service层其实我们去调用dao层这样的写法更加规范,所以我在dao层去做基础封装。
public interface MyBaseMapper<T> extends BaseMapper<T> {
default QueryChainWrapper<T> queryChain() {
return new QueryChainWrapper<>(this);
}
default LambdaQueryChainWrapper<T> lambdaQueryChain() {
return new LambdaQueryChainWrapper<>(this);
}
default UpdateChainWrapper<T> updateChain() {
return new UpdateChainWrapper<>(this);
}
default LambdaUpdateChainWrapper<T> lambdaUpdateChain() {
return new LambdaUpdateChainWrapper<>(this);
}
//**/
/ * 批量插入/
/ */
/ */*@param*/entityList/
/ */*@return*
/*//
int insertBatchSomeColumn(List<T> entityList);
//**/
/ * 批量更新/
/ */
/ */*@param*/entity/
/ */*@return*
/*//
int alwaysUpdateSomeColumnById(@Param(Constants./ENTITY/) List<T> entity);
//**/
/ * 批量删除/
/ */
/ */*@param*/entity/
/ */*@return*
/*//
int deleteByIdWithFill(T entity);
//**/
/ */*@param*/id/
/ */*@return*
/*//
T findOne(Serializable id);
}
MybatisPlusConfig分页配置
@Configuration
public class MybatisPlusConfig {
//**/
/ * 分页插件拦截器/
/ *//
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
//**/
/ * 自定义Sql注入器/
/ *//
@Bean
public MySqlInjector sqlInjector() {
return new MySqlInjector();
}
}
同时mapper返回的resulType对象也需要IPage类去接收,实现自动分页。
4:、Wrappers 、lambdaQuery构造器的使用
实现Compare查询条件接口,接口方法对应mysql的查询拼接条件,可以使用
Lambda 语法使用 Wrapper,直接使用Wrapper构造器完成sql的编写在代码层解决问题,避免手写sql出现的错误。
启动类会去扫描mapper文件目录
@SpringCloudApplication
@MapperScan({“com.xxx.**.mapper.**”})
public class xxxApplication {
public static void main(String[] args) {
String appName = “xxxx”;
if(args.length>0){
for (String arg:args){
if (arg.contains(“xxxxx=“)){
appName = arg.replace(xxxxx=“,””).trim();
break;
}
}
}
BladeApplication./run/(appName, xxxApplication.class, args);
}
}
结果调用
创建controller入口调用
//**/
/ * 自定义分页 供应商账单表/
/ *//
@PostMapping(“/page”)
@ApiOperationSupport(order = 1)
@ApiOperation(value = “自定义分页”, notes = “传入supplierBillStatementDTO”)
public R<IPage<SupplierBillStatementVO>> page(@RequestBody SupplierBillStatementDTO supplierBillStatementDTO) {
/log/.info(“自定义分页 【入参】 page supplierBillStatementDTO={},query={}”, JSON./toJSONString/(supplierBillStatementDTO));
return R./data/(supplierBillStatementService.selectSupplierBillStatementPage(supplierBillStatementDTO, this.getCurrentUser(true)));
}
通过swagger调用controller暴露接口,返回查询结果。
总结
以上介绍的就是通过MyBatis-Plus快速进行curd开发的过程,这个过程我们基本都可以通过代码生成,可以大大增加我们的开发效率,使我们能拥有更多的时间去专注于service层业务逻辑的开发,当然框架底层的实现也是值得我们去深入研究的,我们不光得会用还要只其原理,更加充实我们的武器库,加油吧,骚年~