使用Velocity引擎生成数据库对应实体类
Velocity是一种Java模版引擎技术,该项目由Apache提出。 Apache对它的定义是:一种基于Java的模板引擎,它允许任何人使用简单而强大的模板语言来引用定义在Java代码中的对象。
Velocity应用于web开发时,界面设计人员可以和java程序开发人员同步开发一个遵循MVC架构的web站点,也就是说,页面设计人员可以只关注页面的显示效果,而由java程序开发人员关注业务逻辑编码。Velocity将java代码从web页面中分离出来,这样为web站点的长期维护提供了便利,同时也为我们在JSP和PHP之外又提供了一种可选的方案。
Velocity还被用在其他地方,比如系统中用户注册或修改密码时,往往会向用户的邮箱发一封邮件,该邮件的内容可以由Velocity生成,而不是传统的字符串拼接的形式。另外,在一个新项目要开发之前,可能都会先提供实体类,用于和数据库中设计好的表对应,类似写实体类这样的重复的相似劳动,我们也可以使用Velocity解决。
我们今天就来看一下,使用Velocity生成数据库对应的实体类的过程。
项目结构图如下:
其中pojo中的类为自动生成的
其主要流程为:
一、准备数据库
二、通过JDBC建立程序和数据库的连接
三、通过JDBC得到数据库中所有的表和表中的字段信息(类型、字段名)
四、准备Velocity的vm模板,用于生成对应的文件
五、使用Velocity,生成指定名字和字段的单个文件
六、定义main方法,通过第三步得到的数据,根据第四步准备的vm模板,调用第五步生成单个文件的方法,将整个数据库对应的实体类生成
下面详细为详细介绍:
一、准备数据库
这里使用SQLite数据库,表结构如下:
二、通过JDBC建立程序和数据库的连接
1、准备MySql的驱动包,这里使用的是sqlite-jdbc-3.7.2.jar
2、编写数据库连接工具类,如下:
package cn.ucai.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class SQLiteDBUtils { /** * 得到对数据库的连接 * @return */ public static Connection getConnection(){ Connection conn = null; try { Class.forName("org.sqlite.JDBC"); conn = DriverManager.getConnection("jdbc:sqlite:C:/Users/sks/Desktop/superwechat_Database_V02-master/superwechat_v04.db"); }catch(Exception e){ e.printStackTrace(); } return conn; }
/** * 关闭所有数据库操作的相关资源 * @param conn * @param ment * @param rs */ public static void closeAll(Connection conn,PreparedStatement ps ,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ |
try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } |
三、通过JDBC得到数据库中所有的表和表中的字段信息(类型、字段名)
1、封装一个实体类,用于接收从数据库中读取到的全部数据信息,如下:
package cn.ucai.bean; import java.util.Arrays; public class Classes { /** 表名 **/ private String className; /** 一维数组存字段个数,二维数组存每个字段的类型和名称 **/ private String[][] strArr; public Classes() { super(); } public Classes(String className, String[][] strArr) { super(); this.className = className; this.strArr = strArr; } public String getClassName() { return className; } public void setClassName(String className) { String result = ""; for(int i=0;i<className.length();i++){ if(i==0){ result += (className.charAt(i)+"").toUpperCase(); }else{ result += className.charAt(i)+""; } } this.className = result; } public String[][] getStrArr() { return strArr; } public void setStrArr(String[][] strArr) { this.strArr = strArr; |
} @Override public String toString() { String toString = ""; for(int i=0;i<strArr.length;i++){ toString += " "+Arrays.toString(strArr[i]); } return "Classes [className=" + className + ", strArr=" +toString + "]"; } } |
2、从数据库获取所有的表和表中的字段名和字段类型信息
/** * 从数据库获取所有的表和表中的字段名和字段类型信息 * @return */ public static List<Classes> getClassesData(){ List<Classes> claList = new ArrayList<Classes>(); // 获得数据库连接 Connection conn = SQLiteDBUtils.getConnection(); try { DatabaseMetaData databaseMataDate = conn.getMetaData(); // 得到数据库中的所有表 ResultSet tabs = databaseMataDate.getTables(null, null, null,new String[] { "TABLE" }); ResultSet rs = null; Statement st = null; while (tabs.next()) {// 遍历所有表 Classes cla = new Classes(); // 得到表名 String className = tabs.getObject("TABLE_NAME").toString(); String lastClassName =getUpString(className.substring(className.lastIndexOf("_")+1)); |
if(lastClassName.equalsIgnoreCase("Sequence")){ continue; } cla.setClassName(lastClassName); String sql = "select * from "+tabs.getObject("TABLE_NAME"); st = conn.createStatement(); rs = st.executeQuery(sql); // 得到所有的字段类型和字段名 ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); String[][] strArr = new String[colCount][3]; for (int i = 1; i <= colCount; i++) { // 得到对应Java数据类型的类型 strArr[i-1][0] = getDataType(rsmd.getColumnTypeName(i),rsmd.getColumnName(i)); // 得到字段名 strArr[i-1][1] = getFieldName(rsmd.getColumnName(i)); // 得到首字母大写的字段名 strArr[i-1][2] = getUpString(rsmd.getColumnName(i)); } cla.setStrArr(strArr);
claList.add(cla); } tabs.close(); rs.close(); st.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } return claList; } |
得到的表名,字段名和数据类型一般还不能直接用,这个时候我们需要转换,如将全小写的表名转为首字母大写的类名,将数据库中的数据类型转为Java中的数据类型,将数据库中的列名中的下划线去掉,下划线后面跟的字母大写等。
四、准备Velocity的vm模板,用于生成对应的文件
package cn.ucai.pojo; import java.io.Serializable; public class ${classNameUpCase} implements Serializable { private static final long serialVersionUID = 1L; #foreach ($attr in ${attrs}) private ${attr[0]} ${attr[1]}; #end public ${classNameUpCase}(){ super(); } public ${classNameUpCase}(${allargs}){ #foreach($attr in ${attrs}) this.${attr[1]} = ${attr[1]}; #end }
#foreach ($attr in ${attrs}) public ${attr[0]} get${attr[2]}() { return this.${attr[1]}; }
public void set${attr[2]}(${attr[0]} ${attr[1]}){ this.${attr[1]} = ${attr[1]}; }
#end @Override public String toString() { return "${classNameUpCase} [" #foreach($attr in ${attrs}) + "this.${attr[1]}=" + ${attr[1]} #end ; } } |
在vm文件中,可以发现很多以 # 和$符开头的内容,这些都是Velocity的语法,在 Velocity 中所有的关键字都是以 # 开头的,而所有的变量则是以$开头,变量所代表的值,由上一步得到的数据,经由VelocityContext类提供。
除了变量外,这里用的多的就是Velocity中的循环语句,它用于循环生成重复性的内容,如getters和setters,toString中属性的拼接等。如:
#foreach ($attr in ${attrs}) public ${attr[0]} get${attr[2]}() { return this.${attr[1]}; } |
Velocity引擎会讲attrs中的值循环赋值给attr变量,attrs的值同样来源于VelocityContext。
五、使用Velocity,生成指定名字和字段的单个文件
这里主要是Velocity的使用,详细语法请参考代码注释,如下:
/** * 根据类名和字段信息生成实体类 * @param className 类名 * @param attrs 字段信息,包括字段的类型信息和字段名 */ public static void generateClass(String className,String[][] attrs){ // 创建Velocity引擎 VelocityEngine ve = new VelocityEngine(); // 初始化环境 ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); ve.init(); // 加载模板 Template actionTpt = ve.getTemplate("BeanTemplate.vm"); // 创建用于携带数据的VelocityContext; VelocityContext ctx = new VelocityContext(); // 设置类名到模板 |
ctx.put("classNameUpCase", className); // 设置全参构造参数名列表到模板 String result = ""; for(int i=0;i<attrs.length;i++){ result += attrs[i][0]+" "+attrs[i][1]+","; } ctx.put("allargs", result.substring(0,result.length()-1)); // 设置attrs数组到模板 ctx.put("attrs", attrs); PrintWriter pw; try { pw = new PrintWriter(newFile("src/cn/ucai/pojo/"+className+".java")); // 根据模板,将数据模板化之后转为Writer流。 actionTpt.merge(ctx, pw); pw.flush(); pw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } |
六、定义main方法,通过第三步得到的数据,根据第四步准备的vm模板,调用第五步生成单个文件的方法,将整个数据库对应的实体类生成
public static void main(String[] args) { List<Classes> list = getClassesData(); for(Classes cal : list){ generateClass(cal.getClassName(),cal.getStrArr()); } } |
运行程序,可以发现,实体类已经生成到指定包中,如下(以user表为例,生成了对应的User.java类)
package cn.ucai.pojo; import java.io.Serializable; public class User implements Serializable { |
private static final long serialVersionUID = 1L; private String muserName; private String muserPassword; private String muserNick; private Integer muserUnreadMsgCount; public User(){ super(); } public User(String muserName,String muserPassword,StringmuserNick,Integer muserUnreadMsgCount){ this.muserName = muserName; this.muserPassword = muserPassword; this.muserNick = muserNick; this.muserUnreadMsgCount = muserUnreadMsgCount; }
public String getM_user_name() { return this.muserName; }
public void setM_user_name(String muserName){ this.muserName = muserName; }
public String getM_user_password() { return this.muserPassword; }
public void setM_user_password(String muserPassword){ this.muserPassword = muserPassword; }
public String getM_user_nick() { return this.muserNick; }
public void setM_user_nick(String muserNick){ |
this.muserNick = muserNick; }
public Integer getM_user_unread_msg_count() { return this.muserUnreadMsgCount; }
public void setM_user_unread_msg_count(Integer muserUnreadMsgCount){ this.muserUnreadMsgCount = muserUnreadMsgCount; }
@Override public String toString() { return "User [" + "this.muserName=" + muserName + "this.muserPassword=" + muserPassword + "this.muserNick=" + muserNick + "this.muserUnreadMsgCount=" + muserUnreadMsgCount ; } } |
本文章中项目源代码:https://github.com/MyCloudream/DB2POJO
参考资料:http://www.ibm.com/developerworks/cn/java/j-lo-velocity1/
来自:https://mp.weixin.qq.com/s/wbchSN2QAuUPuoXQWav5Wg
相关文章