SORM框架
1 核心框架:
Query接口 负责查询(对外提供读物的核心类)
QueryFactory类 负责根据配置信息创建query对象
Typeconverto接口 负责类型转换
TableContext 类 负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构,
DBManager 类 根据配置信息,维持连接对象的管理增加连接池功能
工具类
JDBCUtil 封裝常用JDBC操作 StringUtil 封裝常用字符串操作
JavaFileUtil封裝java文件操作 ReflectUtil 封裝常用反射操作
client QueryFactory
<interface> DB2Query
query OracleQuery
mysqlQuery
TableContext
DBManager <interface> OracleTypeConvertor
TypeConvertor mysqlTypeConvertor
核心bean ,封裝相关数据
ColumnInfo 封裝表中一个字段的信息(字段类型、字段名、键类型)
Configuration 封裝配置文件信息
TableInfo 封裝一张表的信息
2、针对SORM框架的说明:
核心思想:使用简单、性能高、极易上手!
配置文件:
模卡使用资源文件、后期项目复杂后可以增加xml文件配置和注解。
类名有标明生成、只有受罪大写有区别,其他无区别
java对象的属性有表中字段生成,完全对应
目前,只支持表中只有一个主键,联合主键不支持
3.代码区
package com.bjsxt.po; import java.sql.*; import java.util.*; public class Dept { private Integer id; private String address; private String dname; public Integer getId(){ return id; } public String getAddress(){ return address; } public String getDname(){ return dname; } public void setId(Integer id){ this.id=id; } public void setAddress(String address){ this.address=address; } public void setDname(String dname){ this.dname=dname; } }
package com.bjsxt.po; import java.sql.*; import java.util.*; public class Emp { private Integer id; private java.sql.Date birthday; private Integer deptid; private String empname; private Integer age; private Double bonus; private Double salary; public Integer getId(){ return id; } public java.sql.Date getBirthday(){ return birthday; } public Integer getDeptid(){ return deptid; } public String getEmpname(){ return empname; } public Integer getAge(){ return age; } public Double getBonus(){ return bonus; } public Double getSalary(){ return salary; } public void setId(Integer id){ this.id=id; } public void setBirthday(java.sql.Date birthday){ this.birthday=birthday; } public void setDeptid(Integer deptid){ this.deptid=deptid; } public void setEmpname(String empname){ this.empname=empname; } public void setAge(Integer age){ this.age=age; } public void setBonus(Double bonus){ this.bonus=bonus; } public void setSalary(Double salary){ this.salary=salary; } }
package com.bjsxt.sorm.bean; /** * 封装表中一个字段的信息 * @author gaoiqi www.sxt.cn * @version 0.8 */ public class ColumnInfo { /** * 字段名称 */ private String name; /** * 字段的数据类型 */ private String dataType; /** * 字段的键类型(0:普通键,1:主键 2:外键) */ private int keyType; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public int getKeyType() { return keyType; } public void setKeyType(int keyType) { this.keyType = keyType; } public ColumnInfo(String name, String dataType, int keyType) { super(); this.name = name; this.dataType = dataType; this.keyType = keyType; } public ColumnInfo() { } }
package com.bjsxt.sorm.bean; /** * 管理配置信息 * @author gaoqi www.sxt.cn * */ public class Configuration { /** * 驱动类 */ private String driver; /** * jdbc的url */ private String url; /** * 数据库的用户名 */ private String user; /** * 数据库的密码 */ private String pwd; /** * 正在使用哪个数据库 */ private String usingDB; /** * 项目的源码路径 */ private String srcPath; /** * 扫描生成java类的包(po的意思是:Persistence object持久化对象) */ private String poPackage; private String queryClass; private int poolMinSize; private int poolMaxSize; public String getQueryClass() { return queryClass; } public void setQueryClass(String queryClass) { this.queryClass = queryClass; } public int getPoolMinSize() { return poolMinSize; } public void setPoolMinSize(int poolMinSize) { this.poolMinSize = poolMinSize; } public int getPoolMaxSize() { return poolMaxSize; } public void setPoolMaxSize(int poolMaxSize) { this.poolMaxSize = poolMaxSize; } public Configuration() { } public Configuration(String driver, String url, String user, String pwd, String usingDB, String srcPath, String poPackage) { super(); this.driver = driver; this.url = url; this.user = user; this.pwd = pwd; this.usingDB = usingDB; this.srcPath = srcPath; this.poPackage = poPackage; } public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getUsingDB() { return usingDB; } public void setUsingDB(String usingDB) { this.usingDB = usingDB; } public String getSrcPath() { return srcPath; } public void setSrcPath(String srcPath) { this.srcPath = srcPath; } public String getPoPackage() { return poPackage; } public void setPoPackage(String poPackage) { this.poPackage = poPackage; } }
package com.bjsxt.sorm.bean; /** * 封装了java属性和get、set方法的源代码 * @author gaoqi * */ public class JavaFieldGetSet { /** * 属性的源码信息。如:private int userId; */ private String fieldInfo; /** * get方法的源码信息.如:public int getUserId(){} */ private String getInfo; /** * set方法的源码信息.如:public void setUserId(int id){this.id = id;} */ private String setInfo; @Override public String toString() { System.out.println(fieldInfo); System.out.println(getInfo); System.out.println(setInfo); return super.toString(); } public String getFieldInfo() { return fieldInfo; } public void setFieldInfo(String fieldInfo) { this.fieldInfo = fieldInfo; } public String getGetInfo() { return getInfo; } public void setGetInfo(String getInfo) { this.getInfo = getInfo; } public String getSetInfo() { return setInfo; } public void setSetInfo(String setInfo) { this.setInfo = setInfo; } public JavaFieldGetSet(String fieldInfo, String getInfo, String setInfo) { super(); this.fieldInfo = fieldInfo; this.getInfo = getInfo; this.setInfo = setInfo; } public JavaFieldGetSet() { } }
package com.bjsxt.sorm.bean; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 存储表结构的信息 * @author gaoqi * */ public class TableInfo { /** * 表名 */ private String tname; /** * 所有字段的信息 */ private Map<String,ColumnInfo> columns; /** * 唯一主键(目前我们只能处理表中有且只有一个主键的情况) */ private ColumnInfo onlyPriKey; /** * 如果联合主键,则在这里存储 */ private List<ColumnInfo> priKeys; public List<ColumnInfo> getPriKeys() { return priKeys; } public void setPriKeys(List<ColumnInfo> priKeys) { this.priKeys = priKeys; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } public Map<String, ColumnInfo> getColumns() { return columns; } public void setColumns(Map<String, ColumnInfo> columns) { this.columns = columns; } public ColumnInfo getOnlyPriKey() { return onlyPriKey; } public void setOnlyPriKey(ColumnInfo onlyPriKey) { this.onlyPriKey = onlyPriKey; } public TableInfo(String tname, Map<String, ColumnInfo> columns, ColumnInfo onlyPriKey) { super(); this.tname = tname; this.columns = columns; this.onlyPriKey = onlyPriKey; } public TableInfo() { } public TableInfo(String tname,List<ColumnInfo> priKeys, Map<String, ColumnInfo> columns ) { super(); this.tname = tname; this.columns = columns; this.priKeys = priKeys; } }
package com.bjsxt.sorm.core; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public interface CallBack { public abstract Object doExecute(Connection conn, PreparedStatement ps, ResultSet rs); }
package com.bjsxt.sorm.core; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import com.bjsxt.sorm.bean.Configuration; import com.bjsxt.sorm.pool.DBConnPool; /** * 根据配置信息,维持连接对象的管理(增加连接池功能) * @author Administrator * */ public class DBManager { private static Configuration conf; private static DBConnPool pool; static { //静态代码块 Properties pros = new Properties(); try { pros.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties")); } catch (IOException e) { e.printStackTrace(); } conf = new Configuration(); conf.setDriver(pros.getProperty("driver")); conf.setPoPackage(pros.getProperty("poPackage")); conf.setPwd(pros.getProperty("pwd")); conf.setSrcPath(pros.getProperty("srcPath")); conf.setUrl(pros.getProperty("url")); conf.setUser(pros.getProperty("user")); conf.setUsingDB(pros.getProperty("usingDB")); conf.setQueryClass(pros.getProperty("queryClass")); conf.setPoolMaxSize(Integer.parseInt(pros.getProperty("poolMaxSize"))); conf.setPoolMinSize(Integer.parseInt(pros.getProperty("poolMinSize"))); System.out.println(TableContext.class); } /*public static Connection getConn(){ try { Class.forName(conf.getDriver()); return DriverManager.getConnection(conf.getUrl(), conf.getUser(),conf.getPwd()); //直接建立连接,后期增加连接池处理,提高效率!!! } catch (Exception e) { e.printStackTrace(); return null; } }*/ public static Connection getConn() { if (pool == null) { pool = new DBConnPool(); } return pool.getConnection(); } public static Connection createConn() { try { Class.forName(conf.getDriver()); return DriverManager.getConnection(conf.getUrl(), conf.getUser(), conf.getPwd()); } catch (Exception e) { e.printStackTrace(); }return null; } public static void close(ResultSet rs, Statement ps, Connection conn) { try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } pool.close(conn); } public static void close(Statement ps, Connection conn) { try { if (ps != null) ps.close(); } catch (SQLException e) { e.printStackTrace(); } pool.close(conn); } public static void close(Connection conn) { pool.close(conn); } /** * 返回Configuration对象 * @return */ public static Configuration getConf(){ return conf; } }
package com.bjsxt.sorm.core; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.List; import com.bjsxt.po.Dept; import com.bjsxt.po.Emp; import com.bjsxt.sorm.bean.ColumnInfo; import com.bjsxt.sorm.bean.TableInfo; import com.bjsxt.sorm.utils.JDBCUtils; import com.bjsxt.sorm.utils.ReflectUtils; import com.bjsxt.vo.EmpVO; /** * 负责针对Mysql数据库的查询 * @author gaoqi * */ public class MySqlQuery extends Query { public static void testDML(){ Emp e = new Emp(); e.setEmpname("lily"); e.setBirthday(new java.sql.Date(System.currentTimeMillis())); e.setAge(30); e.setSalary(3000.8); e.setId(1); // new MySqlQuery().delete(e); // new MySqlQuery().insert(e); new MySqlQuery().update(e,new String[]{"empname","age","salary"}); } public static void testQueryRows(){ List<Emp> list = new MySqlQuery().queryRows("select id,empname,age from emp where age>? and salary<?", Emp.class, new Object[]{10,5000}); for(Emp e:list){ System.out.println(e.getEmpname()); } String sql2 = "select e.id,e.empname,salary+bonus 'xinshui',age,d.dname 'deptName',d.address 'deptAddr' from emp e " +"join dept d on e.deptId=d.id "; List<EmpVO> list2 = new MySqlQuery().queryRows(sql2, EmpVO.class, null); for(EmpVO e:list2){ System.out.println(e.getEmpname()+"-"+e.getDeptAddr()+"-"+e.getXinshui()); } } public static void main(String[] args) { /* Number obj = (Number)new MySqlQuery().queryValue("select count(*) from emp where salary>?",new Object[]{1000}); Number obj = new MySqlQuery().queryNumber("select count(*) from emp where salary>?",new Object[]{1000}); System.out.println(obj.doubleValue());*/ //查询信息 List<Emp> emps=new MySqlQuery().queryRows("select * from emp", Emp.class, new Object[0]); for (Emp emp : emps) { System.out.println(emp.toString()); //Emp [id=1, birthday=2017-11-15, deptid=1, empname=周无极, age=12, bonus=20.0, salary=1200.0] } /*Number number=(Number)new MySqlQuery().queryValue("select count(*) from emp ",null); System.out.println(number.toString());*/ //添加信息 /* Dept dept=new Dept(); dept.setAddress("南京路"); dept.setDname("采购部"); new MySqlQuery().insert(dept);*/ } @Override public Object queryPagenate(int pageNum, int size) { return null; } }
package com.bjsxt.sorm.core; /** * mysql数据类型和java数据类型的转换 * @author gaoqi * */ 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("clob".equalsIgnoreCase(columnType)){ return "java.sql.CLob"; }else if("blob".equalsIgnoreCase(columnType)){ return "java.sql.BLob"; }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 javaType2DatabaseType(String javaDataType) { return null; } }
package com.bjsxt.sorm.core; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.bjsxt.sorm.bean.ColumnInfo; import com.bjsxt.sorm.bean.TableInfo; import com.bjsxt.sorm.utils.JDBCUtils; import com.bjsxt.sorm.utils.ReflectUtils; /** * 负责查询(对外提供服务的核心类) * @author gaoqi ww.sxt.cn * */ @SuppressWarnings("all") public abstract class Query implements Cloneable{ public Object executeQueryTemplate(String sql, Object[] params, Class clazz, CallBack back) { Connection conn = DBManager.getConn(); PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(sql); JDBCUtils.handleParams(ps, params); System.out.println(ps); rs = ps.executeQuery(); return back.doExecute(conn, ps, rs); } catch (Exception e) { e.printStackTrace(); return null; } finally { DBManager.close(ps, conn); } } /** * 直接执行一个DML语句 * @param sql sql语句 * @param params 参数 * @return 执行sql语句后影响记录的行数 */ public int executeDML(String sql, Object[] params) { Connection conn = DBManager.getConn(); int count = 0; PreparedStatement ps = null; try { ps = conn.prepareStatement(sql); //给sql设参 JDBCUtils.handleParams(ps, params); System.out.println(ps); count = ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally{ DBManager.close(ps, conn); } return count; } /** * 将一个对象存储到数据库中 * 把对象中不为null的属性往数据库中存储!如果数字为null则放0. * @param obj 要存储的对象 */ public void insert(Object obj) { //obj-->表中。 insert into 表名 (id,uname,pwd) values (?,?,?) Class c = obj.getClass(); List<Object> params = new ArrayList<Object>(); //存储sql的参数对象 TableInfo tableInfo = TableContext.poClassTableMap.get(c); StringBuilder sql = new StringBuilder("insert into "+tableInfo.getTname()+" ("); int countNotNullField = 0; //计算不为null的属性值 Field[] fs = c.getDeclaredFields(); for(Field f:fs){ String fieldName = f.getName(); Object fieldValue = ReflectUtils.invokeGet(fieldName, obj); if(fieldValue!=null){ countNotNullField++; sql.append(fieldName+","); params.add(fieldValue); } } sql.setCharAt(sql.length()-1, ')'); sql.append(" values ("); for(int i=0;i<countNotNullField;i++){ sql.append("?,"); } sql.setCharAt(sql.length()-1, ')'); executeDML(sql.toString(), params.toArray()); } /** * 删除clazz表示类对应的表中的记录(指定主键值id的记录) * @param clazz 跟表对应的类的Class对象 * @param id 主键的值 */ public void delete(Class clazz, Object id) { //Emp.class,2-->delete from emp where id=2 //通过Class对象找TableInfo TableInfo tableInfo = TableContext.poClassTableMap.get(clazz); //获得主键 ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey(); String sql = "delete from "+tableInfo.getTname()+" where "+onlyPriKey.getName()+"=? "; executeDML(sql, new Object[]{id}); } /** * 删除对象在数据库中对应的记录(对象所在的类对应到表,对象的主键的值对应到记录) * @param obj */ public void delete(Object obj) { Class c = obj.getClass(); TableInfo tableInfo = TableContext.poClassTableMap.get(c); ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey(); //主键 //通过反射机制,调用属性对应的get方法或set方法 Object priKeyValue = ReflectUtils.invokeGet(onlyPriKey.getName(), obj); delete(c, priKeyValue); } /** * 更新对象对应的记录,并且只更新指定的字段的值 * @param obj 所要更新的对象 * @param fieldNames 更新的属性列表 * @return 执行sql语句后影响记录的行数 */ public int update(Object obj, String[] fieldNames) { //obj{"uanme","pwd"}-->update 表名 set uname=?,pwd=? where id=? Class c = obj.getClass(); List<Object> params = new ArrayList<Object>(); //存储sql的参数对象 //从加载数据库表信息放在map集合里,根据tablebame.class取表信息 TableInfo tableInfo = TableContext.poClassTableMap.get(c); ColumnInfo priKey = tableInfo.getOnlyPriKey(); //获得唯一的主键 StringBuilder sql = new StringBuilder("update "+tableInfo.getTname()+" set "); for(String fname:fieldNames){ Object fvalue = ReflectUtils.invokeGet(fname,obj); params.add(fvalue); sql.append(fname+"=?,"); } sql.setCharAt(sql.length()-1, ' '); sql.append(" where "); sql.append(priKey.getName()+"=? "); params.add(ReflectUtils.invokeGet(priKey.getName(), obj)); //主键的值 return executeDML(sql.toString(), params.toArray()); } /** * 查询返回多行记录,并将每行记录封装到clazz指定的类的对象中 * @param sql 查询语句 * @param clazz 封装数据的javabean类的Class对象 * @param params sql的参数 * @return 查询到的结果 */ public List queryRows(final String sql,final Class clazz,final Object[] params){ return (List)executeQueryTemplate(sql, params, clazz, new CallBack(){ @Override public Object doExecute(Connection conn,PreparedStatement ps,ResultSet rs) { List list=null; try{ ResultSetMetaData metaData = rs.getMetaData(); while (rs.next()) { if (list==null) { list=new ArrayList(); } Object rowObj = clazz.newInstance(); for (int i = 0; i < metaData.getColumnCount(); i++) { String columnName = metaData.getColumnLabel(i + 1); Object columnValue = rs.getObject(i + 1); ReflectUtils.invokeSet(rowObj, columnName, columnValue); } list.add(rowObj); } } catch (Exception e) { e.printStackTrace(); } return list; } }); } /** * 查询返回一行记录,并将该记录封装到clazz指定的类的对象中 * @param sql 查询语句 * @param clazz 封装数据的javabean类的Class对象 * @param params sql的参数 * @return 查询到的结果 */ public Object queryUniqueRow(String sql, Class clazz, Object[] params) { List list = queryRows(sql, clazz, params); return (list==null&&list.size()>0)?null:list.get(0); } /** * 查询返回一个值(一行一列),并将该值返回 * @param sql 查询语句 * @param params sql的参数 * @return 查询到的结果 */ public Object queryValue(String sql, Object[] params) { return executeQueryTemplate(sql, params, null, new CallBack() { @Override public Object doExecute(Connection conn, PreparedStatement ps, ResultSet rs) { Object value = null; try { while (rs.next()) value = rs.getObject(1); } catch (SQLException e) { e.printStackTrace(); } return value; } }); } /** * 查询返回一个数字(一行一列),并将该值返回 * @param sql 查询语句 * @param params sql的参数 * @return 查询到的数字 */ public Number queryNumber(String sql, Object[] params) { return (Number)queryValue(sql, params); } /** * 分页查询 */ public abstract Object queryPagenate(int pageNum,int size); protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
package com.bjsxt.sorm.core; import com.bjsxt.sorm.bean.Configuration; public class QueryFactory { private static Query prototypeObj; static { try { Class c = Class.forName(DBManager.getConf().getQueryClass()); prototypeObj = (Query)c.newInstance(); } catch (Exception e) { e.printStackTrace(); } TableContext.loadPOTables(); } public static Query createQuery() { try { return (Query)prototypeObj.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); }return null; } }
package com.bjsxt.sorm.core; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import com.bjsxt.sorm.bean.ColumnInfo; import com.bjsxt.sorm.bean.TableInfo; import com.bjsxt.sorm.utils.JavaFileUtils; import com.bjsxt.sorm.utils.StringUtils; /** * 负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构。 * @author gaoqi www.sxt.cn * */ public class TableContext { /** * 表名为key,表信息对象为value */ public static Map<String,TableInfo> tables = new HashMap<String,TableInfo>(); /** * 将po的class对象和表信息对象关联起来,便于重用! */ public static Map<Class,TableInfo> poClassTableMap = new HashMap<Class,TableInfo>(); private TableContext(){} static { try { //初始化获得表的信息 Connection con = DBManager.getConn(); DatabaseMetaData dbmd = con.getMetaData(); ResultSet tableRet = dbmd.getTables(null, "%","%",new String[]{"TABLE"}); while(tableRet.next()){ //得到第一个表名 String tableName = (String) tableRet.getObject("TABLE_NAME"); TableInfo ti = new TableInfo(tableName, new ArrayList<ColumnInfo>() ,new HashMap<String, ColumnInfo>()); tables.put(tableName, ti); //得到第一个表字段的信息 ResultSet set = dbmd.getColumns(null, "%", tableName, "%"); //查询表中的所有字段 while(set.next()){ ColumnInfo ci = new ColumnInfo(set.getString("COLUMN_NAME"), set.getString("TYPE_NAME"), 0); ti.getColumns().put(set.getString("COLUMN_NAME"), ci); } //得到第一个表里的主键 ResultSet set2 = dbmd.getPrimaryKeys(null, "%", tableName); //查询t_user表中的主键 while(set2.next()){ ColumnInfo ci2 = (ColumnInfo) ti.getColumns().get(set2.getObject("COLUMN_NAME")); ci2.setKeyType(1); //设置为主键类型 ti.getPriKeys().add(ci2); } if(ti.getPriKeys().size()>0){ //取唯一主键。。方便使用。如果是联合主键。则为空! ti.setOnlyPriKey(ti.getPriKeys().get(0)); } } } catch (SQLException e) { e.printStackTrace(); } //更新类结构 updateJavaPOFile(); //加载po包下面所有的类,便于重用,提高效率! loadPOTables(); } /** * 根据表结构,更新配置的po包下面的java类 * 实现了从表结构转化到类结构 */ public static void updateJavaPOFile(){ Map<String,TableInfo> map = TableContext.tables; for(TableInfo t:map.values()){ JavaFileUtils.createJavaPOFile(t,new MySqlTypeConvertor()); } } /** * 加载po包下面的类,向poClassTableMap集合放入tableInfo */ public static void loadPOTables(){ for(TableInfo tableInfo:tables.values()){ try { Class c = Class.forName(DBManager.getConf().getPoPackage() +"."+StringUtils.firstChar2UpperCase(tableInfo.getTname())); poClassTableMap.put(c, tableInfo); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } /** * 循环遍历集合 * @param args */ public static void main(String[] args) { Map<String,TableInfo> tables = TableContext.tables; Iterator iterator=tables.values().iterator(); while (iterator.hasNext()) { TableInfo object = (TableInfo) iterator.next(); System.out.println(object); } } }
package com.bjsxt.sorm.core; /** * 负责java数据类型和数据库数据类型的互相转换 * @author gaoqi www.sxt.cn * */ public interface TypeConvertor { /** * 将数据库数据类型转化成java的数据类型 * @param columnType 数据库字段的数据类型 * @return java的数据类型 */ public String databaseType2JavaType(String columnType); /** * 将java数据类型转化成数据库数据类型 * @param javaDataType java数据类型 * @return 数据库类型 */ public String javaType2DatabaseType(String javaDataType); }
package com.bjsxt.sorm.pool; import com.bjsxt.sorm.bean.Configuration; import com.bjsxt.sorm.core.DBManager; import java.io.PrintStream; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class DBConnPool { private List<Connection> pool; private static final int POOL_MAX_SIZE = DBManager.getConf().getPoolMaxSize(); private static final int POOL_MIN_SIZE = DBManager.getConf().getPoolMinSize(); public void initPool() { if (this.pool == null) { this.pool = new ArrayList(); } while (this.pool.size() < POOL_MIN_SIZE) { this.pool.add(DBManager.createConn()); System.out.println("初始化池,池中连接数:" + this.pool.size()); } } public synchronized Connection getConnection() { int last_index = this.pool.size() - 1; Connection conn = (Connection)this.pool.get(last_index); this.pool.remove(last_index); return conn; } public synchronized void close(Connection conn) { if (this.pool.size() >= POOL_MAX_SIZE) try { if (conn == null) return; conn.close(); } catch (SQLException e) { e.printStackTrace(); } else this.pool.add(conn); } public DBConnPool() { initPool(); } }
package com.bjsxt.sorm.utils; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.bjsxt.sorm.bean.ColumnInfo; import com.bjsxt.sorm.bean.JavaFieldGetSet; import com.bjsxt.sorm.bean.TableInfo; import com.bjsxt.sorm.core.DBManager; import com.bjsxt.sorm.core.MySqlTypeConvertor; import com.bjsxt.sorm.core.TableContext; import com.bjsxt.sorm.core.TypeConvertor; /** * 封装了生成Java文件(源代码)常用的操作 * @author www.sxt.cn * */ public class JavaFileUtils { /** * 根据字段信息生成java属性信息。如:varchar 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()); jfgs.setFieldInfo(" private "+javaFieldType+" "+column.getName()+"; "); //public String getUsername(){return username;} //生成get方法的源代码 StringBuilder getSrc = new StringBuilder(); getSrc.append(" public "+javaFieldType+" get"+StringUtils.firstChar2UpperCase(column.getName())+"(){ "); getSrc.append(" return "+column.getName()+"; "); getSrc.append(" } "); jfgs.setGetInfo(getSrc.toString()); //public void setUsername(String username){this.username=username;} //生成set方法的源代码 StringBuilder setSrc = new StringBuilder(); setSrc.append(" public void set"+StringUtils.firstChar2UpperCase(column.getName())+"("); setSrc.append(javaFieldType+" "+column.getName()+"){ "); setSrc.append(" this."+column.getName()+"="+column.getName()+"; "); setSrc.append(" } "); jfgs.setSetInfo(setSrc.toString()); return jfgs; } /** * 根据表信息生成java类的源代码 * @param tableInfo 表信息 * @param convertor 数据类型转化器 * @return java类的源代码 */ public static String createJavaSrc(TableInfo tableInfo,TypeConvertor convertor){ Map<String,ColumnInfo> columns = tableInfo.getColumns(); List<JavaFieldGetSet> javaFields = new ArrayList<JavaFieldGetSet>(); for(ColumnInfo c:columns.values()){ javaFields.add(createFieldGetSetSRC(c,convertor)); } StringBuilder src = new StringBuilder(); //生成package语句 src.append("package "+DBManager.getConf().getPoPackage()+"; "); //生成import语句 src.append("import java.sql.*; "); src.append("import java.util.*; "); //生成类声明语句 src.append("public class "+StringUtils.firstChar2UpperCase(tableInfo.getTname())+" { "); //生成属性列表 for(JavaFieldGetSet f:javaFields){ src.append(f.getFieldInfo()); } src.append(" "); //生成get方法列表 for(JavaFieldGetSet f:javaFields){ src.append(f.getGetInfo()); } //生成set方法列表 for(JavaFieldGetSet f:javaFields){ src.append(f.getSetInfo()); } //生成类结束 src.append("} "); return src.toString(); } public static void createJavaPOFile(TableInfo tableInfo,TypeConvertor convertor){ String src = createJavaSrc(tableInfo,convertor); String srcPath = DBManager.getConf().getSrcPath()+"\"; //替换 String packagePath = DBManager.getConf().getPoPackage().replaceAll("\.", "/"); File f = new File(srcPath+packagePath); if(!f.exists()){ //如果指定目录不存在,则帮助用户建立 f.mkdirs(); } BufferedWriter bw = null; try { bw = new BufferedWriter(new FileWriter(f.getAbsoluteFile()+"/"+StringUtils.firstChar2UpperCase(tableInfo.getTname())+".java")); bw.write(src); System.out.println("建立表"+tableInfo.getTname()+ "对应的java类:"+StringUtils.firstChar2UpperCase(tableInfo.getTname())+".java"); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(bw!=null){ bw.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { // ColumnInfo ci = new ColumnInfo("id", "int", 0); // JavaFieldGetSet f = createFieldGetSetSRC(ci,new MySqlTypeConvertor()); // System.out.println(f); Map<String,TableInfo> map = TableContext.tables; for(TableInfo t:map.values()){ createJavaPOFile(t,new MySqlTypeConvertor()); } } }
package com.bjsxt.sorm.utils; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 封装了JDBC查询常用的操作 * @author gaoqi www.sxt.cn * */ public class JDBCUtils { /** * //给sql设参 * @param ps 预编译sql语句对象 * @param params 参数 */ public static void handleParams(PreparedStatement ps,Object[] params){ if(params!=null){ for(int i=0;i<params.length;i++){ try { ps.setObject(1+i, params[i]); } catch (SQLException e) { e.printStackTrace(); } } } } }
package com.bjsxt.sorm.utils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 封装了反射常用的操作 * * */ public class ReflectUtils { /** * 调用obj对象对应属性fieldName的get方法 * @param fieldName * @param obj * @return */ public static Object invokeGet(String fieldName,Object obj){ try { Class c = obj.getClass(); Method m = c.getDeclaredMethod("get"+StringUtils.firstChar2UpperCase(fieldName), null); return m.invoke(obj, null); } catch (Exception e) { e.printStackTrace(); return null; } } public static void invokeSet(Object obj,String columnName,Object columnValue){ try { Method m = obj.getClass().getDeclaredMethod("set"+StringUtils.firstChar2UpperCase(columnName), columnValue.getClass()); m.invoke(obj, columnValue); } catch (Exception e) { e.printStackTrace(); } } }
package com.bjsxt.sorm.utils; /** * 封装了字符串常用的操作 * @author gaoqi www.sxt.cn * */ public class StringUtils { /** * 将目标字符串首字母变为大写 * @param str 目标字符串 * @return 首字母变为大写的字符串 */ public static String firstChar2UpperCase(String str){ //abcd-->Abcd //abcd-->ABCD-->Abcd return str.toUpperCase().substring(0, 1)+str.substring(1); } }
package com.bjsxt.vo; public class EmpVO { private Integer id; private String empname; private Double xinshui; private Integer age; private String deptName; private String deptAddr; public EmpVO(Integer id, String empname, Double xinshui, Integer age, String deptName, String deptAddr) { super(); this.id = id; this.empname = empname; this.xinshui = xinshui; this.age = age; this.deptName = deptName; this.deptAddr = deptAddr; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } public Double getXinshui() { return xinshui; } public void setXinshui(Double xinshui) { this.xinshui = xinshui; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public String getDeptAddr() { return deptAddr; } public void setDeptAddr(String deptAddr) { this.deptAddr = deptAddr; } public EmpVO() { } }
package com.test; import java.util.List; import com.bjsxt.po.Emp; import com.bjsxt.sorm.core.QueryFactory; public class Test { public static void test01() { List<Emp> emps = QueryFactory.createQuery().queryRows("select * from emp", Emp.class, null); for (Emp emp : emps) { System.out.println(emp.toString()); } } public static void main(String[] args) { Long begin=System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { test01(); } Long end=System.currentTimeMillis(); System.out.println(end-begin);//1262 } }
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/TB47 user=root pwd=123456 usingDB=mysql srcPath=D:\workspace\sormtest\src #生成的实体类放的路径 poPackage=com.bjsxt.po #配置的是mysqlquery queryClass=com.bjsxt.sorm.core.MySqlQuery poolMinSize=10 poolMaxSize=100