用模板做企业网站,做网站到哪里做,合肥房产网最新楼盘,cms与wordpress前言
最近有个想法想整理一个内容比较完整springboot项目初始化Demo。
连接Oracle数据库集成mybatis-plus#xff0c;自定义WrapperFactory。配置代码生成器
一、引入jar包 !--oracle驱动 --dependencygroupIdorg.springframework.boot/groupI…前言
最近有个想法想整理一个内容比较完整springboot项目初始化Demo。
连接Oracle数据库集成mybatis-plus自定义WrapperFactory。配置代码生成器
一、引入jar包 !--oracle驱动 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdcom.oracle.ojdbc/groupIdartifactIdojdbc8/artifactIdversion19.3.0.0/version/dependency!-- oracle8 所需的字符集 --dependencygroupIdcn.easyproject/groupIdartifactIdorai18n/artifactIdversion12.1.0.2.0/version/dependency!--mybatis-plus--dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.1/version/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-generator/artifactIdversion3.5.1/version/dependencydependencygroupIdorg.freemarker/groupIdartifactIdfreemarker/artifactIdversion2.3.28/version/dependency!--mybatis-plus--
二、新建配置文件application-dev.yaml
以根据不同的环境配置不同的属性文件application-{profile} 表示环境名称。 例如application-dev.yaml用于开发环境application-prod.yaml用于生产环境。
增加数据库配置 hikari连接池配置
spring:datasource:driver-class-name: oracle.jdbc.OracleDriverurl: jdbc:oracle:thin://127.0.0.1:1521/orclusername: murg_demopassword: 654321hikari:connection-test-query: SELECT 1 FROM DUALminimum-idle: 10maximum-pool-size: 50idle-timeout: 120000max-lifetime: 180000connection-timeout: 18000
logging:level:org.springframework.security: debug
启动服务看服务是否正常启动
三、自定义MyBatis 构造对象加工厂。
用于规定查询返回值格式 主要用于_处理和字段大小写规定
package com.murg.bootdemo.interceptor;import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import java.util.Map;/*** 自定义ObjectWrapperFactory 结果处理 去除_ 字段大写转小写*/
public class MapWrapperFactory implements ObjectWrapperFactory {Overridepublic boolean hasWrapperFor(Object object) {return object instanceof Map;}Overridepublic ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {return new MyMapWrapper(metaObject,(Map)object);}
}package com.murg.bootdemo.interceptor;import org.apache.commons.lang3.math.NumberUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.wrapper.MapWrapper;import java.util.Map;/*** mybatis 结果处理 去除_ 字段大写转小写*/
public class MyMapWrapper extends MapWrapper {public MyMapWrapper(MetaObject metaObject, MapString, Object map) {super(metaObject, map);}Overridepublic String findProperty(String name, boolean useCamelCaseMapping) {if (useCamelCaseMapping ((name.charAt(0) A name.charAt(0) Z)|| name.contains(_))) {return underlineToCamelhump(name);}return name;}/*** 将下划线风格替换为驼峰风格* param inputString* return*/public String underlineToCamelhump(String inputString) {StringBuilder sb new StringBuilder();boolean nextUpperCase false;for (int i 0; i inputString.length(); i) {char c inputString.charAt(i);if (c _) {if (sb.length() 0) {nextUpperCase true;}} else {if (nextUpperCase) {if (NumberUtils.isNumber(String.valueOf(c))) {sb.append(_).append(c);} else {sb.append(Character.toUpperCase(c));}nextUpperCase false;} else {sb.append(Character.toLowerCase(c));}}}return sb.toString();}
}四、自定义WrapperFactoryConverter
以上配置好WrapperFactory后启动会报错
提示找不到合适的converter将string转化为ObjectWrapperFactory对象
缺少对应的converterspringboot不会提供反射机制来构建一个对象的converter需要手写一个
package com.murg.bootdemo.interceptor;import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;Component
ConfigurationPropertiesBinding
public class ObjectWrapperFactoryConverter implements ConverterString, ObjectWrapperFactory {Overridepublic ObjectWrapperFactory convert(String source) {try {return (ObjectWrapperFactory) Class.forName(source).newInstance();} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {throw new RuntimeException(e);}}
}五、整合MyBatisPlus代码生成器 mybatis-plus-generator配合freemaker引擎
5.1下面这些文件直接创建在resources/generator1/templates的目录下把内容复制进去就行了。这些文件就是代码生成的格式模板。 controller.java.ftl
package ${package.Controller};import org.springframework.web.bind.annotation.RequestMapping;#if restControllerStyle
import org.springframework.web.bind.annotation.RestController;
#else
import org.springframework.stereotype.Controller;
/#if
#if superControllerClassPackage??
import ${superControllerClassPackage};
/#if/*** p* ${table.comment!} 前端控制器* /p** author ${author}* since ${date}*/
#if restControllerStyle
RestController
#else
Controller
/#if
RequestMapping(#if package.ModuleName?? package.ModuleName ! /${package.ModuleName}/#if/#if controllerMappingHyphenStyle??${controllerMappingHyphen}#else${table.entityPath}/#if)
#if kotlin
class ${table.controllerName}#if superControllerClass?? : ${superControllerClass}()/#if
#else
#if superControllerClass??
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
/#if}
/#ifentity.java.ftl
package ${package.Entity};#list table.importPackages as pkg
import ${pkg};
/#list
#if swagger
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/#if
#if entityLombokModel
import lombok.Getter;
import lombok.Setter;#if chainModel
import lombok.experimental.Accessors;/#if
/#if/*** p* ${table.comment!}* /p** author ${author}* since ${date}*/
#if entityLombokModel
Getter
Setter#if chainModel
Accessors(chain true)/#if
/#if
#if table.convert
TableName(${schemaName}${table.name})
/#if
#if swagger
ApiModel(value ${entity}对象, description ${table.comment!})
/#if
#if superEntityClass??
public class ${entity} extends ${superEntityClass}#if activeRecord${entity}/#if {
#elseif activeRecord
public class ${entity} extends Model${entity} {
#elseif entitySerialVersionUID
public class ${entity} implements Serializable {
#else
public class ${entity} {
/#if
#if entitySerialVersionUIDprivate static final long serialVersionUID 1L;
/#if
#-- ---------- BEGIN 字段循环遍历 ----------
#list table.fields as field#if field.keyFlag#assign keyPropertyName${field.propertyName}//#if#if field.comment!?length gt 0#if swaggerApiModelProperty(${field.comment})#else/*** ${field.comment}*//#if/#if#if field.keyFlag#-- 主键 --#if field.keyIdentityFlagTableId(value ${field.annotationColumnName}, type IdType.AUTO)#elseif idType??TableId(value ${field.annotationColumnName}, type IdType.${idType})#elseif field.convertTableId(${field.annotationColumnName})/#if#-- 普通字段 --#elseif field.fill??#-- ----- 存在字段填充设置 -----#if field.convertTableField(value ${field.annotationColumnName}, fill FieldFill.${field.fill})#elseTableField(fill FieldFill.${field.fill})/#if#elseif field.convertTableField(${field.annotationColumnName})/#if#-- 乐观锁注解 --#if field.versionFieldVersion/#if#-- 逻辑删除注解 --#if field.logicDeleteFieldTableLogic/#ifprivate ${field.propertyType} ${field.propertyName};
/#list
#------------ END 字段循环遍历 ----------#if !entityLombokModel#list table.fields as field#if field.propertyType boolean#assign getprefixis/#else#assign getprefixget//#ifpublic ${field.propertyType} ${getprefix}${field.capitalName}() {return ${field.propertyName};}#if chainModelpublic ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {#elsepublic void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {/#ifthis.${field.propertyName} ${field.propertyName};#if chainModelreturn this;/#if}/#list
/#if#if entityColumnConstant#list table.fields as fieldpublic static final String ${field.name?upper_case} ${field.name};/#list
/#if
#if activeRecordOverridepublic Serializable pkVal() {#if keyPropertyName??return this.${keyPropertyName};#elsereturn null;/#if}/#if
#if !entityLombokModelOverridepublic String toString() {return ${entity}{ #list table.fields as field#if field_index0${field.propertyName} ${field.propertyName} #else, ${field.propertyName} ${field.propertyName} /#if/#list};}
/#if
}entity.kt.ftl
package ${package.Entity}#list table.importPackages as pkg
import ${pkg}
/#list
#if swagger
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/#if/*** p* ${table.comment}* /p** author ${author}* since ${date}*/
#if table.convert
TableName(${schemaName}${table.name})
/#if
#if swagger
ApiModel(value ${entity}对象, description ${table.comment!})
/#if
#if superEntityClass??
class ${entity} : ${superEntityClass}#if activeRecord${entity}/#if {
#elseif activeRecord
class ${entity} : Model${entity}() {
#elseif entitySerialVersionUID
class ${entity} : Serializable {
#else
class ${entity} {
/#if#-- ---------- BEGIN 字段循环遍历 ----------
#list table.fields as field
#if field.keyFlag#assign keyPropertyName${field.propertyName}/
/#if
#if field.comment!?length gt 0
#if swaggerApiModelProperty(${field.comment})
#else/*** ${field.comment}*/
/#if
/#if
#if field.keyFlag
#-- 主键 --
#if field.keyIdentityFlagTableId(value ${field.annotationColumnName}, type IdType.AUTO)
#elseif idType ??TableId(value ${field.annotationColumnName}, type IdType.${idType})
#elseif field.convertTableId(${field.annotationColumnName})
/#if
#-- 普通字段 --
#elseif field.fill??
#-- ----- 存在字段填充设置 -----
#if field.convertTableField(value ${field.annotationColumnName}, fill FieldFill.${field.fill})
#elseTableField(fill FieldFill.${field.fill})
/#if
#elseif field.convertTableField(${field.annotationColumnName})
/#if
#-- 乐观锁注解 --
#if field.versionFieldVersion
/#if
#-- 逻辑删除注解 --
#if field.logicDeleteFieldTableLogic
/#if#if field.propertyType Integervar ${field.propertyName}: Int? null#elsevar ${field.propertyName}: ${field.propertyType}? null/#if/#list
#-- ---------- END 字段循环遍历 ----------
#if entityColumnConstantcompanion object {
#list table.fields as fieldconst val ${field.name?upper_case} : String ${field.name}/#list}/#if
#if activeRecordoverride fun pkVal(): Serializable? {
#if keyPropertyName??return ${keyPropertyName}
#elsereturn null
/#if}/#ifoverride fun toString(): String {return ${entity}{
#list table.fields as field
#if field_index0${field.propertyName} ${field.propertyName}
#else, ${field.propertyName} ${field.propertyName}
/#if
/#list}}
}mapper.java.ftl
package ${package.Mapper};import ${package.Entity}.${entity};
import ${superMapperClassPackage};
#if mapperAnnotation
import org.apache.ibatis.annotations.Mapper;
/#if/*** p* ${table.comment!} Mapper 接口* /p** author ${author}* since ${date}*/
#if mapperAnnotation
Mapper
/#if
#if kotlin
interface ${table.mapperName} : ${superMapperClass}${entity}
#else
public interface ${table.mapperName} extends ${superMapperClass}${entity} {}
/#ifmapper.xml.ftl
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespace${package.Mapper}.${table.mapperName}#if enableCache!-- 开启二级缓存 --cache type${cacheClassName}//#if
#if baseResultMap!-- 通用查询映射结果 --resultMap idBaseResultMap type${package.Entity}.${entity}
#list table.fields as field
#if field.keyFlag#--生成主键排在第一位--id column${field.name} property${field.propertyName} /
/#if
/#list
#list table.commonFields as field#--生成公共字段 --result column${field.name} property${field.propertyName} /
/#list
#list table.fields as field
#if !field.keyFlag#--生成普通字段 --result column${field.name} property${field.propertyName} /
/#if
/#list/resultMap/#if
#if baseColumnList!-- 通用查询结果列 --sql idBase_Column_List
#list table.commonFields as field${field.columnName},
/#list${table.fieldNames}/sql/#if
/mapperservice.java.ftl
package ${package.Service};import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;/**
* p* ${table.comment!} 服务实现类* /p
*
* author ${author}
* since ${date}
*/
Service
public class ${table.serviceImplName} extends ${superServiceImplClass}${table.mapperName}, ${entity} {}5.2创建生成代码类CodeGenerator
package com.murg.bootdemo.util;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;/*** Generator生成代码**/
public class CodeGenerator {public static void main(String[] args) {generator();}public static void generator() {final String[] moduleName new String[1];FastAutoGenerator.create(new DataSourceConfig.Builder(jdbc:oracle:thin://127.0.0.1:1521/orcl,murg_test,654321))// 全局配置.globalConfig((scanner, builder) - builder.author(StringUtils.defaultString(getGitUsername(), codeGenerator)).fileOverride().outputDir(System.getProperty(user.dir) /src/main/java).disableOpenDir().enableSwagger().dateType(DateType.ONLY_DATE))// 包配置.packageConfig((scanner, builder) - builder.parent(com.murg.bootdemo. scanner.apply(请输入包名从 com.murg.bootdemo. 开始 )).xml(mapper).serviceImpl(service)).templateConfig((builder - builder.disable(TemplateType.SERVICE, TemplateType.CONTROLLER).serviceImpl(/templates/service.java)))// 策略配置.strategyConfig((scanner, builder) - builder.addInclude(getTables(scanner.apply(请输入表名多个英文逗号分隔所有输入 all).toUpperCase())).controllerBuilder().enableRestStyle().enableHyphenStyle().serviceBuilder().convertServiceImplFileName((entityName - entityName ConstVal.SERVICE)).entityBuilder().enableLombok().idType(IdType.INPUT).build()).templateEngine(new FreemarkerTemplateEngine())//.addIgnoreColumns(prseno) 排除某个字段.execute();}private static String getGitUsername() {Runtime runtime Runtime.getRuntime();Process exec;try {exec runtime.exec(git config user.name);} catch (IOException e) {e.printStackTrace();return null;}InputStreamReader inputStreamReader new InputStreamReader(exec.getInputStream());BufferedReader bufferedReader new BufferedReader(inputStreamReader);try {return bufferedReader.readLine();} catch (IOException e) {e.printStackTrace();return null;}}// 处理 all 情况protected static ListString getTables(String tables) {return all.equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(,));}
}5.3运行CodeGenerator 生成代码
点击左侧按钮 运行main方法控制台输出内容 按照控制台输出内容输入包名和表名多个表名用英文逗号分隔会在输入的包下生成文件 六、测试服务数据库连接 获取TT26相关数据
6.1启动类增加注解MapperScan 指定mapper扫描位置 MapperScan(com.murg.bootdemo.**.mapper)
package com.murg.bootdemo;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;MapperScan(com.murg.bootdemo.**.mapper)
SpringBootApplication
public class BootdemoApplication {public static void main(String[] args) {SpringApplication.run(BootdemoApplication.class, args);}} 6.2创建测试接口controller
引入Tt26Service 调用getOne方法查询数据库获取Tt26数据
getOne方法为MyBatis-Plus 通用IService使用不了解的同学可以了解一下MyBatis-Plus用法。
package com.murg.bootdemo.business.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.murg.bootdemo.business.entity.Tt26;
import com.murg.bootdemo.business.service.Tt26Service;
import com.murg.bootdemo.common.WebResult;
import lombok.RequiredArgsConstructor;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;RequiredArgsConstructor
RestController
public class TestRestController {private final RestTemplate restTemplate;private final Tt26Service tt26Service;RequestMapping(value /getTt26, method RequestMethod.GET)public Tt26 getTt26(RequestParam String code){//通过不同的id获取不同的namereturn tt26Service.getOne(Wrappers.Tt26lambdaQuery().eq(Tt26::getCode,code))}}启动服务访问接口测试结果