神兽坐镇!!
...
...
OK,进入主题,上篇说到了代码生成工具,只是演示了一下简单的操作流程。那么,说好了,这篇是贴码文,在贴码之前先大体说下原理吧(大神止步吧...)......
说到需要生成文件,不得不说说在项目开发中那些让码农们头疼的事:在项目开发中最让人头疼的就是把数据库表字段对应成java实体属性,一个数据库如果有几十个表,单单靠手写java实体的话,等项目上线了,估计实体刚建完...
再一个就是对数据库进行操作的mapper文件,一般的业务上都包括增删改查(批/单),以及对应实体的resultMap定义。此项工作如果没有工具的帮助,就相当于重复造轮子。因为增删改查(批/单)区别就在于表名不同、resultMap区别就在于字段不同
......
以上只是简单的举证了一下(不要嫌俺啰嗦,俺只是深恶痛绝...),说回俺这个代码生成工具,原理莫过于获取系统中的数据库列表,根据数据库获取单个数据库下的所有数据表,最后一步是最重要也是最麻烦的,要获取数据表中的字段、字段类型、字段注释等等,因为要根据字段类型生成对应的java类型变量。
(神马~~!!这TM就是所谓的原理?酱简单?你TM是不是唬我?)
没错,就是这么简单,天地良心
下面到重点部分了,贴码!!
- 获取所有数据库
/**
* @Description 获取数据库列表
* @author zhangyd
* @date 2015年12月9日 上午10:17:33
* @param mybatisSqlForm
* @return
*/
public List<String> getDbNameList(TableForm mybatisSqlForm) {
List<String> list = new ArrayList<String>();
ResultSet rs = null;
Connection conn = null;
Statement statement = null;
try {
String sql = "show databases";
rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
mybatisSqlForm.getDbPassword(), sql.toString());
while (rs.next()) {
list.add(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
获取数据库也是用的最基本的sql语句:show databases;
- 获取数据库表列表
/**
* @Description 获取数据库表列表
* @author zhangyd
* @date 2015年12月9日 上午10:17:46
* @param mybatisSqlForm
* @return
*/
public List<String> getTableNameList(TableForm mybatisSqlForm) {
List<String> list = new ArrayList<String>();
ResultSet rs = null;
Connection conn = null;
Statement statement = null;
try {
String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '"
+ mybatisSqlForm.getSelectedDbNames() + "'";
rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
mybatisSqlForm.getDbPassword(), sql.toString());
while (rs.next()) {
list.add(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
- 获取字段名 列表
/**
* @Description 获取字段名 列表
* @author zhangyd
* @date 2015年12月9日 上午10:18:07
* @param mybatisSqlForm
* @return
*/
public List<String> getColumnNameList(TableForm mybatisSqlForm) {
List<String> columnNames = new ArrayList<String>();
ResultSet rs = null;
Connection conn = null;
Statement statement = null;
try {
StringBuffer sql = new StringBuffer();
sql.append(
"SELECT DISTINCT column_name cloumnName,data_type type,column_comment comment,column_key FROM Information_schema.COLUMNS ");
sql.append("WHERE TABLE_NAME = '" + mybatisSqlForm.getSelectedTableNames() + "' and TABLE_SCHEMA = '"
+ mybatisSqlForm.getSelectedDbNames() + "'");
rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
mybatisSqlForm.getDbPassword(), sql.toString());
while (rs.next()) {
columnNames.add(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return columnNames;
}
- 获取数据表详情(字段类型、注释等)
/**
* @Description 获取数据表详情
* @author zhangyd
* @date 2015年12月9日 上午10:19:19
* @param mybatisSqlForm
* @return
*/
public List<Variable> getTableInfo(TableForm mybatisSqlForm) {
List<Variable> tableInfo = new ArrayList<Variable>();
Connection conn = null;
Statement statement = null;
ResultSet rs = null;
try {
StringBuffer sql = new StringBuffer();
sql.append(
"SELECT DISTINCT column_name cloumnName,data_type type,column_comment comment,column_key FROM Information_schema.COLUMNS ");
sql.append("WHERE TABLE_NAME = '" + mybatisSqlForm.getSelectedTableNames() + "' and TABLE_SCHEMA = '"
+ mybatisSqlForm.getSelectedDbNames() + "'");
rs = getResultSet(conn, statement, mybatisSqlForm.getDbAddress(), mybatisSqlForm.getDbLoginName(),
mybatisSqlForm.getDbPassword(), sql.toString());
while (rs.next()) {
Variable variable = new Variable();
variable.setColumnName(rs.getString("cloumnName"));
variable.setType(rs.getString("type"));
variable.setComment(rs.getString("comment"));
variable.setColumnKey(rs.getString("column_key"));
tableInfo.add(variable);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (statement != null)
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return tableInfo;
}
- 以下这一段代码是以上三段代码需要用到的公共方法
/**
* @Description 请求数据库链接,获取返回结果集
* @author zhangyd
* @date 2015年12月9日 上午10:32:22
* @param dbAddress
* @param userName
* @param passWord
* @param sql
* @return
*/
public ResultSet getResultSet(Connection conn, Statement statement, String dbAddress, String userName,
String passWord, String sql) {
ResultSet rs = null;
try {
conn = DriverManager.getConnection(getDbUrl(dbAddress), userName, passWord);
statement = conn.createStatement();
rs = statement.executeQuery(sql.toString());
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
public String getDbUrl(String dbAddress) {
return "jdbc:mysql://" + dbAddress + "?useUnicode=true&characterEncoding=utf-8";
}
- 生成java文件相关业务实现
/**
* @Title: GenerationClassServiceImpl.java
* @Package: com.maven.web.service.generation.impl
* @Description: TODO
* @author zhangyd
* @date 2015年11月16日 下午5:54:28
* @version 1.0
*/
package com.maven.web.service.generation.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.maven.web.dao.generation.GenerationMapperDao;
import com.maven.web.entity.generation.TableForm;
import com.maven.web.entity.generation.Variable;
import com.maven.web.service.generation.IGenerationClassService;
import com.maven.web.utils.FileUtil;
import com.maven.web.utils.StringUtil;
import com.maven.web.utils.memcache.MemcachedUtil;
/**
* @Description 生成java文件业务实现
* @author zhangyd
* @date 2015年12月18日 下午4:54:13
* @version V1.0
* @since JDK : 1.7
* @modify
* @Review
*/
@Service
public class GenerationClassServiceImpl implements IGenerationClassService {
@Autowired
private GenerationMapperDao generationMapperDao;
// 数据库数据类型、java数据类型映射map
private static Map<String, String> dataTypeMapping = new HashMap<String, String>();
// 初始化数据库类型与java类型转换
static {
dataTypeMapping.put("int", "int");
dataTypeMapping.put("tinyint", "int");
dataTypeMapping.put("smallint", "int");
dataTypeMapping.put("mediumint", "int");
dataTypeMapping.put("integer", "int");
dataTypeMapping.put("bigint", "long");
dataTypeMapping.put("bit", "boolean");
dataTypeMapping.put("real", "float");
dataTypeMapping.put("double", "double");
dataTypeMapping.put("float", "float");
dataTypeMapping.put("float", "float");
dataTypeMapping.put("decimal", "BigDecimal");
dataTypeMapping.put("numeric", "BigDecimal");
dataTypeMapping.put("char", "String");
dataTypeMapping.put("varchar", "String");
dataTypeMapping.put("date", "java.util.Date");
dataTypeMapping.put("time", "java.util.Time");
dataTypeMapping.put("year", "java.util.Date");
dataTypeMapping.put("timestamp", "java.util.Timestamp");
dataTypeMapping.put("datetime", "java.util.Date");
dataTypeMapping.put("tinyblob", "byte[]");
dataTypeMapping.put("blob", "byte[]");
dataTypeMapping.put("mediumblob", "byte[]");
dataTypeMapping.put("longblob", "byte[]");
dataTypeMapping.put("tinytext", "String");
dataTypeMapping.put("text", "String");
dataTypeMapping.put("mediumtext", "String");
dataTypeMapping.put("longtext", "String");
dataTypeMapping.put("binary", "byte[]");
}
/**
* @Description 生成java实体
* @author zhangyd
* @date 2015年12月9日 上午10:11:17
* @param tableForm
* @return
*/
@Override
public Map<String, Object> getJava(TableForm tableForm) {
List<Variable> tableInfo = generationMapperDao.getTableInfo(tableForm);
Map<String, Object> sqlMap = new HashMap<String, Object>();
String sqlString = createJava(tableInfo, tableForm);
sqlMap.put("list", sqlString);
return sqlMap;
}
/**
* @Description 创建java实体字符串
* @author zhangyd
* @date 2015年12月9日 上午10:11:22
* @param tableInfo
* @param tableForm
* @return
*/
@Override
public String createJava(List<Variable> tableInfo, TableForm tableForm) {
StringBuilder sb = new StringBuilder();
// 包名
String packageString = createPackage(tableForm.getEntityPackage());
sb.append(packageString);
// class
String classString = createClass(tableForm.getSelectedTableNames());
sb.append(classString);
// 变量
String variablesString = createVariables(tableInfo);
sb.append(variablesString);
// SetAndGet
String SetAndGetString = createSetAndGet(tableInfo);
sb.append(SetAndGetString);
// 尾部
String tailString = createTail();
sb.append(tailString);
return sb.toString();
}
/**
* @Description 创建包信息
* @author zhangyd
* @date 2015年12月9日 上午10:11:28
* @param packagePath
* @return
*/
@Override
public String createPackage(String packagePath) {
StringBuilder sb = new StringBuilder();
sb.append("package " + packagePath + ";<br><br>");
return sb.toString();
}
/**
* @Description 创建导入信息
* @author zhangyd
* @date 2015年12月9日 上午10:11:33
* @return
*/
@Override
public String createImport() {
StringBuilder sb = new StringBuilder();
sb.append("<br>");
return sb.toString();
}
/**
* @Description 创建class名
* @author zhangyd
* @date 2015年12月9日 上午10:11:39
* @param tableName
* @return
*/
@Override
public String createClass(String tableName) {
StringBuilder sb = new StringBuilder();
String[] temps = tableName.split("_");
tableName = temps[0];
for (int i = 1; i < temps.length; i++) {
tableName += StringUtil.initialtoUpper(temps[i]);
}
sb.append("public class " + StringUtil.initialtoUpper(tableName) + " {<br>");
return sb.toString();
}
/**
* @Description 创建变量
* @author zhangyd
* @date 2015年12月9日 上午10:11:55
* @param tableInfo
* @return
*/
@Override
public String createVariables(List<Variable> tableInfo) {
StringBuilder sb = new StringBuilder();
for (Variable variable : tableInfo) {
if (StringUtil.isNotEmpty(variable.getComment())) {
sb.append(" //" + variable.getComment() + "<br>");
}
sb.append(" private " + dataTypeMapping.get(variable.getType()) + " " + variable.getPropertyNames()
+ ";<br>");
}
sb.append("<br>");
return sb.toString();
}
/**
* @Description 创建set、get方法
* @author zhangyd
* @date 2015年12月9日 上午10:12:02
* @param tableInfo
* @return
*/
@Override
public String createSetAndGet(List<Variable> tableInfo) {
StringBuilder sb = new StringBuilder();
for (Variable variable : tableInfo) {
sb.append(" public void set" + StringUtil.initialtoUpper(variable.getPropertyNames()) + "("
+ dataTypeMapping.get(variable.getType()) + " " + variable.getPropertyNames() + "){<br>");
sb.append(" this." + variable.getPropertyNames() + " = " + variable.getPropertyNames() + ";<br>");
sb.append(" }<br><br>");
sb.append(" public " + dataTypeMapping.get(variable.getType()) + " get"
+ StringUtil.initialtoUpper(variable.getPropertyNames()) + "(){<br>");
sb.append(" return this." + variable.getPropertyNames() + ";<br>");
sb.append(" }<br><br>");
}
return sb.toString();
}
/**
* @Description 创建class尾部
* @author zhangyd
* @date 2015年12月9日 上午10:12:09
* @return
*/
@Override
public String createTail() {
return "}";
}
}
- 关于文件导出
/**
* @Description 得到生成的实体字符串
* @author zhangyd
* @date 2015年12月9日 上午9:51:36
* @param sqlForm
* @return
*/
@RequestMapping(value = "/getJava", produces = "application/json; charset=utf-8")
@ResponseBody
public String getJava(TableForm sqlForm) {
try {
String filename = StringUtil.splitAndtoUpper(sqlForm.getSelectedTableNames(), "_") + ".java";
String path = generationClassService.getSaveFilePath(filename, sqlForm);
MemcachedUtil.set("java_path", path);
MemcachedUtil.set("java_name", filename);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, Object> map = generationClassService.getJava(sqlForm);
// 页面用,保证队形
String sql = (String) map.get("list");
map.put("list", sql.replace(" ", " "));
JSONObject jsonObject = JSONObject.fromObject(map);
return jsonObject.toString();
}
/**
* @Description 获取保存文件的地址
* @author zhangyd
* @date 2015年12月18日 下午4:27:35
* @param filename
* @param mybatisSqlForm
* @return
*/
@Override
public String getSaveFilePath(String filename, TableForm mybatisSqlForm) {
filename = StringUtil.initialtoUpper(filename);
Map<String, Object> map = this.getJava(mybatisSqlForm);
String sql = (String) map.get("list");
sql = sql.replace("<br>", "\n");
String path = FileUtil.getGenerationJavaFilePath() + filename;
FileUtil.saveFile(path, sql.replace("<br>", "\n"));
MemcachedUtil.set("java_path", path);
return path;
}
说明:因为我设计的是在点击生成java代码后才会显示导出按钮,因此,在生成java代码时就要把内容保存到文件中,供下载导出。同时,因为我没有用到数据库表记录生成的文件路径和名字,我用的是Memcache缓存,此处无强求,根据个人爱好,爱咋整咋整。
- 将字符串保存到新文件中
/**
* @Description 将字符串写入文件==生成文件
* @author zhangyd
* @date 2015年12月8日 下午3:29:49
* @param filePath
* @param content
* @return
*/
public static boolean saveFile(String filePath, String content) {
return saveFile(filePath, content, "UTF-8");
}
/**
* @Description 将字符串写入文件==生成文件
* @author zhangyd
* @date 2015年12月9日 下午1:32:30
* @param path
* @param content
* @param encodeingType
* @return
*/
public static boolean saveFile(String path, String content, String encodeingType) {
boolean flag = false;
DataOutputStream dos = null;
try {
File file = new File(path);
if (content != null && content.length() >= 0) {
byte abyte[] = content.getBytes(encodeingType);
dos = new DataOutputStream(new FileOutputStream(file));
dos.write(abyte, 0, abyte.length);
dos.flush();
flag = true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
close(dos);
}
}
return flag;
}
OK,到这儿就算到量了,基本的流程和逻辑以及核心代码,就是以上所示。如果感兴趣,可以根据这个思路自己弄一个。如果以上有看不明白的,或者我写的有不明确的地方,请随时call我,或者本文留言也行。
......
恭迎各位大神指点......
github:servlet版项目代码
注:源代码是在SSM框架中的,没另外提。因为有慕友让我提出来一份简单的,所以我就提成了一个servlet版的。
热门评论
在文采好的人里,你技术是最好的。在技术好的人里,你文采是最好的。你的才华如同滔滔江水延绵不绝生生不息令人高山仰止心生佩服!
在文采好的人里,你技术是最好的。在技术好的人里,你文采是最好的。你的才华如同滔滔江水延绵不绝生生不息令人高山仰止心生佩服!
你不知道mybatis-generate生成工具吗?