基于SpringBoot、Mybatis 您所在的位置:网站首页 java打印模板 基于SpringBoot、Mybatis

基于SpringBoot、Mybatis

#基于SpringBoot、Mybatis| 来源: 网络整理| 查看: 265

背景

我们在日常开发过程,大多数都是使用主流MVC架构,如下图所示。

从图中可以看出,我们主要的业务代码基本都是从Controller->Service->Dao/Mapper,由Dao/Mapper则通过Mybatis连接数据库连接池的方式与数据库进行指令数据交互。

因此,可以知道一张业务表一般可以对应上述一套后台代码,如果业务表众多就会对应多套后台代码,很明显这是重复且麻烦的代码生成工作。基于此,我们考虑能否实现一个与Ideaj代码生成工具有相似功能的工具类,根据我们定义的后台代码模板,来帮助我们个性化生成我们想要的后台代码。

技术路线

我们基于Springboot Gradle构建工程,将工程分为两部分模块。

(1)代码生成器模块:主要基于Freemarker和Velocity模板引擎,对需要的后台代码内容和风格自定义ftl模板。在Generator的主程序中连接数据库,加载模板文件,执行引擎方法,生成数据库表对应的后台代码到指定包路径中;

(2)服务发布模块:基于已生成的后台代码,使用SpringBoot进行发布,发布后通过浏览器访问,验证生成的后台代码是否满足指定业务表的增删改查(全量和分页查询)。

模块解析

(1)公共配置依赖:主要为build.gradle和application.properties配置

build.gradle:

plugins { id 'java' id 'org.springframework.boot' version '2.1.3.RELEASE' } group = 'com.example.mybatis' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' tasks.withType(JavaCompile) { options.encoding = "utf-8" } repositories { mavenCentral() } configurations { compileOnly { //仅在编译时依赖,此处为lombok使用,相关注解在编译时生成getter、setter等 extendsFrom annotationProcessor } } dependencies { compile 'com.alibaba:druid:1.2.8' compile 'mysql:mysql-connector-java:5.1.47' compile (group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.1.1'){ exclude group:'org.springframework.boot', module:'spring-boot-autoconfigure' exclude group:'org.springframework.boot', module:'spring-boot-starter-logging' exclude group:'org.springframework.boot', module: 'spring-boot-starter' } compile (group:'com.baomidou', name:'mybatis-plus-boot-starter', version:'3.5.1'){ exclude group:'org.springframework.boot', module:'spring-boot-starter-jdbc' exclude group:'org.springframework.boot', module:'spring-boot-autoconfigure' exclude group:'org.springframework.boot', module: 'spring-boot-starter' } compile group: 'org.springframework.boot', name: 'spring-boot-starter-parent', version: '2.0.7.RELEASE' compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.0.7.RELEASE' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.7.RELEASE' compileOnly 'org.projectlombok:lombok:1.18.6' compile group: 'junit', name: 'junit', version: '4.12' compile (group:'com.github.pagehelper', name:'pagehelper-spring-boot-starter', version:'1.3.1'){ exclude group:'org.mybatis.spring.boot', module: 'mybatis-spring-boot-starter' exclude group:'org.springframework.boot', module:'spring-boot-autoconfigure' exclude group:'org.springframework.boot', module: 'spring-boot-starter' } compile 'org.apache.commons:commons-io:1.3.2' compile group: 'io.springfox', name: 'springfox-swagger2', version:'2.9.2' compile group: 'io.springfox', name: 'springfox-swagger-ui', version:'2.9.2' compile('com.baomidou:mybatis-plus-generator:3.5.1') compile 'org.apache.velocity:velocity-engine-core:2.2' compile 'org.freemarker:freemarker:2.3.28' }

application.properties:

spring.application.name=mybatis-generator-application server.port=8080 # druid spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # druid参数调优(可选) # 初始化大小,最小,最大 spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 # 配置获取连接等待超时的时间 spring.datasource.maxWait=60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 spring.datasource.timeBetweenEvictionRunsMillis=60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 spring.datasource.minEvictableIdleTimeMillis=300000 # 测试连接 spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 打开PSCache,并且指定每个连接上PSCache的大小 spring.datasource.poolPreparedStatements=true spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 # 配置监控统计拦截的filters spring.datasource.filters=stat # asyncInit是1.1.4中新增加的配置,如果有initialSize数量较多时,打开会加快应用启动时间 spring.datasource.asyncInit=true #数据库配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url= jdbc:mysql://localhost:3306/mysql?serverTimeZone=UTC&useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username=root spring.datasource.password= #分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect 属性来指定分页插件使用哪种方言。 pagehelper.helper-dialect=mysql #分页合理化参数,默认值为 false 。当该参数设置为 true 时, pageNumpages (超过总数时),会查询最后一页。 pagehelper.reasonable=true #支持通过Mapper接口参数传递page参数,默认值为falset pagehelper.support-methods-arguments=true #默认值为 false ,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit =0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。 pagehelper.pageSizeZero=true #为了支持 startPage(Object params) 方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值 pagehelper.params=count=countSql

公共包

BaseController.java:

package com.common; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class BaseController extends AbstractController { @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { return null; } /** * 响应返回结果 * 参数result 类型可自行更换 * 如: * boolean result -> return result == true ? success() : error(); * int result -> return result > 0 ? success() : error(); */ protected AjaxResult toAjax(boolean result) { return result == true ? success() : error(); } protected AjaxResult toAjax(int result) { return result > 0 ? success() : error(); } /** * 返回成功 */ public AjaxResult success() { return AjaxResult.success(); } /** * 返回失败 */ public AjaxResult error() { return AjaxResult.error(); } /** * 返回成功消息 */ public AjaxResult success(String message) { return AjaxResult.success(message); } /** * 返回失败消息 */ public AjaxResult error(String message) { return AjaxResult.error(message); } /** * 返回错误码消息 */ public AjaxResult error(int code, String message) { return AjaxResult.error(code, message); } }

AjaxResult.java:

package com.common; import org.apache.commons.lang3.StringUtils; import java.util.HashMap; /** * 操作消息提醒 * * */ public class AjaxResult extends HashMap { private static final long serialVersionUID = 1L; /** 状态码 */ public static final String CODE_TAG = "code"; /** 返回内容 */ public static final String MSG_TAG = "msg"; /** 数据对象 */ public static final String DATA_TAG = "data"; /** * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 */ public AjaxResult() { } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 */ public AjaxResult(int code, String msg) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); } /** * 初始化一个新创建的 AjaxResult 对象 * * @param code 状态码 * @param msg 返回内容 * @param data 数据对象 */ public AjaxResult(int code, String msg, Object data) { super.put(CODE_TAG, code); super.put(MSG_TAG, msg); if (null != data) { super.put(DATA_TAG, data); } } /** * 返回成功消息 * * @return 成功消息 */ public static AjaxResult success() { return AjaxResult.success("操作成功"); } /** * 返回成功数据 * * @return 成功消息 */ public static AjaxResult success(Object data) { return AjaxResult.success("操作成功", data); } /** * 返回成功消息 * * @param msg 返回内容 * @return 成功消息 */ public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); } /** * 返回成功消息 * * @param msg 返回内容 * @param data 数据对象 * @return 成功消息 */ public static AjaxResult success(String msg, Object data) { return new AjaxResult(HttpStatus.SUCCESS, msg, data); } /** * 返回错误消息 * * @return */ public static AjaxResult error() { return AjaxResult.error("操作失败"); } /** * 返回错误消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); } /** * 返回错误消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static AjaxResult error(String msg, Object data) { return new AjaxResult(HttpStatus.ERROR, msg, data); } /** * 返回错误消息 * * @param code 状态码 * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(int code, String msg) { return new AjaxResult(code, msg, null); } /** * 方便链式调用 * * @param key 键 * @param value 值 * @return 数据对象 */ @Override public AjaxResult put(String key, Object value) { super.put(key, value); return this; } }

BaseEntity.java:

package com.common; import java.io.Serializable; public class BaseEntity implements Serializable { private int page; private int limit; public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getLimit() { return limit; } public void setLimit(int limit) { this.limit = limit; } @Override public String toString() { return "BaseEntity{" + "page=" + page + ", limit=" + limit + '}'; } }

HttpStatus.java:

package com.common; /** * 返回状态码 * * */ public class HttpStatus { /** * 操作成功 */ public static final int SUCCESS = 200; /** * 对象创建成功 */ public static final int CREATED = 201; /** * 请求已经被接受 */ public static final int ACCEPTED = 202; /** * 操作已经执行成功,但是没有返回数据 */ public static final int NO_CONTENT = 204; /** * 资源已被移除 */ public static final int MOVED_PERM = 301; /** * 重定向 */ public static final int SEE_OTHER = 303; /** * 资源没有被修改 */ public static final int NOT_MODIFIED = 304; /** * 参数列表错误(缺少,格式不匹配) */ public static final int BAD_REQUEST = 400; /** * 未授权 */ public static final int UNAUTHORIZED = 401; /** * 访问受限,授权过期 */ public static final int FORBIDDEN = 403; /** * 资源,服务未找到 */ public static final int NOT_FOUND = 404; /** * 不允许的http方法 */ public static final int BAD_METHOD = 405; /** * 资源冲突,或者资源被锁 */ public static final int CONFLICT = 409; /** * 不支持的数据,媒体类型 */ public static final int UNSUPPORTED_TYPE = 415; /** * 系统内部错误 */ public static final int ERROR = 500; /** * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; }

(2)代码生成器模块:该模块核心是定义ftl文件,然后主程序加载并执行模板引擎。

Generator.java

package com.generator; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.config.OutputFile; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import com.baomidou.mybatisplus.generator.fill.Column; import com.baomidou.mybatisplus.generator.fill.Property; import java.io.File; import java.util.*; /** * mybatis-plus */ public class Generator { //输出文件的作者注释 public static final String auth = "test"; //项目路径 public static final String finalProjectPath = "F:\\workspaces4ideaj"; //输出.java文件的根目录 public static final String javaRootPath = "/src/main/java"; //输出java文件的包目录 public static final String parent = "com.test"; //输出mapper.xml文件的包目录 public static final String mapperPath = "/src/main/resources/mapper"; //数据库信息 public static final String url = "jdbc:mysql://127.0.0.1:3306/mysql?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useSSL=false"; public static final String username = "root"; public static final String password = ""; public static void main(String[] args) { //创建生成器,连接数据库 FastAutoGenerator.create(url, username, password) //全局配置 .globalConfig(builder -> { builder.author(auth) //swagger模式 .enableSwagger() //关闭覆盖已生成文件功能,解决自定义模板被覆盖问题 //.fileOverride() .outputDir(finalProjectPath + javaRootPath) // 指定输出目录 .disableOpenDir(); }) .packageConfig((scanner, builder) -> builder .other("vo") .pathInfo(Collections.singletonMap(OutputFile.mapperXml, finalProjectPath + mapperPath)) .parent(parent + "." + scanner.apply("Please enter a package name:") )) //策略配置 .strategyConfig((scanner, builder) -> builder.addInclude( getTables(scanner.apply("Please enter a table name separated by dot, all input all: ")) ) // 设置过滤表前缀 .addTablePrefix("sys_") .controllerBuilder() .serviceBuilder() .mapperBuilder() .entityBuilder() .disableSerialVersionUID() .enableLombok() // 开启Lombok .enableTableFieldAnnotation() .addTableFills(new Column("create_time", FieldFill.INSERT)) .addTableFills(new Property("update_time", FieldFill.INSERT_UPDATE)) .idType(IdType.AUTO) .build() ) // 自定义注入模 // .vm为velocity引擎的,.ftl为freemarker引擎的 .injectionConfig(consumer -> { Map customFile = new HashMap(); customFile.put("Controller.java", "/templates/ftl/controller.java.ftl"); customFile.put("Service.java", "/templates/ftl/service.java.ftl"); customFile.put("ServiceImpl.java", "/templates/ftl/serviceImpl.java.ftl"); customFile.put("Mapper.java", "/templates/ftl/mapper.java.ftl"); customFile.put(".java", "/templates/ftl/entity.java.ftl"); customFile.put("Mapper.xml", "/templates/ftl/mapper.xml.ftl"); customFile.put("Vo.java", "/templates/ftl/vo.java.ftl"); consumer.customFile(customFile); }) /*//自定义模板模式 .templateConfig(builder -> { //禁止所有模板 builder.disable(TemplateType.ENTITY); builder.disable(TemplateType.XML); builder.disable(TemplateType.MAPPER); builder.disable(TemplateType.SERVICE); builder.disable(TemplateType.SERVICEIMPL); builder.disable(TemplateType.CONTROLLER); }) */ //使用Framemarker引擎模板,默认Velocity引擎模板 .templateEngine(new EnhanceFreemarkerTemplateEngine()).execute(); } //处理输入为all所有表 protected static List getTables(String tables) { return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(",")); } /** * 代码生成器支持自定义[DTO\VO等]模版 */ public final static class EnhanceFreemarkerTemplateEngine extends FreemarkerTemplateEngine { @Override protected void outputCustomFile(Map customFile, TableInfo tableInfo, Map objectMap) { String entityName = tableInfo.getEntityName(); String otherPath = this.getPathInfo(OutputFile.other); String controller = this.getPathInfo(OutputFile.controller); String service = this.getPathInfo(OutputFile.service); String serviceImpl = this.getPathInfo(OutputFile.serviceImpl); String mapper = this.getPathInfo(OutputFile.mapper); String entity = this.getPathInfo(OutputFile.entity); String mapperXml = this.getPathInfo(OutputFile.mapperXml); customFile.forEach((key, value) -> { //指定输出文件路径 if ("Controller.java".equals(key)) { String fileName = String.format(controller + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if ("Service.java".equals(key)) { String fileName = String.format(service + File.separator + "I" + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if ("ServiceImpl.java".equals(key)) { String fileName = String.format(serviceImpl + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if ("Mapper.java".equals(key)) { String fileName = String.format(mapper + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if (".java".equals(key)) { String fileName = String.format(entity + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if ("Mapper.xml".equals(key)) { String fileName = String.format(mapperXml + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } // 过滤掉非vo或dto对象自定义文件 if ("Vo.java".equals(key)) { String fileName = String.format(otherPath + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } if ("Dto.java".equals(key)) { String fileName = String.format(otherPath + File.separator + entityName + "%s", key); outputFile(new File(fileName), objectMap, value); } }); } } }

src/main/resources/mybatis-generator.xml:

src/main/resources/templates/ftl/文件

controller.java.ftl:

package ${package.Controller}; import ${package.Entity}.${entity}; import ${package.Other}.${entity}Vo; import ${package.Service}.${table.serviceName}; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.*; import io.swagger.annotations.*; import com.common.AjaxResult; import com.common.BaseController; import java.util.List; import java.util.Map; import ${superControllerClassPackage}; /** * ${table.comment!} 前端控制器 * @author ${author} * @since ${date} */ @Api(tags = "${table.comment!}文档") @RestController @RequestMapping("/${package.ModuleName}/${controllerMappingHyphen}${table.entityPath}") public class ${table.controllerName} extends BaseController{ @Resource(name="${entity?lower_case}Service") private ${table.serviceName} ${entity?lower_case}Service; /** * * 分页查詢列表 * @return page */ @ApiOperation(value = "分页查询列表", httpMethod = "GET", notes = "分页查询列表") @ApiImplicitParam(paramType = "body", name = "${entity?lower_case}Vo", value = "对象", dataType = "${entity}Vo") @ApiResponses({ @ApiResponse(code = 200, message = "响应对象", response = ${entity}.class) }) @GetMapping("/queryListByPagging") public AjaxResult queryListByPagging(${entity}Vo ${entity?lower_case}Vo) { Map map = ${entity?lower_case}Service.select${entity}ListByPagging(${entity?lower_case}Vo); return AjaxResult.success(map); } /** * * 查詢列表 * @return page */ @ApiOperation(value = "查询列表", httpMethod = "GET", notes = "查询列表") @ApiImplicitParam(paramType = "body", name = "${entity?lower_case}Vo", value = "对象", dataType = "${entity}Vo") @ApiResponses({ @ApiResponse(code = 200, message = "响应对象", response = ${entity}.class) }) @GetMapping("/queryList") public AjaxResult queryList(${entity}Vo ${entity?lower_case}Vo) { List list = ${entity?lower_case}Service.select${entity}List(${entity?lower_case}Vo); return AjaxResult.success(list); } /** * 新增 */ @ApiOperation(value = "新增", httpMethod = "POST") @ApiImplicitParam(paramType = "body", name = "${entity?lower_case}", value = "对象", dataType = "${entity}") @PostMapping("/insert${entity}") public AjaxResult insert${entity}(@RequestBody ${entity} ${entity?lower_case}){ return toAjax(${entity?lower_case}Service.insert${entity}(${entity?lower_case})); } /** * 修改 */ @ApiOperation(value = "修改", httpMethod = "POST") @ApiImplicitParam(paramType = "body", name = "${entity?lower_case}", value = "对象", dataType = "${entity}") @PostMapping("/update${entity}") public AjaxResult update${entity}(@RequestBody ${entity} ${entity?lower_case}){ return toAjax(${entity?lower_case}Service.update${entity}(${entity?lower_case})); } /** * 删除 */ @ApiOperation(value = "删除", httpMethod = "POST") @ApiImplicitParam(paramType = "query", name = "id", value = "主键id") @PostMapping("/delete${entity}") public AjaxResult delete${entity}(@RequestParam("id") Integer id){ return toAjax(${entity?lower_case}Service.delete${entity}(id)); } }

service.java.ftl:

package ${package.Service}; import ${package.Entity}.${entity}; import ${package.Other}.${entity}Vo; import ${superServiceClassPackage}; import java.util.List; import java.util.Map; /** * ${table.comment!} 服务类 * @author ${author} * @since ${date} */ public interface ${table.serviceName} extends ${superServiceClass} { /** * 查询${table.comment!}数量 */ public Integer select${entity}Count(${entity}Vo ${entity?lower_case}Vo); /** * 查詢${table.comment!}列表 * @return page */ List select${entity}List(${entity}Vo ${entity?lower_case}Vo); /** * 分页查詢${table.comment!}列表 * @return page */ Map select${entity}ListByPagging(${entity}Vo ${entity?lower_case}Vo); /** * 新增${table.comment!} */ int insert${entity}(${entity} ${entity?lower_case}); /** * 修改${table.comment!} */ int update${entity}(${entity} ${entity?lower_case}); /** * 删除${table.comment!} */ int delete${entity}(Integer id); }

serviceImpl.java.ftl:

package ${package.ServiceImpl}; import ${package.Entity}.${entity}; import ${package.Mapper}.${table.mapperName}; import ${package.Service}.${table.serviceName}; import ${superServiceImplClassPackage}; import ${package.Other}.${entity}Vo; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.HashMap; import java.util.Map; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; /** * ${table.comment!}服务实现类 * @author ${author} * @since ${date} */ @Slf4j @Service("${entity?lower_case}Service") public class ${table.serviceImplName} extends ${superServiceImplClass} implements ${table.serviceName} { @Autowired private ${table.mapperName} ${entity?lower_case}Mapper; /** * 查询${table.comment!}数量 */ @Override public Integer select${entity}Count(${entity}Vo ${entity?lower_case}Vo) { return ${entity?lower_case}Mapper.queryCount(${entity?lower_case}Vo); } /** * * 查詢${table.comment!}列表 * * @return page */ @Override public List select${entity}List(${entity}Vo ${entity?lower_case}Vo) { return ${entity?lower_case}Mapper.queryList(${entity?lower_case}Vo); } /** * 分页查詢${table.comment!}列表 * @return Map */ public Map select${entity}ListByPagging(${entity}Vo ${entity?lower_case}Vo){ Integer count = select${entity}Count(${entity?lower_case}Vo); Map map = new HashMap(); List list = null; if(null != count && count > 0){ PageInfo pageInfo = null; try { PageHelper.startPage(${entity?lower_case}Vo.getPage(), ${entity?lower_case}Vo.getLimit()); list = select${entity}List(${entity?lower_case}Vo); }finally { PageHelper.clearPage(); } } map.put("count", count); map.put("list", list); return map; } /** * 新增${table.comment!} * * @return 结果 */ @Override public int insert${entity}(${entity} ${entity?lower_case}) { return ${entity?lower_case}Mapper.insert(${entity?lower_case}); } /** * 修改${table.comment!} * * @return 结果 */ @Override public int update${entity}(${entity} ${entity?lower_case}) { return ${entity?lower_case}Mapper.updateById(${entity?lower_case}); } /** * 删除${table.comment!} * * @return 结果 */ @Override public int delete${entity}(Integer id) { return ${entity?lower_case}Mapper.deleteById(id); } }

entity.java.ftl:

package ${package.Entity}; import ${pkg}; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import lombok.Data; import java.io.Serializable; /** * ${table.comment!} * @author ${author} * @since ${date} */ @Data @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @TableName("${schemaName}${table.name}") @ApiModel(value = "${entity}对象", description = "${table.comment!}") public class ${entity} implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty("${field.comment}") /** * ${field.comment} */ @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO) @TableId(value = "${field.annotationColumnName}", type = IdType.${idType}) @TableId("${field.annotationColumnName}") @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill}) @TableField(fill = FieldFill.${field.fill}) @TableField("${field.annotationColumnName}") @Version @TableLogic private ${field.propertyType} ${field.propertyName}; public ${field.propertyType} ${getprefix}${field.capitalName}() { return ${field.propertyName}; } public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) { public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) { this.${field.propertyName} = ${field.propertyName}; return this; } public static final String ${field.name?upper_case} = "${field.name}"; @Override public Serializable pkVal() { return this.${keyPropertyName}; return null; } @Override public String toString() { return "${entity}{" + "${field.propertyName}=" + ${field.propertyName} + ", ${field.propertyName}=" + ${field.propertyName} + "}"; } }

vo.java.ftl:

package ${package.Other}; import ${pkg}; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; import io.swagger.annotations.ApiModel; import com.common.BaseEntity; /** *

* ${table.comment!} *

* * @author ${author} * @since ${date} */ @Data @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor @ApiModel(value = "${entity}对象", description = "${table.comment!}") public class ${entity}Vo extends BaseEntity { private static final long serialVersionUID = 1L; private ${field.propertyType} ${field.propertyName}; @Override public String toString() { return "TOrderVo{" + "${field.propertyName}=" + ${field.propertyName} + "," + "}"; } }

mapper.java.ftl:

package ${package.Mapper}; import ${package.Entity}.${entity}; import ${package.Other}.${entity}Vo; import ${superMapperClassPackage}; import java.util.List; import org.apache.ibatis.annotations.Mapper; /** * ${table.comment!} Mapper 接口 * @author ${author} * @since ${date} */ @Mapper public interface ${table.mapperName} extends ${superMapperClass} { /** * 查詢${table.comment!}数量 * @return Integer */ Integer queryCount(${entity}Vo ${entity?lower_case}Vo); /** * 查詢${table.comment!}列表 * @return List */ List queryList(${entity}Vo ${entity?lower_case}Vo); }

mapper.xml.ftl:

${field.columnName}, ${table.fieldNames} AND ${field.name} = #${r"{"}${field.propertyName}${r"}"} AND ${field.name} = #${r"{"}${field.propertyName}${r"}"} select COUNT(1) from ${table.name} select from ${table.name}

然后启动mysql服务,创建一张t_bill表,并新增4条记录。

CREATE TABLE t_bill(

bill_id INT NOT NULL AUTO_INCREMENT,

bill_title VARCHAR(100) NOT NULL,

bill_author VARCHAR(40) NOT NULL,

bill_date DATE,

PRIMARY KEY ( bill_id )

);

mysql> select * from t_bill;

+---------+------------+-------------+-----------+

| bill_id | bill_title | bill_author | bill_date |

+---------+------------+-------------+-----------+

| 1 | haha | test | NULL |

| 2 | haha | test | NULL |

| 3 | haha | test | NULL |

| 4 | haha55 | test | NULL |

+---------+------------+-------------+-----------+

4 rows in set (0.00 sec)

执行Generator工具类,输入需要创建的子包名、表名,执行结束即可看到工程中自动生成该表的后台代码:

(3)服务发布模块:该模块启动Springboot工程,将生成的后台代码发布到tomcat后通过浏览器访问。

BootApplicationl.java:

package com; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication @EnableSwagger2 @MapperScan(value="com.test") public class BootApplication { public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); } }

然后可通过浏览器访问查询/分页查询方法服务

http://localhost:8080/t-bill/queryList

返回

{"msg":"操作成功","code":200,"data":[{"billId":1,"billTitle":"haha","billAuthor":"test","billDate":null},{"billId":2,"billTitle":"haha","billAuthor":"test","billDate":null},{"billId":3,"billTitle":"haha","billAuthor":"test","billDate":null},{"billId":4,"billTitle":"haha55","billAuthor":"test","billDate":null}]}

http://localhost:8080/t-bill/queryListByPagging?page=1&limit=2

返回

{"msg":"操作成功","code":200,"data":{"count":4,"list":[{"billId":1,"billTitle":"haha","billAuthor":"test","billDate":null},{"billId":2,"billTitle":"haha","billAuthor":"test","billDate":null}]}}

http://localhost:8080/t-bill/queryListByPagging?page=2&limit=2

返回

{"msg":"操作成功","code":200,"data":{"count":4,"list":[{"billId":3,"billTitle":"haha","billAuthor":"test","billDate":null},{"billId":4,"billTitle":"haha55","billAuthor":"test","billDate":null}]}}

也可使用postman等工具测试insert,update,delete服务

http://localhost:8080/t-bill/insertTBill

{

"billId":888,

"billTitle":"888",

"billAuthor":"888",

"LocalDate":null

}

返回

{

"msg": "操作成功",

"code": 200

}

mysql> select * from t_bill;

+---------+------------+-------------+-----------+

| bill_id | bill_title | bill_author | bill_date |

+---------+------------+-------------+-----------+

| 1 | haha | test | NULL |

| 2 | haha | test | NULL |

| 3 | haha | test | NULL |

| 4 | haha55 | test | NULL |

| 888 | 888 | 888 | NULL |

+---------+------------+-------------+-----------+

5 rows in set (0.03 sec)

http://localhost:8080/t-bill/updateTBill

{

"billId":888,

"billTitle":"update888",

"billAuthor":"update888",

"LocalDate":null

}

返回

{

"msg": "操作成功",

"code": 200

}

mysql> select * from t_bill;

+---------+------------+-------------+-----------+

| bill_id | bill_title | bill_author | bill_date |

+---------+------------+-------------+-----------+

| 1 | haha | test | NULL |

| 2 | haha | test | NULL |

| 3 | haha | test | NULL |

| 4 | haha55 | test | NULL |

| 888 | update888 | update888 | NULL |

+---------+------------+-------------+-----------+

5 rows in set (0.00 sec)

http://localhost:8080/t-bill/deleteTBill?id=1

返回

{

"msg": "操作成功",

"code": 200

}

mysql> select * from t_bill;

+---------+------------+-------------+-----------+

| bill_id | bill_title | bill_author | bill_date |

+---------+------------+-------------+-----------+

| 2 | haha | test | NULL |

| 3 | haha | test | NULL |

| 4 | haha55 | test | NULL |

| 888 | update888 | update888 | NULL |

+---------+------------+-------------+-----------+

4 rows in set (0.00 sec)

总结

在构建工程过程中,踩了不少坑下面描述一下避免后面入坑。

1.没有安装mysql,工程中没有配置mysql相关配置,没有引入mysql相关驱动包等导致启动失败。

2.工程使用springboot2.0.7启动,引入mybatis-plus,pageHelper会修改springboot版本,应剔除

3.mybatis-plus,pageHelper的版本没有互相适配导致报jsqlparser错误

4.Application启动类中添加MapperScan扫描,且扫描路径应详细到具体包根路径,扫描引入的jar会出现bean冲突

5.mapper.xml中如果需要动态sql带有特殊字符如#的,在ftl模板中需要对#使用r"{"和r"}"进行转义,



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有