自动生成java实体类的工具类

写实体类的悲伤

写一个java实体类,需要对着数据库的表来写,还要写注释,注解,虽然可以一键生成get和set方法,
但是当表字段非常多的时候,真的是挺烦的一件事情,
我一直信奉一个观念,能自动化的,就不要动手了,写代码也应该是一样,
很多人都知道,mybatis提供的生成器,可以生成实体类啊,dao啊,还有xml,多方便,
但是我开发的数据库的表的字段特殊啊,于是自己网上找个例子,然后照着写了一个,强行装逼,
从此,实体类,dao,xml一键生成,完美!


自动生成的本质

所谓自动生成对应的类,其本质也是使用代码,拼凑java类的代码字符串内容,然后生成一个file,
把内容流写入,在项目对应路径下直接生成一个需要的文件,当然,只适用于格式固定,有规律的类。


代码示例

(1)初始化全局常量,以及定义对应变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 数据库配置
*/
private final static String pgUrl = "jdbc:postgresql://192.168.1.69:5432/test_db";
private final static String username = "dbuser";
private final static String password = "123456";
/**
* 包路径配置
*/
private final static String domain = "com.test.domain";
private final static String mapper = "com.test.mapper";
private final static String I_mapper = "com.test.mapper";
private final static String mapper_impl = "com.test.mapper.impl";
private final static String I_service = "com.test.service";
private final static String service_impl = "com.test.service.impl";
//表名
private String tableNames = "";
// 全列名数组(没有做大小写转换,没有去除字段前缀)
private String[] all_colnames;
// 列名类型数组
private String[] col_types;
// 列注释数组
private String[] col_remarks;
// 是否需要导入包java.util.Date
private boolean is_util = false;
//作者
private String authors = "lmshe";


(2)获取数据库连接,并初始化相关变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public void generatorUtils(String tableName,String author){
tableNames = tableName;
authors = author;
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 得到数据库连接
conn = DriverManager.getConnection(pgUrl, username, password);
String strsql = "select * from " + tableName;
pstmt = conn.prepareStatement(strsql);
ResultSetMetaData rsmd = pstmt.getMetaData();
// 查询该表共有多少列,并初始化相关数组
int size = rsmd.getColumnCount();
all_colnames = new String[size];
col_types = new String[size];
col_remarks = new String[size];
//初始化列注释
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getColumns(null, null, tableName, null);
int re = 0;
while (rs.next()) {
String remarks = rs.getString("REMARKS");// 列描述
col_remarks[re] = remarks;
re++;
}
//初始化列名以及列的字段类型,同时初始化是否需要导入java.util.Date
for (int i = 0; i < rsmd.getColumnCount(); i++) {
all_colnames[i] = rsmd.getColumnName(i + 1);
col_types[i] = rsmd.getColumnTypeName(i + 1);
if (rsmd.getColumnTypeName(i + 1).equalsIgnoreCase("timestamp")) {
is_util = true;
}
}
//生成domain实体类
createDomainUtils();
//生成sql的xml
createMappingUtils();
//生成dao接口类
createIDaoUtils();
//生成dao实现类
createDaoImplUtils();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}


(3)生成domain类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public void createDomainUtils() {
try {
String content = parseDomain();
String path = System.getProperty("user.dir") + "/src/main/java/" + domain.replaceAll("\\.", "/");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String resPath = path + "/" + initcap(tableNames.substring(2, tableNames.length())) + ".java";
FileUtils.writeStringToFile(new File(resPath), content);
System.out.println("建立domain成功");
} catch (Exception e) {
e.printStackTrace();
}
}
private String parseDomain() {
StringBuffer sb = new StringBuffer();
sb.append("package " + domain + ";\r\n\r\n");
//导入依赖包
if (is_util) {
sb.append("import java.util.Date;\r\n\r\n");
}
sb.append("import javax.persistence.Column;\r\n");
sb.append("import javax.persistence.Id;\r\n");
sb.append("import javax.persistence.Table;\r\n\r\n");
//添加注解
sb.append("/**\r\n");
sb.append(" *\r\n");
sb.append(" * @author " + authors + "\r\n");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
String date = sf.format(new Date());
sb.append(" * @time " + date + "\r\n");
sb.append(" * @desc \r\n");
sb.append(" */\r\n");
//类主体
sb.append("@Table(name=\"" + tableNames + "\")\r\n");
sb.append("public class " + initcap(tableNames.substring(2))
+ " {\r\n\r\n");
//生成属性
processAllAttrs(sb);
sb.append("\r\n");
//生成方法
processAllMethod(sb);
sb.append("}\r\n");
return sb.toString();
}
private void processAllMethod(StringBuffer sb) {
for (int i = 0; i < all_colnames.length; i++) {
String allColname = all_colnames[i];
String colname = getCamelStr(allColname);
if (colname.substring(0, 1).equals("f")) {
colname = colname.substring(1);
}
sb.append("\tpublic void set" + initcap(colname) + "(" + sqlType2JavaType(col_types[i]) + " " + colname
+ "){\r\n");
sb.append("\t\tthis." + colname + "=" + colname + ";\r\n");
sb.append("\t}\r\n\r\n");
sb.append("\tpublic " + sqlType2JavaType(col_types[i]) + " get" + initcap(colname) + "(){\r\n");
sb.append("\t\treturn " + colname + ";\r\n");
sb.append("\t}\r\n\r\n");
}
}
private void processAllAttrs(StringBuffer sb) {
for (int i = 0; i < all_colnames.length; i++) {
String remark = col_remarks[i];
if (remark != null) {
sb.append("\t/**\r\n");
sb.append("\t * " + remark + "\r\n");
sb.append("\t */\r\n");
}
String allColname = all_colnames[i];
String colname = getCamelStr(allColname);
if (allColname.equals("id")) {
sb.append("\t@Id\r\n");
sb.append("\t@Column(name = \""+allColname+"\")\r\n");
} else {
sb.append("\t@Column(name=\"" + allColname + "\")\r\n");
}
if (colname.substring(0, 1).equals("f")) {
colname = colname.substring(1);
}
sb.append("\tprivate " + sqlType2JavaType(col_types[i]) + " " + colname + ";\r\n\r\n");
}
}


(4)生成sql的xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public void createMappingUtils() {
try {
String content = parseMapping();
String path = System.getProperty("user.dir") + "/src/main/java/" + mapper.replaceAll("\\.", "/");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String resPath = path + "/I" + initcap(tableNames.substring(2, tableNames.length())) + "Mapper.xml";
FileUtils.writeStringToFile(new File(resPath), content);
System.out.println("建立xml成功");
} catch (Exception e) {
e.printStackTrace();
}
}
private String parseMapping() {
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
sb.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\r\n\r\n");
sb.append("<mapper namespace=\"com.unionbon.youlb.http.mapper.I"+initcap(tableNames.substring(2))+"Mapper\">\r\n\r\n");
sb.append("\t<resultMap id=\"BaseResultMap\" type=\"com.unionbon.youlb.http.domain."+initcap(tableNames.substring(2))+"\">\r\n");
for (int i = 0; i < all_colnames.length; i++) {
String allColname = all_colnames[i];
String colname = getCamelStr(allColname);
if (allColname.equals("id")) {
sb.append("\t\t<id column=\"id\" property=\"id\" jdbcType=\""+sqlType2MybatisType(col_types[i])+"\" />\r\n");
} else {
if (colname.substring(0, 1).equals("f")) {
colname = colname.substring(1);
}
sb.append("\t\t<result column=\""+allColname+"\" property=\""+colname+"\" jdbcType=\""+sqlType2MybatisType(col_types[i])+"\" />\r\n");
}
}
sb.append("\t</resultMap>\r\n");
sb.append("</mapper>");
return sb.toString();
}


(5)生成dao以及实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public void createIDaoUtils() {
try {
String content = parseIDao();
String path = System.getProperty("user.dir") + "/src/main/java/" + I_mapper.replaceAll("\\.", "/");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String resPath = path + "/I" + initcap(tableNames.substring(2, tableNames.length())) + "Mapper.java";
FileUtils.writeStringToFile(new File(resPath), content);
System.out.println("建立dao接口类成功");
} catch (Exception e) {
e.printStackTrace();
}
}
private String parseIDao() {
StringBuffer sb = new StringBuffer();
sb.append("package " + I_mapper + ";\r\n\r\n");
sb.append("import com.unionbon.youlb.http.mapper.IBaseMapper;\r\n");
sb.append("import com.unionbon.youlb.http.domain."+initcap(tableNames.substring(2))+";\r\n\r\n");
//添加注解
sb.append("/**\r\n");
sb.append(" *\r\n");
sb.append(" * @author " + authors + "\r\n");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
String date = sf.format(new Date());
sb.append(" * @time " + date + "\r\n");
sb.append(" * @desc \r\n");
sb.append(" */\r\n");
//类主体
String idType = "";
for (int i = 0; i < all_colnames.length; i++) {
String allColname = all_colnames[i];
if (allColname.equals("id")) {
idType = sqlType2JavaType(col_types[i]);
break;
}
}
sb.append("public interface I" + initcap(tableNames.substring(2)) + "Mapper extends IBaseMapper<"+initcap(tableNames.substring(2))+", "+idType+">{\r\n\r\n");
sb.append("}\r\n");
return sb.toString();
}
public void createDaoImplUtils() {
try {
String content = parseDaoImpl();
String path = System.getProperty("user.dir") + "/src/main/java/" + mapper_impl.replaceAll("\\.", "/");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
String resPath = path + "/" + initcap(tableNames.substring(2, tableNames.length())) + "MapperImpl.java";
FileUtils.writeStringToFile(new File(resPath), content);
System.out.println("建立dao实现类成功");
} catch (Exception e) {
e.printStackTrace();
}
}
private String parseDaoImpl() {
StringBuffer sb = new StringBuffer();
sb.append("package " + mapper_impl + ";\r\n\r\n");
sb.append("import com.unionbon.youlb.http.mapper.impl.BaseMapperImpl;\r\n");
sb.append("import com.unionbon.youlb.http.mapper.I"+initcap(tableNames.substring(2))+"Mapper;\r\n");
sb.append("import com.unionbon.youlb.http.domain."+initcap(tableNames.substring(2))+";\r\n\r\n");
//添加注解
sb.append("/**\r\n");
sb.append(" *\r\n");
sb.append(" * @author " + authors + "\r\n");
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
String date = sf.format(new Date());
sb.append(" * @time " + date + "\r\n");
sb.append(" * @desc \r\n");
sb.append(" */\r\n");
//类主体
String idType = "";
for (int i = 0; i < all_colnames.length; i++) {
String allColname = all_colnames[i];
if (allColname.equals("id")) {
idType = sqlType2JavaType(col_types[i]);
break;
}
}
sb.append("public class " + initcap(tableNames.substring(2)) + "MapperImpl extends BaseMapperImpl<"+initcap(tableNames.substring(2))+", "+idType+"> implements I"+initcap(tableNames.substring(2))+"Mapper{\r\n\r\n");
sb.append("}\r\n");
return sb.toString();
}


(6)工具方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* 把输入字符串的首字母改成大写
*
* @param str
* @return
*/
public static String initcap(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return getCamelStr(new String(ch));
}
/**
*
* @param s
* @return
* @author lmshe
* @time 2017年3月30日
* @desc 处理下横杠,并转为大写
*/
public static String getCamelStr(String s) {
while (s.indexOf("_") > 0) {
int index = s.indexOf("_");
s = s.substring(0, index) + s.substring(index + 1, index + 2).toUpperCase() + s.substring(index + 2);
}
return s;
}
/**
*
* @param sqlType
* @return
* @author lmshe
* @time 2017年3月30日
* @desc 数据库类型与java类型互转
*/
private String sqlType2JavaType(String sqlType) {
if (sqlType.equalsIgnoreCase("bit")) {
return "bool";
} else if (sqlType.equalsIgnoreCase("tinyint")) {
return "byte";
} else if (sqlType.equalsIgnoreCase("int2")) {
return "short";
} else if (sqlType.equalsIgnoreCase("int4") || sqlType.equals("serial")) {
return "Integer";
} else if (sqlType.equalsIgnoreCase("int8")) {
return "Long";
} else if (sqlType.equalsIgnoreCase("bigint")) {
return "Long";
} else if (sqlType.equalsIgnoreCase("float")) {
return "float";
} else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
|| sqlType.equalsIgnoreCase("real")) {
return "double";
} else if (sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
return "double";
} else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char")
|| sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")) {
return "String";
} else if (sqlType.equalsIgnoreCase("timestamp")) {
return "Date";
} else if (sqlType.equalsIgnoreCase("image")) {
return "Blob";
} else if (sqlType.equalsIgnoreCase("text")) {
return "Clob";
}
return null;
}
/**
*
* @param sqlType
* @return
* @author lmshe
* @time 2017年3月31日
* @desc 数据库类型与mybatisxml的jdbc类型转换
*/
private String sqlType2MybatisType(String sqlType) {
if (sqlType.equalsIgnoreCase("int4") || sqlType.equals("serial")) {
return "INTEGER";
} else if (sqlType.equalsIgnoreCase("varchar")) {
return "VARCHAR";
} else if (sqlType.equalsIgnoreCase("char")){
return "CHAR";
}else if (sqlType.equalsIgnoreCase("timestamp")) {
return "TIMESTAMP";
}else if(sqlType.equalsIgnoreCase("decimal")){
return "DECIMAL";
}
return null;
}


(7)测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
*
*
* @author lmshe
* @time 2017年3月30日
* @desc 代码生成器
*/
public class Generator {
//表名
private final static String tableName= "t_users";
//作者
private final static String author = "lmshe";
//生成代码仅适用于表主键字段名为“id”,且其它字段以“f”开始,且字段都以下横杠连接
public static void main(String[] args) {
new GeneratorUtils().generatorUtils(tableName,author);
}
}


寄语

当人生活成了回忆,不过是在等待逝去,而只有不断创造回忆,才是人生精彩的演绎