建表语句分析
建表sql
下面是执行 sql show create table user 的结果:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` varchar(225) DEFAULT NULL COMMENT '用户名',
`create_date` datetime DEFAULT NULL,
`status` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL COMMENT '年龄',
`mark` varchar(225) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2104778081 DEFAULT CHARSET=latin1 COMMENT='用户表'
这里可以看出,要创建的实体类的名称就在第一行的CREATE TABLE 后的两个`符号中间,这样我们就可以通过正则将表的名称取出来,然后转换成为我们需要的class名称。首先我们先写一个通过正则提取数据的方法,下面是代码:
正则代码
/**
* 根据正则查找
*
* @param sql
* @param pattern
* @param group
* @return
*/
static String getByPattern(String sql, String pattern, int group) {
Pattern compile = Pattern.compile(pattern);
Matcher matcher = compile.matcher(sql);
while (matcher.find()) {
return matcher.group(group);
}
return null;
}
现在开始从建表语句中提取table的名称(虽然在获得数据库所有表的时候就已经知道了,但是在写一次也没有什么问题不是 ~~~),下面是代码:
获取class名称
/**
* 获得表的名称
*
* @param sql
* @return
*/
public static String getTableName(String sql) {
return getByPattern(sql, "CREATE TABLE `(.*)`", 1);
}
这里就已经将table的名称取出来了。
接下来是获取class上的注释,这里我们取table的注释。下面是代码:
提取class注释
public static String getTableComment(String sql) {
return getByPattern(sql, "\\) .* COMMENT='(.*)'", 1);
}
现在开始提取数据库中的字段,字段类型,字段注释。
字段,字段类型,字段注释
先取出来建表语句中的和字段相关的sql
/**
* 获取建表语句中和字段相关的sql
*
* @param sql
* @return
*/
public static List<String> getColumnSqls(String sql) {
List<String> lines = new ArrayList<>();
Scanner scanner = new Scanner(sql);
boolean start = false;
while (scanner.hasNextLine()) {
String nextLine = scanner.nextLine();
if (nextLine.indexOf("CREATE TABLE") != -1) {
start = true;
continue;
}
if (nextLine.indexOf("PRIMARY KEY") != -1) {
start = false;
continue;
}
if (start) {
lines.add(nextLine);
}
}
return lines;
}
这里的运行结果是:
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` varchar(225) DEFAULT NULL COMMENT '用户名',
`create_date` datetime DEFAULT NULL,
`status` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL COMMENT '年龄',
`mark` varchar(225) DEFAULT NULL,
这也就取到了table中所有的字段相关信息了,接下来我们来获取字段名称:
获取class属性名称,注释,sql中的数据类型
List<String> columns = SqlUtils.getColumnSqls(sql);
for (String oneLine : columns) {
System.out.println(oneLine);
String columnName = SqlUtils.getByPattern(oneLine, "`(.*)`", 1);
String comment = SqlUtils.getByPattern(oneLine, "COMMENT '(.*)'", 1);
String columnType = SqlUtils.getByPattern(oneLine, "`" + columnName + "` ([A-Za-z]*)", 1);
System.out.printf("名称:%-20s 类型:%-20s 注释:%-20s \n", columnName, columnType, comment);
}
输出结果:
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
名称:id 类型:int 注释:用户id
`name` varchar(225) DEFAULT NULL COMMENT '用户名',
名称:name 类型:varchar 注释:用户名
`create_date` datetime DEFAULT NULL,
名称:create_date 类型:datetime 注释:null
`status` int(11) DEFAULT NULL,
名称:status 类型:int 注释:null
`age` int(11) DEFAULT NULL COMMENT '年龄',
名称:age 类型:int 注释:年龄
`mark` varchar(225) DEFAULT NULL,
名称:mark 类型:varchar 注释:null
这里我们拿到了字段名称,字段类型后还要将其转换为java中的格式,字段名称转换和上面的class名称转换类似,只是首字母不需要大写,这里就不贴代码了。把sql 的数据类型转换为java的数据类型代码在下面:
sql数据类型和java数据类型转换
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class ColumnFieldTypeMapping {
private Map<String, Class> sqlFieldTypeMapping = new HashMap<>();
{
sqlFieldTypeMapping.put("VARCHAR", String.class);
sqlFieldTypeMapping.put("CHAR", String.class);
sqlFieldTypeMapping.put("TEXT", String.class);
sqlFieldTypeMapping.put("MEDIUMTEXT", String.class);
sqlFieldTypeMapping.put("LONGTEXT", String.class);
sqlFieldTypeMapping.put("TINYTEXT", String.class);
sqlFieldTypeMapping.put("BIT", Boolean.class);
sqlFieldTypeMapping.put("INT", int.class);
sqlFieldTypeMapping.put("BIGINT", long.class);
sqlFieldTypeMapping.put("DOUBLE", double.class);
sqlFieldTypeMapping.put("TINYINT", int.class);
sqlFieldTypeMapping.put("FLOAT", float.class);
sqlFieldTypeMapping.put("DECIMAL", BigDecimal.class);
sqlFieldTypeMapping.put("INT UNSIGNED", int.class);
sqlFieldTypeMapping.put("BIGINT UNSIGNED", int.class);
sqlFieldTypeMapping.put("DECIMAL UNSIGNED", BigDecimal.class);
sqlFieldTypeMapping.put("DATETIME", Date.class);
sqlFieldTypeMapping.put("TIME", Date.class);
sqlFieldTypeMapping.put("DATE", Date.class);
sqlFieldTypeMapping.put("TIMESTAMP", Date.class);
}
/**
* 根据sql数据类型获取Java数据类型
*
* @param columnType
* @return
*/
public Class getFieldType(String columnType) {
Class aClass = sqlFieldTypeMapping.get(columnType);
if (aClass == null) {
return sqlFieldTypeMapping.get(columnType.toUpperCase());
}
return null;
}
}
这里只是简单的做了一个映射,有需要修改的各自自己修改一下就好了。接下来我们来获取表中的id
获取id
获取id依然是使用正则就好了,代码如下:
public static String getId(String sql) {
String id = getByPattern(sql, "PRIMARY KEY (`.*`)", 1);
return getByPattern(id, "`(.*)`", 1);
}
因为原本语句中有一对括号,所以使用正则提取了两次。如果有更好的方法的话麻烦告知。
到了这,我就就已经从建表语句里拿到了所有需要的数据了,下面就开始使用这些数据来生成java文件了。
下一篇继续~