重复的写相同的crud代码没有任何意义,为了提高基础代码书写效率可以使用代码生成器。
代码生成器是一个工具,用于生成通用的基础代码。是使用 mybatis-plus 和 velocity 来实现的
velocity是一个模板引擎,与jsp,freemarker,thymeleaf类似。
第一步:导入依赖
<!--代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<!--模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
第二步:添加配置文件
#此处为本项目src所在路径(代码生成器输出路径),注意一定是当前项目所在的目录哟
OutputDir=E:\\Java\\IdeaProjects\\项目名\\src\\main\\java
#mapper.xml SQL映射文件目录
OutputDirXml=E:\\Java\\IdeaProjects\\项目名\\src\\main\\resources
#设置作者
author=myltakema
#自定义包路径
parent=
#数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///?useUnicode=true&characterEncoding=utf8
jdbc.user=
jdbc.pwd=
第三步:设置模板templates
controller.java.vm
package ${package.Controller};
import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};
import ${cfg.parent}.query.${entity}Query;
import com.nanrui.basic.util.AjaxResult;
import com.nanrui.basic.util.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 后端接口类;
*/
@RestController
@RequestMapping("/${table.entityPath}")
public class ${entity}Controller {
@Autowired
public ${table.serviceName} ${table.entityPath}Service;
/**
* 接口:添加或修改
* @param ${table.entityPath} 传递的实体
* @return AjaxResult 响应给前端
*/
@PutMapping
public AjaxResult addOrUpdate(@RequestBody ${entity} ${table.entityPath}){
if( ${table.entityPath}.getId()!=null){
${table.entityPath}Service.update(${table.entityPath});
}else{
${table.entityPath}Service.add(${table.entityPath});
}
return new AjaxResult();
}
/**
* 接口:删除
* @param id
* @return AjaxResult 响应给前端
*/
@DeleteMapping(value="/{id}")
public AjaxResult delete(@PathVariable("id") Long id){
${table.entityPath}Service.delete(id);
return new AjaxResult();
}
/**
* 接口:批量删除
* @param ids
* @return AjaxResult 响应给前端
*/
@PatchMapping
public AjaxResult batchDel(@RequestBody List<Long> ids){
${table.entityPath}Service.batchDel(ids);
return new AjaxResult();
}
/**
* 接口:查询单个对象
* @param id
*/
@GetMapping("/{id}")
public ${entity} findOne(@PathVariable("id")Long id) {
return ${table.entityPath}Service.findOne(id);
}
/**
* 接口:查询所有
* @return
*/
@GetMapping
public List<${entity}> findAll(){
return ${table.entityPath}Service.findAll();
}
/**
* 接口:分页查询或高级查询
* @param query 查询对象
* @return PageList 分页对象
*/
@PostMapping
public PageInfo<${entity}> page(@RequestBody ${entity}Query query) {
return ${table.entityPath}Service.page(query);
}
}
entity.java.vm
package ${package.Entity};
import java.math.BigDecimal;
import java.util.Date;
import com.nanrui.basic.domain.BaseDomain;
#if(${entityLombokModel})
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#end
/**
* 实体类:$!{table.comment}
*/
#if(${entityLombokModel})
@Data
#if(${superEntityClass})
@EqualsAndHashCode(callSuper = true)
#end
@Accessors(chain = true)
#end
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}{
#elseif(${activeRecord})
public class ${entity} extends Model<${entity}> {
#else
public class ${entity} implements Serializable {
#end
## ---------- BEGIN 字段循环遍历 ----------
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
/**
* ${field.comment}
*/
#end
## 乐观锁注解
#if(${versionFieldName}==${field.name})
@Version
#end
## 逻辑删除注解
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
private ${field.propertyType} ${field.propertyName};
#end
## ---------- END 字段循环遍历 ----------
#if(!${entityLombokModel})
#foreach($field in ${table.fields})
#if(${field.propertyType.equals("boolean")})
#set($getprefix="is")
#else
#set($getprefix="get")
#end
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
#if(${entityBuilderModel})
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#else
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#end
this.${field.propertyName} = ${field.propertyName};
#if(${entityBuilderModel})
return this;
#end
}
#end
#end
#if(${entityColumnConstant})
#foreach($field in ${table.fields})
public static final String ${field.name.toUpperCase()} = "${field.name}";
#end
#end
#if(!${entityLombokModel})
@Override
public String toString() {
return "${entity}{" +
#foreach($field in ${table.fields})
#if($!{velocityCount}==1)
"${field.propertyName}=" + ${field.propertyName} +
#else
", ${field.propertyName}=" + ${field.propertyName} +
#end
#end
"}";
}
#end
}
mapper.xml.vm
<?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="${package.Mapper}.${table.mapperName}">
<!--添加对象-->
<insert id="add" parameterType="${entity}" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into ${table.name}(
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
#if($foreach.count != $table.fields.size())
${field.name},
#else
${field.name}
#end
#end
#end
) values(
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
#if($foreach.count != $table.fields.size())
#if(${field.name} == ${field.propertyName})#{${field.name}}#else#{${field.propertyName}}#end,
#else
#if(${field.name} == ${field.propertyName})#{${field.name}}#else#{${field.propertyName}}#end
#end
#end
#end
)
</insert>
<!--删除对象-->
<delete id="delete" parameterType="long">
delete from ${table.name} where id = #{id}
</delete>
<!--更新对象-->
<update id="update" parameterType="${entity}">
update ${table.name}
set
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
#if($foreach.count != $table.fields.size())
${field.name} = #if(${field.name} == ${field.propertyName})#{${field.name}}#else#{${field.propertyName}}#end,
#else
${field.name} = #if(${field.name} == ${field.propertyName})#{${field.name}}#else#{${field.propertyName}}#end
#end
#end
#end
where id = #{id}
</update>
<!--查找单个对象-->
<select id="findOne" resultMap="BaseResultMap" parameterType="long">
select * from ${table.name} where id = #{id}
</select>
<!--查找所有对象-->
<select id="findAll" resultMap="BaseResultMap">
select * from ${table.name}
</select>
<!--查询总数=参数(查询对象),返回值:long-->
<select id="queryCount" parameterType="${entity}Query" resultType="integer">
select count(*) from ${table.name}
<include refid="pageWhere"/>
</select>
<!--查询当前页数据=参数(查询对象),返回值:List-->
<select id="page" parameterType="${entity}Query" resultMap="BaseResultMap">
select * from ${table.name}
<include refid="pageWhere"/>
limit #{begin},#{pageSize}
</select>
<sql id="pageWhere">
<where>
<if test="keyword!=null and keyword!=''">
and (name like concat('%',#{keyword},'%'))
</if>
</where>
</sql>
<!--批量删除-->
<delete id="batchDel" parameterType="arraylist">
delete from ${table.name} where id in
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
#if(${enableCache})
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
#end
#if(${baseResultMap})
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
#foreach($field in ${table.commonFields})
#if(${field.keyFlag})##生成主键排在第一位
<id column="${field.name}" property="${field.propertyName}" />
#end
#end
#foreach($field in ${table.fields})
#if(!${field.keyFlag})##生成普通字段
<result column="${field.name}" property="${field.propertyName}" />
#end
#end
</resultMap>
#end
</mapper>
query.java.vm
package ${cfg.parent}.query;
import com.nanrui.basic.query.BaseQuery;
/**
* 查询类:
*/
public class ${table.entityName}Query extends BaseQuery{
}
serviceimpl.java.vm
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
/**
* 业务实现类:$!{table.comment}
*/
@Service
#if(${kotlin})
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
}
#else
public class ${table.serviceImplName} extends ${superServiceImplClass}<${entity}> implements ${table.serviceName} {
}
#end
生成表的代码:
package com.nanrui.generator;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;ss
import java.util.*;
/**
* Created by CDHong on 2018/4/6.
*/
public class GenteratorCode {
public static void main(String[] args) throws InterruptedException {
//用来获取Mybatis-Plus.properties文件的配置信息
ResourceBundle rb = ResourceBundle.getBundle("mybatitsPlus-config"); //不要加后缀
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(rb.getString("OutputDir"));
gc.setFileOverride(true);
gc.setActiveRecord(true);// 开启 activeRecord 模式
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(true);// XML columList
gc.setAuthor(rb.getString("author"));
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert());
dsc.setDriverName(rb.getString("jdbc.driver"));
dsc.setUsername(rb.getString("jdbc.user"));
dsc.setPassword(rb.getString("jdbc.pwd"));
dsc.setUrl(rb.getString("jdbc.url"));
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setTablePrefix(new String[] { "t_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[]{""}); // 需要生成的表
strategy.setSuperEntityClass("com.nanrui.basic.domain.BaseDomain");
strategy.setSuperServiceClass("com.nanrui.basic.service.IBaseService");
strategy.setSuperServiceImplClass("com.nanrui.basic.service.impl.BaseServiceImpl");
strategy.setSuperMapperClass("com.nanrui.basic.mapper.BaseMapper");
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent(rb.getString("parent"));
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("domain");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-rb");
map.put("parent", pc.getParent());
this.setMap(map);
}
};
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
String parentPath = "/"+pc.getParent().replaceAll("\\.","/")+"/";
System.out.println(parentPath);
// 调整 domain 生成目录演示
focList.add(new FileOutConfig("/templates/entity.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDir")+ parentPath+"domain/" + tableInfo.getEntityName() + ".java";
}
});
//query
focList.add(new FileOutConfig("/templates/query.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDir")+ parentPath+"query/" + tableInfo.getEntityName() + "Query.java";
}
});
// 调整 xml 生成目录演示
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return rb.getString("OutputDirXml")+ parentPath+"mapper/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改,
// 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称
TemplateConfig tc = new TemplateConfig();
tc.setService("/templates/service.java.vm");
tc.setServiceImpl("/templates/serviceImpl.java.vm");
tc.setEntity("/templates/entity.java.vm");
tc.setMapper("/templates/mapper.java.vm");
//tc.setController(null);
tc.setXml(null);
// 如上任何一个模块如果设置 空 OR Null 将不生成该模块。
mpg.setTemplate(tc);
// 执行生成
mpg.execute();
}
}
代码自动生成工具生成的domain实体对象的属性名字,如果遇到数据库列名是下划线,它会转成驼峰
使用到的工具类
package com.nanrui.basic.util;
import lombok.Data;
@Data
public class AjaxResult {
//接口状态(true:成功;false:失败)
private Boolean success = true;
//返回前端的提示信息(成功)
private String message = "操作成功";
private String code = "0";
//存储返回给前端的数据
private Object data = null;
public AjaxResult() {
}
//链式语法改造
public static AjaxResult success(){
return new AjaxResult();
}
public static AjaxResult success(String code,String message){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setCode(code);
ajaxResult.setMessage(message);
return ajaxResult;
}
public static AjaxResult success(String code,String message,Object data){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setCode(code);
ajaxResult.setMessage(message);
ajaxResult.setData(data);
return ajaxResult;
}
public static AjaxResult success(Object data){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setData(data);
return ajaxResult;
}
public static AjaxResult error(String code,String message){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setSuccess(false);
ajaxResult.setCode(code);
ajaxResult.setMessage(message);
return ajaxResult;
}
public static AjaxResult error(String code, String message, Object data){
AjaxResult ajaxResult = new AjaxResult();
ajaxResult.setSuccess(false);
ajaxResult.setMessage(message);
ajaxResult.setCode(code);
ajaxResult.setData(data);
return ajaxResult;
}
}
package com.nanrui.basic.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageInfo<T> {
private Integer totals = 0;
private List<T> data = new ArrayList<>();
}