概述
在写后台管理系统的时候,有这样一个功能,它需要对任意一张表生成对表字段的预览
类似这样:
分析
该如何做呐?我们所能看到字段名、字段类型、字段注释以及字段默认值需要从数据库中得到,而java字段名和java字段类型则涉及到数据库到java 实体名 和java 数据类型的转换
数据库字段名到java字段名的转换规则为:当数据库字段名中有下划线_时则将起替换为空字符串,并且将其后的第一个字母大写
表的字段名、字段类型、字段注释及字段默认值在mysql中是专门存在于表columns中的,如下
我们打开这张表看一下,以sys_user表为例,我们可以看到sys_user表所有的字段名、字段类型、字段注释以及字段默认值
mysql的数据类型和Java的数据类型呈现映射关系,要将mysql中的数据类型转换为Java的数据类型就应当设置其中的映射关系,如中mysql的部分数据类型和Java数据类型的映射如下图所示
编码
有了如上分析,如何编码呐?大体思路如下
主要的操作都是按如上图逻辑写的,大写驼峰按如下规则进行javaName遇到mysql中的下滑线_,去掉_,将起后的一个字符大写,按下划线切数据,然后将第二个字符串的首字母大写
@Service
public class GeneratorServiceImpl implements GeneratorService {
@Autowired
private JdbcTemplate jdbcTemplate;
private static Map<String, String> map = new HashMap<>();
static {
map.put("int",Integer.class.getSimpleName());
map.put("tinyint",Integer.class.getSimpleName());
map.put("double",Double.class.getSimpleName());
map.put("float",Float.class.getSimpleName());
map.put("decimal", BigDecimal.class.getSimpleName());
map.put("date", Date.class.getSimpleName());
map.put("timestamp",Date.class.getSimpleName());
map.put("varchar",String.class.getSimpleName());
map.put("text",String.class.getSimpleName());
map.put("longtext",String.class.getSimpleName());
}
private RowMapper fieldMapper(){
return new RowMapper() {
@Override
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
BeanField beanField = new BeanField();
beanField.setCloumnName(rs.getString("COLUMN_NAME"));
beanField.setCloumnType(rs.getString("DATA_TYPE"));
beanField.setCloumnComment(rs.getString("COLUMN_COMMENT"));
beanField.setCloumnDefualt(rs.getString("COLUMN_DEFAULT"));
return beanField;
}
};
}
@Override
public List<BeanField> filedList(String tableName) throws Exception {
List<BeanField> fields = jdbcTemplate.query("SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_NAME = ? ",
fieldMapper(), tableName
);
if (CollectionUtils.isEmpty(fields)){
throw new Exception("表不存在");
}
fields.stream().forEach(e -> {
//mysql类型和java类型转换
e.setJavaType(map.get(e.getCloumnType()));
//mysql命名和java命名转换
e.setJavaName(strToUpper(e.getCloumnName()));
});
return fields;
}
private String strToUpper(String cloumnName){
StringBuffer stringBuffer = new StringBuffer();
if (cloumnName.contains("_")){
String[] s = cloumnName.split("_");
stringBuffer.append(s[0].toLowerCase());
for (int i = 1; i < s.length; i++) {
String lowerCase = s[i].toLowerCase();
String upperCase = lowerCase.replaceFirst(lowerCase.substring(0, 1), lowerCase.substring(0, 1).toUpperCase());
stringBuffer.append(upperCase);
}
return stringBuffer.toString();
}
return cloumnName;
}
}
BeanField:
@Data
public class BeanField {
private String cloumnName;
private String cloumnType;
private String cloumnComment;
private String cloumnDefualt;
private String javaType;
//javaName遇到mysql中的下滑线_,去掉_,将起后的一个字符大写
private String javaName;
}
生成的结果如图,但是存在的问题是,如果数据库的下划线的后面只有一个字母,那么单将这个字母大写就有点怪异,具体要怎么操作,怎么实现,可能会留到往后来考虑具体的解决办法了