基于SpingBoot 2.X 整合MyBatis Plus
本文旨在整理SpringBoot 2.X整合MyBatis Plus基础功能,如有问题请指出
参考资料:https://mp.baomidou.com/
一. 在pom.xml文件中引入MyBatis Plus的依赖
这里需要引入lombok、jdbc、数据库、druid、Mybatis-plus、CodeGenerator、freemarker的依赖
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-actuator-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<!--CodeGenerator-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.0</version>
</dependency>
<!-- freemarker 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
二. 配置CodeGeneratorUtil
这里使用mybaties plus代码生成器自动生成,右键Debug ‘CodeGeneratorUtl main()’即可自动生成,以下是参数说明
参数1:系统名称,即当前项目的包名(新建项目的时候指定的Module name)
参数2:主键生成策略,这里Oracle使用的是Sequence,所以指定的是INPUT,对于主键策略来说,相当于用户手动插入,使用IdType插入
参数3:作者
参数4:数据库类型,使用DbType插入
参数5:数据库url
参数6:驱动名
参数7:数据库名
参数8:数据库密码
参数9:模块名,即代码生成器生成的代码文件存放的包名 (即在参数10的基础上建一个包存放代码文件)
参数10:模块名的父目录,即代码生成器生成的代码文件所存放的目录(新建项目的时候指定的Package)
参数11:映射的数据库表明
/**
* @author SLy
* @Title: CodeGeneratorUtil
* @ProjectName newyhcloud
* @Description: 代码生成器(Oracle生成后实体需自己手动加入@KeySequence注解标识序列)
* @date 创建于2019-1-23 15:57
*/
public class CodeGeneratorUtil {
/**
* @param systemName 系统名称 例:newyhcloud-service-platform
* @param idType 主键生成策略 例:IdType.INPUT
* @param author 作者 例:SLy
* @param dbType 数据库类型 例:DbType.ORACLE
* @param dbUrl 数据库 例:jdbc:oracle:thin:@(description=(address_list= (address=(host=10.0.9.11) (protocol=tcp)(port=1521))(address=(host=10.0.9.12)(protocol=tcp) (port=1521)) (load_balance=yes)(failover=yes))(connect_data=(service_name= hrdev)))
* @param driverName 驱动名 例:oracle.jdbc.driver.OracleDriver
* @param dbName 数据库名 例:hrdev
* @param dbPass 数据库密码 例:hrdev
* @param moduleName 模块名 例:platform
* @param parent 模块名所生成的父目录 例:com.yihuacomputer.newyhcloud.server
* @param tableName 映射的数据库表名 例:PUB_NEW_USER
*/
public static void codeGeneration(String systemName, IdType idType, String author, DbType dbType, String dbUrl, String driverName, String dbName, String dbPass, String moduleName, String parent, String tableName) {
if (StringUtil.isEmpty(systemName) || idType == null || StringUtil.isEmpty(author) || dbType == null ||
StringUtil.isEmpty(dbUrl) || StringUtil.isEmpty(driverName) || StringUtil.isEmpty(dbName) ||
StringUtil.isEmpty(dbPass) || StringUtil.isEmpty(moduleName) || StringUtil.isEmpty(parent) ||
StringUtil.isEmpty(tableName)) {
throw new MybatisPlusException("请求参数不能为空!");
}
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
gc.setActiveRecord(true); // 是否支持AR模式
String projectPath = System.getProperty("user.dir") + "/" + systemName;
gc.setOutputDir(projectPath + "/src/main/java"); // 生成路径
gc.setFileOverride(true); // 文件覆盖
gc.setIdType(idType); // 主键策略--Oracle使用Sequence
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setBaseResultMap(true); //生成基本的resultMap
gc.setBaseColumnList(true); //生成基本的SQL片段
gc.setAuthor(author); // 作者
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 2、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
// dsc.setSchemaName("public");
dsc.setDbType(dbType);// 设置数据库类型
dsc.setUrl(dbUrl);
dsc.setDriverName(driverName);
dsc.setUsername(dbName);
dsc.setPassword(dbPass);
mpg.setDataSource(dsc);
// 3、包名策略配置
PackageConfig pc = new PackageConfig();
// pc.setService("service");
// pc.setController("controller");
// pc.setEntity("entity");
pc.setModuleName(moduleName);
pc.setParent(parent);
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
// templateConfig.setEntity();
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setCapitalMode(false); // 全局大写命名 ORACLE 注意
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setInclude(tableName);
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
// strategy.setTablePrefix(pc.getModuleName() + "_"); // 此处可以修改为您的表前缀(表名以什么开头)
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
public static void main(String[] args) {
CodeGeneratorUtil.codeGeneration("newyhcloud-demo", IdType.INPUT, "SLy", DbType.ORACLE,
"jdbc:oracle:thin:@(description=(address_list= (address=(host=10.0.9.11) (protocol=tcp)(port=1521))(address=(host=10.0.9.12)(protocol=tcp) (port=1521)) (load_balance=yes)(failover=yes))(connect_data=(service_name= hrdev)))",
"oracle.jdbc.driver.OracleDriver", "hrdev", "hrdev", "demo", "com.yihuacomputer.newyhcloud.server", "STUDENT");
}
我这里使用的是Oracle的Sequence序列,所以生成后需要在实体里指定序列,同时Alt+Insert快捷键生成setter/getter方法
@KeySequence("SEQ_STUDENT")
三. 配置application.yml文件
这里使用的是drtrang的druid配置
mybaties plus的typeAliasesPackage需配置当前实体包
server:
port: 8768
eureka:
client:
serviceUrl:
defaultZone: http://admin:12345@localhost:8761/eureka/
spring:
application:
name: demo-service
datasource:
url: jdbc:oracle:thin:@(description=(address_list= (address=(host=10.0.9.11) (protocol=tcp)(port=1521))(address=(host=10.0.9.12)(protocol=tcp) (port=1521)) (load_balance=yes)(failover=yes))(connect_data=(service_name= hrdev)))
driver-class-name: oracle.jdbc.driver.OracleDriver
username: hrdev
password: hrdev
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 #初始化连接个数
max-active: 20 #最大连接个数
min-idle: 5 #最小连接个数
max-wait: 6000 #最大等待时间
pool-prepared-statements: true #开启缓存PSCache
max-pool-prepared-statement-per-connection-size: 20 #指定每个连接上PSCache的大小
time-between-eviction-runs-millis: 6000 #在空闲连接回收器线程运行期间休眠的时间值
min-evictable-idle-time-millis: 100000 #配置一个连接在池中最小生存的时间
validation-query: SELECT 1 FROM DUAL #用来检测连接是否有效的sql
validation-query-timeout: 60000 #检查sql超时时间
test-while-idle: true #申请连接的时候检测
test-on-borrow: false #申请连接时执行validationQuery检测连接是否有效
test-on-return: false #归还连接时执行validationQuery检测连接是否有效
#开启StatFilter
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
#开启Slf4jFilter
slf4j:
enabled: true
data-source-log-enabled: false
connection-log-enabled: false
statement-log-enabled: false
result-set-log-enabled: false
#开启WallFilter
wall:
enabled: true
log-violation: true
throw-exception: false
config:
delete-where-none-check: true
#开启Web监控
web-stat:
enabled: true
#开启Aop监控
aop-stat:
enabled: true
#开启监控页面
stat-view-servlet:
enabled: true
login-username: admin
login-password: yhadmin123
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.yihuacomputer.newyhcloud.server.demo.entity
global-config:
# 数据库相关配置
db-config:
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
id-type: INPUT
#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
field-strategy: not_empty
#数据源类型
db-type: oracle
# 原生配置
configuration:
map-underscore-to-camel-case: true
#配置JdbcTypeForNull, oracle数据库必须配置
jdbc-type-for-null: 'null'
#这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
四. 配置mapper扫描路径
在启动类增加mapper扫描路径
@MapperScan(“com.yihuacomputer.newyhcloud.server.demo.mapper”)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@MapperScan("com.yihuacomputer.newyhcloud.server.demo.mapper")
public class NewyhcloudDemoApplication {
public static void main(String[] args) {
SpringApplication.run(NewyhcloudDemoApplication.class, args);
}
}
五. 配置MybatisPlusConfig分页插件
这里使用MybatisPlus的分页插件,指定扫描项目所在的mapper
@MapperScan(“com.yihuacomputer.newyhcloud.server.demo.mapper”)
@EnableTransactionManagement
@Configuration
@MapperScan("com.yihuacomputer.newyhcloud.server.demo.mapper")
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
/**
* Sequence主键
*/
@Bean
public OracleKeyGenerator oracleKeyGenerator() {
return new OracleKeyGenerator();
}
}
六. 编写业务代码
这里只展示简单的查询业务,建议安装Mybatis X插件简化开发,详细安装步骤参考链接
https://mp.baomidou.com/guide/mybatisx-idea-plugin.html
这里以实体形式传参,@Param(“student”)即为xml标签里if条件的student
Mapper
编写完mapper后,Mybatis X会自动提示创建映射的标签,快捷键Alt+Enter ,选择Generate statement会自动生成映射的xml标签
public interface StudentMapper extends BaseMapper<Student> {
List<Student> selectStudentList(Page<Student> page, @Param("student") Student student);
}
XML
自动生成的selectStudentList,在select标签里写SQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yihuacomputer.newyhcloud.server.demo.mapper.StudentMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.yihuacomputer.newyhcloud.server.demo.entity.Student">
<id column="ID" property="id" />
<result column="NAME" property="name" />
<result column="AGE" property="age" />
<result column="SEX" property="sex" />
<result column="BIRTHDAY" property="birthday" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
ID, NAME, AGE, SEX, BIRTHDAY
</sql>
<select id="selectStudentList" resultType="com.yihuacomputer.newyhcloud.server.demo.entity.Student">
SELECT * FROM STUDENT WHERE 1 = 1
<if test="student.id != null">
AND STUDENT.ID = #{student.id}
</if>
<if test="student.name != null">
AND STUDENT.NAME LIKE '%'||#{student.name}||'%'
</if>
</select>
</mapper>
Service
public interface StudentService extends IService<Student> {
IPage<Student> selectStudentList(Page<Student> studentPage, Student student);
}
ServiceImpl
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
private static Logger logger = LoggerFactory.getLogger(StudentServiceImpl.class);
@Autowired
private StudentMapper studentMapper;
@Override
public IPage<Student> selectStudentList(Page<Student> studentPage, Student student) {
try {
studentPage.setRecords(studentMapper.selectStudentList(studentPage, student));
return studentPage;
} catch (Exception e) {
logger.error("查询学生列表出错" + e);
throw new RuntimeException(e.getMessage());
}
}
}
Controller
@RestController
@RequestMapping("/demo/student")
public class StudentController {
private static Logger logger = LoggerFactory.getLogger(StudentController.class);
@Autowired
private StudentService studentService;
@GetMapping
@ApiOperation(value = "测试", httpMethod = "GET", notes = "测试接口")
@ApiResponses({
@ApiResponse(code = 201, message = "请求已经被实现"),
@ApiResponse(code = 400, message = "请求参数有误"),
@ApiResponse(code = 401, message = "用户验证失败"),
@ApiResponse(code = 403, message = "服务器禁止访问"),
@ApiResponse(code = 404, message = "请求资源未找到"),
@ApiResponse(code = 500, message = "服务器内部解析出错")})
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "ID", dataType = "long", paramType = "query", example = "0"),
@ApiImplicitParam(name = "name", value = "姓名", dataType = "string", paramType = "query"),
@ApiImplicitParam(name = "page", value = "当前页", required = true, dataType = "int", example = "0"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, dataType = "int", example = "0"),
@ApiImplicitParam(name = "orderColumn", value = "排序字段", required = true, dataType = "string"),
@ApiImplicitParam(name = "orderWay", value = "排序方式", required = true, dataType = "string")})
public ModelMap list(
@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "page") int page,
@RequestParam(value = "pageSize") int pageSize,
@RequestParam(value = "orderColumn") String orderColumn,
@RequestParam(value = "orderWay") String orderWay) {
ModelMap modelMap = new ModelMap();
List<Student> studentList = null;
try {
Student student = new Student();
if (id != null) {
student.setId(id);
}
if (name != null && !"".equals(name)) {
student.setName(name);
}
Page<Student> studentPage = new Page<>(page, pageSize);
if ("asc".equals(orderWay)) {
studentPage.setAsc(orderColumn);
} else if ("desc".equals(orderWay)) {
studentPage.setDesc(orderColumn);
}
IPage<Student> studentIPage = studentService.selectStudentList(studentPage, student);
studentList = studentIPage.getRecords();
modelMap.put("result", studentList);
} catch (Exception e) {
logger.error("查询出错" + e);
}
return modelMap;
}
}
七. 编译启动运行
maven clean、maven install 后启动运行,访问swagger,按照我swagger2的教程,我这里需要修改下swagger扫描路径,启动测试
http://localhost:8768/swagger-ui.html