第32次文章:手写SORM框架(二)
- 2019 年 10 月 8 日
- 筆記
在上周,我们将整个SORM的框架结构梳理了一下,本周开始对整个框架的每个细节步骤进行相关的填充。目前还没有把整个框架全部搭建起来,只完成了一小部分,这周我们就对已完成的类中,一些比较有意思的功能进行一个小介绍吧!
1、核心bean中的JavaFieldGetSet类
在核心Javabean类中,我们增加了一个JavaFieldGetSet类,主要用于封装一个java属性的get和set方法的源码。
JavaFieldGetSet类中,设置有三个属性参数,分别为:
(1)fieldInfo:主要存储属性源码信息,如:private int userId;
(2)getInfo:get方法源码。如:public int getUserId(){}
(3)setInfo:set方法源码。如:public void setUserId(int id){this.id = id;}
需要注意的是JavaFieldGetSet类本身也属于一个Javabean类,内部只包括三个属性的set和get方法,以及无参构造器和带参构造器。
2、工具类Utils中的JavaFileUtils类
根据上周我们的架构预设,JavaFileUtils中主要是封装生成Java文件(源代码)常用的操作。
针对上面提到的JavaFieldGetSet类,我们封装相应的方法来生成源码信息。此处我们着重分享生成源码的方法:根据字段信息生成java属性信息。如:var username –>private String username;以及相应的set和get方法源码。该方法的程序代码如下:
package com.peng.sorm.utils; import com.peng.sorm.bean.ColumnInfo; import com.peng.sorm.bean.JavaFieldGetSet; import com.peng.sorm.core.MySqlTypeConvertor; import com.peng.sorm.core.TypeConvertor; /** * 封装了生成Java文件(源代码)常用的操作 * */ public class JavaFileUtils { /** * 根据字段信息生成java属性信息。如:var username -->private String username;以及相应的set和get方法源码 * @param column 字段信息 * @param convertor 类型转化器 * @return java属性和set/get方法源码 */ public static JavaFieldGetSet createFieldGetSetSRC(ColumnInfo column,TypeConvertor convertor) { JavaFieldGetSet jfgs = new JavaFieldGetSet(); String javaFieldType = convertor.databaseType2JavaType(column.getDataType());//获取属性在java中的数据类型 //private String username; //生成属性源码 jfgs.setFieldInfo("tprivate "+javaFieldType+" "+column.getName()+";n"); //public String getUsername(){return username;} //生成get方法的源码 StringBuilder getSrc = new StringBuilder(); getSrc.append("tpublic "+javaFieldType+" get"+StringUtils.firstChar2UpperCase(column.getName())+"(){n"); getSrc.append("ttreturn "+column.getName()+";n" ); getSrc.append("t}n"); jfgs.setGetInfo(getSrc.toString()); //public void setUsername(String username){this.username=username;} //生成set方法的源码 StringBuilder setSrc = new StringBuilder(); setSrc.append("tpublic void set"+StringUtils.firstChar2UpperCase(column.getName())+"("); setSrc.append(javaFieldType+" "+column.getName()+"){n"); setSrc.append("tt this."+column.getName()+"="+column.getName()+";n" ); setSrc.append("t}n"); jfgs.setSetInfo(setSrc.toString()); return jfgs; } }
tips:在上面的代码中,我们封装了一个createFieldGetSetSRC()方法,根据属性声明,set,get方法的格式,使用拼接字符串的方法来完成每一段源代码的生成。
1.为了源码生成之后的美观问题,我们需要对每一行代码的缩进与对齐方面进行控制,所以增加了制表符“t”和换行符“n"。
2.在生成set和get方法的源码的时候,我们按照常规习惯,会将属性名的第一字母变为大写,然后在属性名前面加上set或者get,形成set与get方法的方法名。为了便于后续的使用,我们封装了一个改变字符串首字母大小写的方法firstChar2UpperCase(),在后面我们将对其进行分析。
3.在生成源码的时候,我们还需要对数据库中传递过来的数据类型进行转换,使用到了一个我们自己封装的方法databaseType2JavaType(),此方法在后面进行详解。
3、工具类Utils中的StringUtils类
在规划整个SORM框架的时候,在StringUtils中主要封装字符串常用的操作。
针对上面的createFieldGetSetSRC()方法,我们提到了一个转换字符串首字母大小写的方法firstChar2UpperCase()。下面给出此方法的源程序:
package com.peng.sorm.utils; /** * 封装了字符串常用的操作 */ public class StringUtils { /** * 将目标字符串首字母变为大写 * @param str 目标字符串 * @return 首字母变为大写的字符串 */ public static String firstChar2UpperCase(String str) { return str.toUpperCase().substring(0,1)+str.substring(1); } }
tips:在上述firstChar2UpperCase()方法里面,转换字符串首字母大小写的思想很简单:首先使用toUpperCase()方法,将字符串的全部字母转换为大写字母,然后使用subString(0,1)截取首字母;然后再用拼接字符串的方法,将原字符串的剩余部分拼接在首字母后面,最后得到一个仅改变首字母大小写的字符串。
4、核心架构中的MySqlTypeConvertor类
MySqlTypeConvertor类属于核心架构中实现了TypeConvertor接口的一个实现类,主要负责将MySql数据库和java之间的数据类型进行相互转化。在上面的createFieldGetSetSRC()方法中,已经提到了这一部分。
package com.peng.sorm.core; /** * mysql数据类型和java数据类型的转换 */ public class MySqlTypeConvertor implements TypeConvertor { @Override public String databaseType2JavaType(String columnType) { // varchar ---- >String if("varchar".equalsIgnoreCase(columnType)||"char".equalsIgnoreCase(columnType)) { return "String"; }else if("int".equalsIgnoreCase(columnType) ||"tinyint".equalsIgnoreCase(columnType) ||"smallint".equalsIgnoreCase(columnType) ||"integer".equalsIgnoreCase(columnType) ) { return "Integer"; }else if("bigint".equalsIgnoreCase(columnType)) { return "Long"; }else if("double".equalsIgnoreCase(columnType)||"float".equalsIgnoreCase(columnType)) { return "Double"; }else if("blob".equalsIgnoreCase(columnType)) { return "java.sql.BLob"; }else if("clob".equalsIgnoreCase(columnType)) { return "java.sql.CLob"; }else if("date".equalsIgnoreCase(columnType)) { return "java.sql.Date"; }else if("time".equalsIgnoreCase(columnType)) { return "java.sql.Time"; }else if("timeStamp".equalsIgnoreCase(columnType)) { return "java.sql.TimeStamp"; } return null; } @Override public String javaType2DatebaseType(String columnType) { return null; } }
tips:在类型转换的时候,我们仅实现TypeCOnvertor接口中的databaseType2JavaType()方法。思想很简单,就是使用条件语句来对每一个数据库中的数据类型进行判断,然后再将其转换为对应的java中的数据类型。
5、最后检测一下生成源码的的效果
public static void main(String[] args) { ColumnInfo ci = new ColumnInfo("username","varchar",0); JavaFieldGetSet jfgs = createFieldGetSetSRC(ci, new MySqlTypeConvertor()); System.out.println(jfgs.toString()); }
结果:
所得结果符合我们的预期效果,和我们自己手写的代码一致。