不积跬步,无以至千里
今天重构以前的代码,因为数据库有比较大的改动,所以需要写很多javaBean!
作为一个程序员,重复意味着没有效率,更意味着无聊,一旦无聊便没有想编程的欲望,代码质量肯定刷刷刷的下降,质量下降了就意味着重写。。。。
so,为了集中精力在业务逻辑的代码上,减少不必要的时间浪费,于是花了一点时间写了一个把数据库中表的字段自动映射到 javaBean 中。
输入所生成 文件的存放路径、文件的名称(默认是表名)、包名(生成的是java文件,一定要指定包名)、是否使用lombok插件(考虑到自己实现getter/setter方法有一定的困难,直接借助lombok插件),判断每一个表中的字段的类型,生成一个标准的javaBean文件。
得到数据库的连接
package connection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionUtil {
public static Connection getConn(String dbName, String username, String password) {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/"+dbName+"?useUnicode=true&characterEncoding=utf-8&useSSL=false";
Connection conn = null;
try {
Class.forName(driver);
conn = (Connection) DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
这里写的是上述需要封装的所有方法
package mapper;
import connection.ConnectionUtil;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.*;
import java.util.*;
public class MapperUtil {
private DatabaseMetaData databaseMetaData;
Connection connection;
public MapperUtil(String dbName, String username, String password) throws SQLException {
connection = ConnectionUtil.getConn(dbName, username, password);
databaseMetaData = connection.getMetaData();
}
/**
* 只是文件名(不包含扩展名)
* @param fileName 文件名称
* @param dir 文件所处的目录
* @param mainContent 文件的主要内容
* @param isLombok 是否包含lombok常见的一些方法?包含:不包含
*/
public void createFile(String fileName, String dir, String packagePath, String mainContent, boolean isLombok) throws Exception {
if (fileName == null || fileName.trim().equals("") || dir == null || dir.trim().equals("")){
throw new Exception("传入参数不正确");
}
/**
* 1.首先检测是否有这个文件夹路径
* 2.如果不存在则新建
*/
File fileDir = new File(dir);
if (!fileDir.exists()){
fileDir.setWritable(true);
fileDir.mkdirs();
}
/**
* 如果没有出错,那么创建文件,这里统一创建java文件
*/
File javaFile = new File(fileDir, fileName+".java");
javaFile.createNewFile();
/**
* 向文件中输送内容
* 使用
*/
DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(javaFile)));
dataOutputStream.writeBytes("package " + packagePath + ";\n");
dataOutputStream.writeBytes("\n");
if (isLombok){
dataOutputStream.writeBytes(
"import lombok.*;\n\n"+
"@Data\n" +
"@ToString\n" +
"@Builder\n" +
"@AllArgsConstructor\n" +
"@NoArgsConstructor\n");
}
dataOutputStream.writeBytes("public class " + fileName + "{\n");
dataOutputStream.writeBytes(mainContent);
dataOutputStream.writeBytes("}");
dataOutputStream.close();
}
/**
* 构造对应的字符串。
* @param map
* @return
*/
public String generateString(Map<String, String> map){
String result = "";
Set set = map.entrySet();
/**
* 对map进行遍历
*/
for(Iterator iter = set.iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
//把字段的下划线去掉,下划线后一位变为大写
StringBuilder sb = new StringBuilder(key);
for (int i = 1; i < key.length(); i++) {
if (i+1 < key.length() && key.substring(i,i+1).equals("_")){
sb.replace(i, i+2, key.substring(i+1,i+2).toUpperCase());
}
}
String value = (String)entry.getValue();
System.out.println("key: " + key + " sb: " + sb +" :" + value);
result += " private " + value + " " + sb + ";\n";
}
return result;
}
/**
* 返回字段名称和属性
* @param tableName
* @return
*/
public Map<String, String> getFiledAndType(String tableName) throws SQLException {
if (tableName == null || tableName.trim().equals("")){return null;}
ResultSet resultSet = connection.prepareStatement("select * from " + tableName).executeQuery();
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//得到所有的列名信息
int count = resultSetMetaData.getColumnCount();
Map<String, String> map = new HashMap<String, String>();
for (int i = 1; i <= count; i++) {
String type = resultSetMetaData.getColumnTypeName(i);
type = typeTransform(type);
map.put(resultSetMetaData.getColumnName(i), type);
}
return map;
}
/**
* 得到所有表的名称
* @return 含有所有表名的列表
*/
public List<String> getTableNames() throws SQLException {
List<String> tables = new ArrayList<String>();
ResultSet resultSet = databaseMetaData.getTables(null, null, "%", null);
while (resultSet.next()){
String tableName = resultSet.getString("TABLE_NAME");
tables.add(tableName);
System.out.println(tableName);
}
return tables;
}
/**
* 类型转换: 目前针对常见的几个类型
* @return
*/
public String typeTransform(String sqlType){
if (sqlType == null || sqlType.trim().equals("")){
return null;
}
sqlType = sqlType.toLowerCase();
if (matchFloatNumber(sqlType)){
return "double";
}else if (matchInt(sqlType)){
return "int";
}else if (matchString(sqlType)){
return "String";
}
return "String";
}
public boolean match(String target, String[] datas) {
if (target == null || "".equals(target.trim()) || datas.length == 0){
return false;
}
for (String a:datas) {
if (a.equals(target)){
return true;
}
}
return false;
}
public boolean matchString(String target){
String[] datas = {"char", "varchar", "date", "text", "timestamp", "datetime", "tinytext", "longtext"};
return match(target, datas);
}
public boolean matchFloatNumber(String target){
String[] datas = {"float", "double"};
return match(target, datas);
}
public boolean matchInt(String target){
String[] datas = {"int", "tinyint"};
return match(target, datas);
}
}
封装MapperUtil.java当中存在的方法
package mapper;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class MapperDo {
private String dbName;
private String username;
private String password;
private String baseDir;
private String packagePath;
private boolean isLombok;
MapperUtil mapperUtil;
public MapperDo(String dbName, String username, String password) throws SQLException {
this.dbName = dbName;
this.username = username;
this.password = password;
mapperUtil = new MapperUtil(dbName, username, password);
}
/**
* 创建单个文本文件
* @param baseDir
* @param packagePath
* @param isLombok
* @param tableName
* @throws Exception
*/
public void generateFileModel(String baseDir, String packagePath, boolean isLombok, final String tableName) throws Exception {
List<String> list = mapperUtil.getTableNames();
boolean isExist = list.stream().noneMatch((s) -> s.equals(tableName));
if (isExist){
return;
}
String fileName = toCamelCase(tableName);
Map<String, String> map = mapperUtil.getFiledAndType(tableName);
String mainContent = mapperUtil.generateString(map);
mapperUtil.createFile(fileName, baseDir, packagePath, mainContent, true);
}
/**
* 创建这个数据库中所有的模板文件、
* @param baseDir
* @param packagePath
* @param isLombok
*/
public void generateFileModels( String baseDir, String packagePath, boolean isLombok) throws Exception {
List<String> list = mapperUtil.getTableNames();
for (String tableName:list) {
String fileName = toCamelCase(tableName);
Map<String, String> map = mapperUtil.getFiledAndType(tableName);
String mainContent = mapperUtil.generateString(map);
mapperUtil.createFile(fileName, baseDir, packagePath, mainContent, true);
}
}
public String toCamelCase(String s){
if (s == null){
return null;
}
/**
* 1. 把全部转成小写
* 2. 把下划线全部去掉
* 3. 把下划线之后的一个字母变成大写
* 4. 首个字母变成大写
*/
StringBuilder sb = new StringBuilder(s.toLowerCase());
for (int i = 1; i < sb.length(); i++) {
if (i+1 < sb.length() && sb.substring(i,i+1).equals("_")){
sb.replace(i, i+2, sb.substring(i+1,i+2).toUpperCase());
}
}
sb.replace(0,1, s.substring(0,1).toUpperCase());
return sb.toString();
}
/**
*------------------此处省略getter/setter方法
**/
}
测试代码
package run;
import mapper.MapperDo;
public class Main {
public static void main(String[] args) throws Exception {
MapperDo mapperDo = new MapperDo("bonetest","root","root");
//测试生成数据库中所有表的javaBean
mapperDo.generateFileModels("/home/liudong/code/evaluate_bone/src/test/java/cn/edu/cqupt/mis/evaluate_bone/test", "liudong", false);
//测试生成advices一个表的javaBean
mapperDo.generateFileModel("/home/liudong/code/evaluate_bone/src/test/java/cn/edu/cqupt/mis/evaluate_bone/test", "liudong", false,"advices");
}
}
代码和逻辑虽然简单,但是实现之后再次记录,就会温故而知新。
代码我会继续完善,希望有问题大家可以一起探讨探讨。