上一篇:springboot2.2.X手册:构建多元化的API接口,我们这样子设计
源码请关注后私信
mybaits,现在很多公司都会用,替换掉hibernate,但是写SQL确实麻烦,比较痛苦。
mybatis plus是国内开源的很好的一个工具,号称为简化开发而生
1、只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
2、只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。
3、热加载、代码生成、分页、性能分析等功能一应俱全。
当前最新版本
com.baomidou
mybatis-plus
3.3.1.tmp
org.springframework.boot
spring-boot-autoconfigure
org.springframework.boot
spring-boot-starter-web
org.mybatis
mybatis
3.5.4
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.2
com.alibaba
druid-spring-boot-starter
1.1.21
mysql
mysql-connector-java
com.baomidou
mybatis-plus-boot-starter
3.3.1.tmp
/**
* 自定义ID生成器
* @author:溪云阁
* @date:2020年5月10日
*/
@Component
public class CustomIdGenerator implements IdentifierGenerator {
/**
* 获取自定义id
* @author 溪云阁
* @param entity
* @return 返回数据库的主键ID
*/
@Override
public Number nextId(Object entity) {
// 采用雪花算法获取id,时间回拨会存在重复,这里用随机数来减少重复的概率
final Snowflake snowflake = IdUtil.createSnowflake(1, (int) (Math.random() * 20 + 1));
return snowflake.nextId();
}
}
package com.module.boots.mp;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import lombok.extern.slf4j.Slf4j;
/**
* 数据源配置
* @author:溪云阁
* @date:2020年5月10日
*/
@ServletComponentScan
@Configuration
@Slf4j
public class DataSourceConfig {
@Value("${boots.datasource.druid.url}")
private String url;
@Value("${boots.datasource.druid.username}")
private String username;
@Value("${boots.datasource.druid.password}")
private String password;
@Value("${boots.datasource.druid.initial-size:1}")
private int initialSize;
@Value("${boots.datasource.druid.max-active:30}")
private int maxActive;
@Value("${boots.datasource.druid.min-idle:3}")
private int minIdle;
@Value("${boots.datasource.druid.max-wait:60000}")
private int maxWait;
@Value("${boots.datasource.druid.time-between-eviction-runs-millis:60000}")
private int timeBetweenEvictionRunsMillis;
@Value("${boots.datasource.druid.min-evictable-idle-time-millis:300000}")
private int minEvictableIdleTimeMillis;
@Value("${boots.datasource.druid.validation-query:select 'x'}")
private String validationQuery;
@Value("${boots.datasource.druid.test-while-idle:true}")
private boolean testWhileIdle;
@Value("${boots.datasource.druid.test-on-borrow:false}")
private boolean testOnBorrow;
@Value("${boots.datasource.druid.test-on-return:false}")
private boolean testOnReturn;
@Value("${boots.datasource.druid.pool-prepared-statements:true}")
private boolean poolPreparedStatements;
@Value("${boots.datasource.druid.max-pool-prepared-statement-per-connection-size:20}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${boots.datasource.druid.filter-class-names:stat,slf4j}")
private String filters;
@Value("${boots.datasource.druid.connection-properties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000}")
private String connectionProperties = "";
/**
* 数据源配置
* @author 溪云阁
* @return DataSource
*/
@Bean(initMethod = "init", destroyMethod = "close")
@Primary
public DataSource dataSource() {
DruidDataSource datasource = null;
try {
datasource = new DruidDataSource();
datasource.setDriverClassName("com.p6spy.engine.spy.P6SpyDriver");
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
// 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
datasource.setInitialSize(initialSize);
// 最小连接池数量
datasource.setMinIdle(minIdle);
// 最大连接池数量
datasource.setMaxActive(maxActive);
// 配置获取连接等待超时的时间
datasource.setMaxWait(maxWait);
// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
// 配置一个连接在池中最小生存的时间,单位是毫秒
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
// 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'.
// 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
datasource.setValidationQuery(validationQuery);
// 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
datasource.setTestWhileIdle(testWhileIdle);
// 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
datasource.setTestOnBorrow(testOnBorrow);
// 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
datasource.setTestOnReturn(testOnReturn);
// 打开PSCache,并且指定每个连接上PSCache的大小
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
// 配置监控统计拦截的filters,去掉后监控界面sql无法统计:监控统计用的filter:stat;日志用的filter:log4j;防御sql注入的filter:wall'wall'用于防火墙
datasource.setFilters(filters);
// 通过connectProperties属性来打开mergeSql功能;慢SQL记录
datasource.setConnectionProperties(connectionProperties);
}
catch (final SQLException e) {
log.error("数据初始化中出现问题", e);
}
return datasource;
}
/**
* druid拦截及账号配置
* @author 溪云阁
* @return ServletRegistrationBean
*/
@Bean
public ServletRegistrationBean druidServlet() {
final ServletRegistrationBean reg = new ServletRegistrationBean<>();
reg.setServlet(new StatViewServlet());
// 添加映射路径
reg.addUrlMappings("/druid/*");
// 白名单
reg.addInitParameter("allow", "");
// 添加控制台管理用户
reg.addInitParameter("loginUsername", "admin");
reg.addInitParameter("loginPassword", "admin@123");
reg.addInitParameter("resetEnable", "true");
reg.addInitParameter("logSlowSql", "true");
return reg;
}
/**
* 过滤资源配置
* @author 溪云阁
* @return FilterRegistrationBean
*/
@Bean
public FilterRegistrationBean filterRegistrationBean() {
final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
filterRegistrationBean.addInitParameter("DruidWebStatFilter", "/*");
return filterRegistrationBean;
}
}
/**
* MybatisPlus配置
* @author:溪云阁
* @date:2020年5月10日
*/
@MapperScan({ "com.boots.**.business.**.dao" })
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {
@Autowired
private DataSource dataSource;
@Autowired
private CustomIdGenerator customIdGenerator;
// 数据库查询后获取的对象存放目录,包含单表查询对象及多表查询对象
private final static String typeAliasPackage = "com.boots.**.business.**.model";
// 数据库查询的xml文件配置
private final static String mapperPath = "classpath:com/boots/**/business/**/dao/*Mapper.xml";
/**
* 添加分页插件支持
* @author 溪云阁
* @return PaginationInterceptor
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
final PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
/**
* mybatisplus数据层配置
* @author 溪云阁
* @return DbConfig
*/
@Bean
public DbConfig dbConfig() {
final DbConfig dbConfig = new DbConfig();
// 设置ID的生成规则
dbConfig.setIdType(IdType.ASSIGN_ID);
// 设置表名是否使用下划线命名
dbConfig.setTableUnderline(true);
// 字段插入非空判断
dbConfig.setInsertStrategy(FieldStrategy.NOT_EMPTY);
// 字段更新非空判断
dbConfig.setUpdateStrategy(FieldStrategy.NOT_EMPTY);
// 字段查询非空判断
dbConfig.setSelectStrategy(FieldStrategy.NOT_EMPTY);
return dbConfig;
}
/**
* mybatisplus全局配置
* @author 溪云阁
* @param dbConfig
* @return GlobalConfig
*/
@Bean
public GlobalConfig globalConfig(DbConfig dbConfig) {
final GlobalConfig globalConfig = new GlobalConfig();
// 设置mybatisplus数据层配置
globalConfig.setDbConfig(dbConfig);
// 初始化SqlRunner
globalConfig.setEnableSqlRunner(true);
// 设置自定义主键ID的生成方式
globalConfig.setIdentifierGenerator(customIdGenerator);
return globalConfig;
}
/**
* 配置mybatis
* @author 溪云阁
* @return MybatisConfiguration
*/
@Bean
public MybatisConfiguration mybatisConfiguration() {
final MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
// 设置为XML语言驱动
mybatisConfiguration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
// 设置数据库字段值映射方式,例如:updatedId在进行DB操作的时候会被自动解析为updated_id
mybatisConfiguration.setMapUnderscoreToCamelCase(true);
// 开启Mybatis的二级缓存
mybatisConfiguration.setCacheEnabled(true);
// 当查询的返回一行都是null的结果时,MyBatis会帮忙填充一个所有属性都是null的对象
mybatisConfiguration.setCallSettersOnNulls(true);
return mybatisConfiguration;
}
/**
* 配置mybatis连接的session工厂
* @author 溪云阁
* @param globalConfig
* @param mybatisConfiguration
* @param paginationInterceptor
* @return
* @throws Exception MybatisSqlSessionFactoryBean
*/
@Bean
public MybatisSqlSessionFactoryBean sqlSessionFactory(GlobalConfig globalConfig,
MybatisConfiguration mybatisConfiguration, PaginationInterceptor paginationInterceptor) throws Exception {
final MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
// 设置数据源
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置XML的映射路径
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperPath));
// 设置实体类扫描路径
sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasPackage);
// 设置mybatisplus全局配置
sqlSessionFactoryBean.setGlobalConfig(globalConfig);
// 设置mybatis的配置
sqlSessionFactoryBean.setConfiguration(mybatisConfiguration);
// 设置插件
final List interceptors = new ArrayList<>();
// 设置数据库为mysql,如果是oracle,记得更改
paginationInterceptor.setDbType(DbType.MYSQL);
// 设置分页插件
interceptors.add(paginationInterceptor);
// 加载插件
sqlSessionFactoryBean.setPlugins(interceptors.get(0));
return sqlSessionFactoryBean;
}
}
在上一篇的中springboot2.2.X手册:构建多元化的API接口,我们这样子设计,我们新增一个简单的分页对象
/**
* 分页对象
* @author:溪云阁
* @date:2020年5月10日
*/
@Data
@ApiModel(value = "分页对象", description = "分页对象")
public class PageMsg {
@ApiModelProperty(value = "总数量")
private int total = 0;
@ApiModelProperty(value = "当前页的行数")
private List rows = new ArrayList<>();
public PageMsg() {
}
public PageMsg(List rows, int total) {
this.rows = rows;
this.total = total;
}
}
/**
* 数据字典接口
* @author:溪云阁
* @date:2020年5月10日
*/
@SuppressWarnings("deprecation")
@Api(tags = { "后台系统服务:数据字典接口" })
@RestController
@RequestMapping("view/dict")
public class DictView {
@Autowired
private IDictService dictService;
/**
* 获取数据字典数据
* @author 溪云阁
* @param id
* @return ResponseMsg
*/
@ApiOperation(value = "获取数据字典数据")
@GetMapping(value = "/getDict", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@SneakyThrows(CommonRuntimeException.class)
public ResponseMsg getDict(@RequestParam("id") Long id) {
final Dict dict = dictService.getById(id);
final GetDictVO vo = GetDictVO.builder()
.id(dict.getId())
.name(dict.getName())
.value(dict.getValue())
.description(dict.getDescription())
.build();
return MsgUtils.buildSuccessMsg(vo);
}
/**
* 联合查询列表数据
* @author 溪云阁
* @param name
* @return ResponseMsg
*/
@ApiOperation(value = "联合查询列表数据")
@GetMapping(value = "/getDictList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@SneakyThrows(CommonRuntimeException.class)
public ResponseMsg> getDictList(@RequestParam("name") String name) {
final List bos = dictService.getDictList(name);
final List vos = new ArrayList<>();
bos.forEach(bo -> {
final GetDictListVO vo = GetDictListVO.builder()
.id(bo.getId())
.name(bo.getName())
.typeName(bo.getTypeName())
.value(bo.getValue())
.description(bo.getDescription())
.build();
vos.add(vo);
});
return MsgUtils.buildSuccessMsg(vos);
}
}
/**
* 数据字典服务实现层
* @author:溪云阁
* @date:2020年5月10日
*/
@Service
public class DictServiceImpl extends ServiceImpl implements IDictService{
/**
* 联合查询列表数据
* @author 溪云阁
* @param name
* @return List
*/
@Override
public List getDictList(String name) {
return baseMapper.getDictList(name);
}
}
/**
* 数据字典数据访问层
* @author:溪云阁
* @date:2020年5月10日
*/
@Mapper
public interface IDictDao extends BaseMapper {
/**
* 联合查询列表数据
* @author 溪云阁
* @param name
* @return List
*/
List getDictList(@Param("name") String name);
}
加入p6spy包
p6spy
p6spy
3.9.0
加入p6spy的配置文件
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,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
运行服务后,我们访问接口localhost:8080/doc.html
欢迎关注头条获取源码:@溪云阁
部分图片或代码来源网络,如侵权请联系删除,谢谢!