freemarket的语法知识: https://blog.csdn.net/ljk126wy/article/details/82978442
通过下面的方法可以自己自定义的去生成任何代码, 包括生成python、php代码
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class CodeGenerateUtils {
private final String AUTHOR = "<作者名称>";
private final String CURRENT_DATE = calendarToString();
private final String tableName = "<表名称>";
private final String packageName = "<包名称>";
private final String tableAnnotation = "<表描述>";
private final String URL = "<数据库连接地址>";
private final String USER = "<数据库账号>";
private final String PASSWORD = "<数据库密码>";
private final String DRIVER = "<数据库驱动>";
private final String diskPath = "D://"; //导出位置
private final String changeTableName = replaceUnderLineAndUpperCase(tableName);
public Connection getConnection() throws Exception{
Class.forName(DRIVER);
Connection connection= DriverManager.getConnection(URL, USER, PASSWORD);
return connection;
}
public static void main(String[] args) throws Exception{
CodeGenerateUtils codeGenerateUtils = new CodeGenerateUtils();
codeGenerateUtils.generate();
}
private static String calendarToString() {
Calendar calendar = Calendar.getInstance();
if (calendar == null) {
return null;
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// 设置你想要的格式
String dateStr = df.format(calendar.getTime());
return dateStr;
}
public static String replaceUnderLineAndUpperCase(String str){
//处理第一个下划线前字符串不超过两个时候删除
String[] splits = str.split("_");
Integer i = 0;
if (splits[0].length() < 3) {
for (char c : str.toCharArray()) {
if (c == UNDERLINE) {
++i;
break;
} else {
++i;
}
}
str = str.substring(i);
}
StringBuffer sb = new StringBuffer();
sb.append(str);
int count = sb.indexOf("_");
while(count!=0){
int num = sb.indexOf("_",count);
count = num + 1;
if(num != -1){
char ss = sb.charAt(count);
char ia = (char) (ss - 32);
sb.replace(count , count + 1,ia + "");
}
}
String result = sb.toString().replaceAll("_","");
return StringUtils.capitalize(result);
}
private static final char UNDERLINE='_';
//驼峰转换
public static String underlineToCamel(String param){
if (param==null||"".equals(param.trim())){
return "";
}
int len=param.length();
StringBuilder sb=new StringBuilder(len);
for (int i = 0; i < len; i++) {
char c = Character.toLowerCase(param.charAt(i));
if (c == UNDERLINE){
if (++i<len){
sb.append(Character.toUpperCase(param.charAt(i)));
}
}else{
sb.append(c);
}
}
return sb.toString();
}
List<Map<String, Object>> mapList;
public void generate() throws Exception{
try {
Connection connection = getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null,"%", tableName,"%")
//生成Mapper文件(该方法必须启用)
generateMapperFile(resultSet);
//生成DTO文件
generateDTOFile(resultSet);
//生成Dao文件
generateMapperInterfaceFile(resultSet);
//生成Repository文件
//generateRepositoryFile(resultSet);
//生成服务层接口文件
generateServiceInterfaceFile(resultSet);
//生成服务实现层文件
generateServiceImplFile(resultSet);
//生成Controller层文件
//generateControllerFile(resultSet);
} catch (Exception e) {
throw new RuntimeException(e);
}finally{
}
}
private void generateModelFile(ResultSet resultSet) throws Exception{
final String suffix = ".java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Model.ftl";
File mapperFile = new File(path);
List<ColumnClass> columnClassList = new ArrayList<>();
ColumnClass columnClass = null;
while(resultSet.next()){
//id字段略过
if(resultSet.getString("COLUMN_NAME").equals("id")) continue;
columnClass = new ColumnClass();
//获取字段名称
columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
//获取字段类型
columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
//转换字段名称,如 sys_name 变成 SysName
columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
//字段在数据库的注释
columnClass.setColumnComment(resultSet.getString("REMARKS"));
columnClassList.add(columnClass);
}
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("model_column",columnClassList);
generateFileByTemplate(templateName,mapperFile,resultSet);
}
private String suitTypeName(String TYPE_NAME){
String res = TYPE_NAME;
switch (TYPE_NAME){
case "CHAR":
res = "VARCHAR";
break;
case "DATETIME":
res = "TIMESTAMP";
break;
case "INT":
res = "INTEGER";
break;
case "JSON":
res = "BLOB";
break;
}
return res;
}
//获取数据库中每个字段的信息
private List<Map<String,Object>> getDataMap(ResultSet resultSet) throws SQLException {
List<Map<String, Object>> tempList = new ArrayList<Map<String, Object>>();
while(resultSet.next()) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("COLUMN_NAME", resultSet.getString("COLUMN_NAME"));//表字段名称
map.put("DATA_TYPE", resultSet.getString("DATA_TYPE")); //字段类型
map.put("TYPE_NAME",suitTypeName(resultSet.getString("TYPE_NAME")));//字段类型名称
map.put("COLUMN_SIZE", resultSet.getString("COLUMN_SIZE"));//字段大小
map.put("NULLABLE", resultSet.getString("NULLABLE"));//是否为空
map.put("REMARKS", resultSet.getString("REMARKS"));//表的注释
//转换为驼峰后字段名称
map.put("humpName", underlineToCamel(resultSet.getString("COLUMN_NAME")));
map.put("POJO_TYPE_NAME", getPojoType(resultSet.getString("TYPE_NAME")));//字段对应的实体类的名称
//实体类与sql类转换
tempList.add(map);
System.out.println(map);
}
return tempList;
}
//生成对应的类型名称
private String getPojoType(String type_name) {
String res = "";
switch (type_name){
case "TINYINT":
res = "Integer";
break;
case "SMALLINT":
res = "Integer";
break;
case "MEDIUMINT":
res = "Integer";
break;
case "INT":
res = "Integer";
break;
case "BIGINT":
res = "Long";
break;
case "FLOAT":
res = "Float";
break;
case "DOUBLE":
res = "Double";
break;
case "DECIMAL":
res = "BigDecimal";
break;
case "DATETIME":
res = "Date";
break;
case "CHAR":
res = "String";
break;
case "VARCHAR":
res = "String";
break;
case "TINYBLOB":
res = "String";
break;
case "TINYTEXT":
res = "String";
break;
case "BLOB":
res = "String";
break;
case "TEXT":
res = "String";
break;
case "MEDIUMBLOB":
res = "String";
break;
case "LONGTEXT":
res = "String";
break;
case "MEDIUMTEXT":
res = "String";
break;
case "JSON":
res = "String";
break;
}
return res;
}
private void generateDTOFile(ResultSet resultSet) throws Exception{
final String suffix = ".java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "DTO.ftl";
File mapperFile = new File(path);
generateFileByTemplate(templateName,mapperFile,resultSet);
}
/*private void generateControllerFile(ResultSet resultSet) throws Exception{
final String suffix = "Controller.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Controller.ftl";
File mapperFile = new File(path);
Map dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,resultSet);
}*/
private void generateServiceImplFile(ResultSet resultSet) throws Exception{
final String suffix = "ServiceImpl.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "ServiceImpl.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,resultSet);
}
private void generateServiceInterfaceFile(ResultSet resultSet) throws Exception{
//final String prefix = "I";
final String suffix = "Service.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "ServiceInterface.ftl";
File mapperFile = new File(path);
Map<String,Object> dataMap = new HashMap<>();
generateFileByTemplate(templateName,mapperFile,resultSet);
}
private void generateMapperInterfaceFile(ResultSet resultSet) throws Exception{
final String suffix = "Mapper.java";
final String path = diskPath + changeTableName + suffix;
final String templateName = "MapperInterface.ftl";
File mapperFile = new File(path);
generateFileByTemplate(templateName,mapperFile,resultSet);
}
private void generateMapperFile(ResultSet resultSet) throws Exception{
final String suffix = "Mapper.xml";
final String path = diskPath + changeTableName + suffix;
final String templateName = "Mapper.ftl";
File mapperFile = new File(path);
mapList = getDataMap(resultSet);
generateFileByTemplate(templateName,mapperFile,resultSet);
}
private void generateFileByTemplate(final String templateName,File file,ResultSet resultSet) throws Exception{
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("mapList", mapList);
Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
FileOutputStream fos = new FileOutputStream(file);
dataMap.put("table_name_small",tableName);
dataMap.put("table_name",changeTableName);
dataMap.put("author",AUTHOR);
dataMap.put("date",CURRENT_DATE);
dataMap.put("package_name",packageName);
dataMap.put("table_annotation",tableAnnotation);
Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"),10240);
template.process(dataMap,out); //dataMap就是向模板引擎进行传值
}
获取字段的基本信息
import lombok.Data;//需要引入lombok依赖
@Data
public class ColumnClass {
/** 数据库字段名称 **/
private String columnName;
/** 数据库字段类型 **/
private String columnType;
/** 数据库字段首字母小写且去掉下划线字符串 **/
private String changeColumnName;
/** 数据库字段注释 **/
private String columnComment;
}
调用FreeMarkerTemplate模板引擎
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.NullCacheStorage;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import java.io.IOException;
public class FreeMarkerTemplateUtils {
private FreeMarkerTemplateUtils(){}
private static final Configuration CONFIGURATION = new Configuration(Configuration.VERSION_2_3_22);
static{
//这里比较重要,用来指定加载模板所在的路径(最好是把模板文件放在source目录下的templates中)
CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreeMarkerTemplateUtils.class, "/templates"));
CONFIGURATION.setDefaultEncoding("UTF-8");
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
CONFIGURATION.setCacheStorage(NullCacheStorage.INSTANCE);
}
public static Template getTemplate(String templateName) throws IOException {
try {
return CONFIGURATION.getTemplate(templateName);
} catch (IOException e) {
throw e;
}
}
public static void clearCache() {
CONFIGURATION.clearTemplateCache();
}
}
模板文件必须放在resource目录下,否则会找不到
模板的名称为DTO.ftl
package ${package_name}.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @描述 ${table_annotation}
* @author ${author}
* @date ${date}
*/
@Data
public class ${table_name} implements Serializable{
private static final long serialVersionUID = 1L;
<#list mapList as map>
//${map.REMARKS}
private ${map.POJO_TYPE_NAME} ${map.humpName};
#list>
}
文件的名称必须为: Mapper.ftl
详细解释一下Mapper文件:
${package_name}: 包名称
${table_name}: 表名称
<#list mapList as map> : mapList为字段的List集合, 内部可以循环遍历所有字段
${map.COLUMN_NAME}: 字段名称
${map_index} : List的索引位置
${map.humpName}: 字段的驼峰名称
<#list mapList as map>
#list>
<#list mapList as map>${map.COLUMN_NAME}<#if mapList?size!=(map_index+1)>,#if>#list>
<#list mapList as map>
and ${map.humpName} != ''#if>">
<#if 0!=(map_index)>and#if> ${map.COLUMN_NAME} = ${r'#{'}${map.humpName}${r'}'}
#list>
select from ${table_name_small} order by update_time desc
SELECT LAST_INSERT_ID()
insert into ${table_name_small} (
<#list mapList as map>
and ${map.humpName} != ''#if>">
${map.COLUMN_NAME}<#if mapList?size!=(map_index+1)>,#if>
#list>
) values (
<#list mapList as map>
and ${map.humpName} != ''#if>">
${r'#{'}${map.humpName},jdbcType=${map.TYPE_NAME}${r'}'}<#if mapList?size!=(map_index+1)>,#if>
#list>
)
update ${table_name_small}
<#list mapList as map>
and ${map.humpName} != ''#if>">
${map.COLUMN_NAME} = ${r'#{'}${map.humpName},jdbcType=${map.TYPE_NAME}${r'}'}<#if mapList?size!=(map_index+1)>,#if>
#list>
${mapList[0].COLUMN_NAME} = ${r'#{'}${mapList[0].humpName}${r'}'}
delete from ${table_name_small}
${mapList[0].COLUMN_NAME} = ${r'#{'}${mapList[0].humpName}${r'}'}
文件名称为 MapperInterface.ftl
import ${package_name}.entity.${table_name};
import java.util.HashMap;
import java.util.List;
/**
* 描述:${table_annotation} 服务实现层接口
* @author ${author}
* @date ${date}
*/
public interface ${table_name}Mapper {
${table_name} selectByPrimaryKey(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName});
List<${table_name}> selectByPrimaryKeys(List<${mapList[0].POJO_TYPE_NAME}> ${mapList[0].humpName}s);
${table_name} selectByHashMap(HashMap hashMap);
List<${table_name}> selectList(HashMap hashMap);
int insertOne(${table_name} ${table_name?uncap_first}) ;
int deleteByPrimaryKey(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName});
int updateById(${table_name} ${table_name?uncap_first});
}
文件名称为: ServiceInterface.ftl
import ${package_name}.entity.${table_name};
import com.github.pagehelper.PageInfo;
import java.util.HashMap;
import java.util.List;
/**
* 描述:${table_annotation} 服务实现层接口
* @author ${author}
* @date ${date}
*/
public interface ${table_name}Service {
/**
* @描述 根据主键查询
* @param ${mapList[0].humpName} 主键
* @data ${date}
*/
${table_name} findById(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName});
/**
* @描述 根据多个主键查询
* @param ${mapList[0].humpName}s 主键集合
* @data ${date}
*/
List<${table_name}> findByIds(List<${mapList[0].POJO_TYPE_NAME}> ${mapList[0].humpName}s);
/**
* @描述 根据hashMap进行条件查询
* @param hashMap 传入的键值对
* @data ${date}
*/
${table_name} findByHashMap(HashMap hashMap);
/**
* @描述 查询列表
* @param hashMap 传入的键值对
* @data ${date}
*/
PageInfo findList(HashMap hashMap,PageInfo pageInfo);
/**
* @描述 插入数据
* @param ${table_name?uncap_first} 传入的Model
* @data ${date}
*/
${mapList[0].POJO_TYPE_NAME} create(${table_name} ${table_name?uncap_first}) ;
/**
* @描述 根据主键删除
* @param ${mapList[0].humpName} 主键
* @data ${date}
*/
int deleteById(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName});
/**
* @描述 根据主键更新
* @param ${table_name?uncap_first} 传入Model
* @data ${date}
*/
int updateById(${table_name} ${table_name?uncap_first}) ;
}
文件名称为: ServiceImpl.ftl
import com.github.pagehelper.PageHelper;
import ${package_name}.entity.${table_name};
import ${package_name}.service.${table_name}Service;
import ${package_name}.mapper.${table_name}Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ${package_name}.entity.${table_name};
import org.springframework.beans.BeanUtils;
import com.github.pagehelper.PageInfo;
import java.util.HashMap;
import java.util.List;
/**
* 描述:${table_annotation} 服务实现层
* @author ${author}
* @date ${date}
*/
@Service
public class ${table_name}ServiceImpl implements ${table_name}Service {
@Autowired
private ${table_name}Mapper ${table_name?uncap_first}Mapper;
@Override
public ${table_name} findById(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName}) {
return ${table_name?uncap_first}Mapper.selectByPrimaryKey(${mapList[0].humpName});
}
@Override
public List<${table_name}> findByIds(List<${mapList[0].POJO_TYPE_NAME}> ${mapList[0].humpName}s) {
List<${table_name}> ${table_name?uncap_first}List = ${table_name?uncap_first}Mapper.selectByPrimaryKeys(${mapList[0].humpName}s);
return ${table_name?uncap_first}List;
}
@Override
public ${table_name} findByHashMap(HashMap hashMap) {
${table_name} ${table_name?uncap_first} = ${table_name?uncap_first}Mapper.selectByHashMap(hashMap);
return ${table_name?uncap_first};
}
@Override
public PageInfo findList(HashMap hashMap,PageInfo pageInfo) {
PageHelper.startPage(pageInfo.getPageNum(), pageInfo.getPageSize());
List<${table_name}> ${table_name?uncap_first}List = ${table_name?uncap_first}Mapper.selectList(hashMap);
pageInfo = new PageInfo<${table_name}>(${table_name?uncap_first}List);
return pageInfo;
}
@Override
public ${mapList[0].POJO_TYPE_NAME} create(${table_name} model){
${table_name} ${table_name?uncap_first} = new ${table_name}();
BeanUtils.copyProperties(model,${table_name?uncap_first});
int result = ${table_name?uncap_first}Mapper.insertOne(${table_name?uncap_first});
if(result == 0)
throw new RuntimeException("更新失败,更新结果数为0");
return ${table_name?uncap_first}.get${mapList[0].humpName?cap_first}();
}
@Override
public int updateById(${table_name} model) {
${table_name} ${table_name?uncap_first} = new ${table_name}();
BeanUtils.copyProperties(model,${table_name?uncap_first});
int result = ${table_name?uncap_first}Mapper.updateById(${table_name?uncap_first});
if(result == 0)
throw new RuntimeException("更新失败,更新结果数为0");
return result;
}
@Override
public int deleteById(${mapList[0].POJO_TYPE_NAME} ${mapList[0].humpName}){
int result =${table_name?uncap_first}Mapper.deleteByPrimaryKey(${mapList[0].humpName});
if(result == 0)
throw new RuntimeException("更新失败,更新结果数为0");
return result;
}
}