手写ORM持久层框架(转)

工程结构:

本文测试的数据库为:

其中student的表结构为:

      

表数据:

配置文件 DB2.properties

driver=com.mysql.jdbc.Driver
url=jdbc\:mysql\://127.0.0.1\:3306/test
user=root
password=123456
usingDB=mysql
srcPath=E:/eclipse_workspace/Test/src
poPackage=com.frank.po
queryClass=com.frank.stom.core.imp.MySqlQuery
poolMinSize=10
poolMaxSize=100

只支持mysql数据库.poPackage为框架根据数据库表自动生成的domain类的包名

下面堆代码:

package com.frank.stom.bean;

/**
 * 封装表中一个字段的信息
 *
 */
public class ColumnInfo {

    public static final int NORMAL_KEY=0;
    public static final int PRIMARY_KEY=1;
    public static final int FOREIGN_KEY=2;
    
    /**
     *  字段名称
     */
    private String colName;
    
    /**
     * 字段类型
     */
    private String dataType;
    
    /**
     * 字段的键类型
     * 0:普通键 1:主键 2:外键
     */
    private int keyType;
    
    public ColumnInfo(String colName, String dataType, int keyType) {
        super();
        this.colName = colName;
        this.dataType = dataType;
        this.keyType = keyType;
    }
    
    public ColumnInfo() {
        
    }

    public String getColName() {
        return colName;
    }

    public void setColName(String colName) {
        this.colName = colName;
    }

    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;
    }

}
package com.frank.stom.bean;

/**
 * 管理配置信息
 *
 */
public class Configuration {
    /**
     * 驱动类
     */
    private String driver;
    /**
     * jdbc-url
     */
    private String url;
    /**
     * 数据库用户名
     */
    private String user;
    /**
     * 数据库密码
     */
    private String password;
    /**
     * 使用的数据库
     */
    private String usingDB;
    /**
     * 项目的源码路径
     */
    private String srcPath;
    /**
     * 扫描生成java类的包
     * persistence object
     */
    private String poPackage;
    
    /**
     * 连接池中最小的连接数
     */
    private int poolMinSize;
    /**
     * 连接池中最大的连接数
     */
    private int poolMaxSize;
    
    /**
     * 项目使用的查询类
     */
    private String queryClass;
    
    public String getQueryClass() {
        return queryClass;
    }
    public void setQueryClass(String queryClass) {
        this.queryClass = queryClass;
    }
    public Configuration(String driver, String url, String user,
            String password, String usingDB,
            String srcPath, String poPackage) {
        super();
        this.driver = driver;
        this.url = url;
        this.user = user;
        this.password = password;
        this.usingDB = usingDB;
        this.srcPath = srcPath;
        this.poPackage = poPackage;
    }
    
    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() {
        super();
    }
    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 getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    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.frank.stom.bean;

/**
 * 封装了java属性和set/get源码信息
 * 
 * @author frank
 * 
 */
public class JavaFieldGetSet {
    /**
     * 属性的源码信息
     */
    private String fieldInfo;
    /**
     * get的源码信息
     */
    private String getInfo;
    /**
     * set的源码信息
     */
    private String setInfo;
    
    public JavaFieldGetSet(String fieldInfo, String getInfo, String setInfo) {
        super();
        this.fieldInfo = fieldInfo;
        this.getInfo = getInfo;
        this.setInfo = setInfo;
    }

    public JavaFieldGetSet() {
        super();
    }

    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;
    }

    @Override
    public String toString() {
        System.out.println(fieldInfo);
        System.out.println(getInfo);
        System.out.println(setInfo);
        return super.toString();
    }

}
package com.frank.stom.bean;

import java.util.List;
import java.util.Map;

/**
 * 封装表结构信息
 * @author frank
 *
 */
public class TableInfo {
    
    /**
     * 表名
     */
    private String tabName;
    
    /**
     * 所以字段信息 
     */
    private Map<String,ColumnInfo> columns;

    /**
     * 主键
     */
    private ColumnInfo priKey;
    
    /**
     *联合主键 
     *
     */
    private List<ColumnInfo> priKeys;
    
    public TableInfo(String tabName, Map<String, ColumnInfo> columns, ColumnInfo priKey) {
        super();
        this.tabName = tabName;
        this.columns = columns;
        this.priKey = priKey;
    }

    public TableInfo(String tabName, Map<String, ColumnInfo> columns,
            List<ColumnInfo> priKeys) {
        super();
        this.tabName = tabName;
        this.columns = columns;
        this.priKeys = priKeys;
    }

    public TableInfo() {
        super();
    }
    

    public List<ColumnInfo> getPriKeys() {
        return priKeys;
    }

    public void setPriKeys(List<ColumnInfo> priKeys) {
        this.priKeys = priKeys;
    }

    public String getTabName() {
        return tabName;
    }

    public void setTabName(String tabName) {
        this.tabName = tabName;
    }

    public Map<String, ColumnInfo> getColumns() {
        return columns;
    }

    public void setColumns(Map<String, ColumnInfo> columns) {
        this.columns = columns;
    }

    public ColumnInfo getPriKey() {
        return priKey;
    }

    public void setPriKey(ColumnInfo priKey) {
        this.priKey = priKey;
    }

}
package com.frank.stom.connPool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.frank.stom.core.DBManager;

/**
 * 连接池
 * @author frank
 *
 */
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 DBconnPool(){
        initPool();
    }
    
    /**
     * 初始化连接池
     */
    public void initPool(){
        if(pool==null){
            pool=new ArrayList<Connection>();
        }
        while(pool.size()<POOL_MIN_SIZE){
            pool.add(DBManager.createConnection());
        }
    }
    
    /**
     * 从连接池中取出一个连接
     * @return 连接
     */
    public synchronized Connection getConnection(){
        int last_index=pool.size()-1;
        Connection conn = pool.get(last_index);
        pool.remove(last_index);
        return conn;
    }
    
    /**
     * 将连接放回池中
     * @param conn 连接
     */
    public synchronized void close(Connection conn){
        if(pool.size()>=POOL_MAX_SIZE)
            try {
                if(conn!=null)
                    conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        else
            pool.add(conn);
        
    }
    
}
package com.frank.stom.core.imp;

import com.frank.stom.core.Query;

/**
 * 负责mysql数据库的操作
 * @author frank
 *
 */
public class MySqlQuery extends Query {

//    @Override
//    public Object queryPagenate(int pageNum, int pageSize) {
//        return null;
//    }
}
package com.frank.stom.core.imp;

import com.frank.stom.core.TypeConvertor;


/**
 * mysql数据库类型和java类型的转换
 * 
 * @author frank
 * 
 */
public class MysqlTypeConvertor implements TypeConvertor {

    @Override
    public String databaseType2JavaType(String columnType) {
        // TODO Auto-generated method stub
        // 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 javaType) {
        return null;
    }

}
package com.frank.stom.core;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public interface CallBack {
    public Object doExecute(Connection conn, PreparedStatement ps,ResultSet rs);
}
package com.frank.stom.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.frank.stom.bean.Configuration;
import com.frank.stom.connPool.DBconnPool;

/**
 *  根据配置信息,维持连接对象的管理 
 * @author frank
 *
 */
public class DBManager {

    /**
     * 配置信息
     */
    private static Configuration conf;
    /**
     * 连接池对象
     */
    private static DBconnPool pool ;
    public static Configuration getConf() {
        return conf;
    }
    static{
        Properties pros=new Properties();
        
        try {
            pros.load(DBManager.class.getClassLoader().getResourceAsStream("DB2.properties"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        conf = new Configuration();
        conf.setDriver(pros.getProperty("driver"));
        conf.setPoPackage(pros.getProperty("poPackage"));
        conf.setPassword(pros.getProperty("password"));
        conf.setUrl(pros.getProperty("url"));
        conf.setUser(pros.getProperty("user"));
        conf.setSrcPath(pros.getProperty("srcPath"));
        conf.setUsingDB(pros.getProperty("usingDB"));
        conf.setQueryClass(pros.getProperty("queryClass"));
        conf.setPoolMaxSize(Integer.parseInt(pros.getProperty("poolMaxSize")));
        conf.setPoolMinSize(Integer.parseInt(pros.getProperty("poolMinSize")));  
    }
    /**
     * 获得数据库连接
     * @return 连接
     */
    public static Connection createConnection(){
        try {
            Class.forName(conf.getDriver());
            return DriverManager.getConnection(conf.getUrl(), conf.getUser(), conf.getPassword());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 从连接池中获得数据库连接
     * @return 连接
     */
    public static Connection getConnection(){
//        try {
//            Class.forName(conf.getDriver());
//            return DriverManager.getConnection(conf.getUrl(), conf.getUser(), conf.getPassword());
//        } catch (Exception e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//            return null;
        if(pool==null)
            pool = new DBconnPool();
        return pool.getConnection();
        
    }
    /**
     * 关闭资源
     * @param rs
     * @param ps
     * @param conn
     */
    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);
    }
}
package com.frank.stom.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.frank.stom.bean.ColumnInfo;
import com.frank.stom.bean.TableInfo;
import com.frank.stom.util.JDBCUtil;
import com.frank.stom.util.ReflectUtil;

/**
 *    负责查询 对外提供服务的核心类 
 * @author frank
 */
public abstract class Query implements Cloneable{
    
    /**
     * 采用模板方法模式将JDBC操作封装成模板
     * @param sql sql语句
     * @param params sql参数 
     * @param clazz 记录要封装到的java类
     * @param back CallBack的实现类 回调
     * @return
     */
    public Object executeQueryTemplate(String sql,Object[] params, Class clazz,CallBack back){
        Connection conn=DBManager.getConnection();
        PreparedStatement ps=null;
        ResultSet rs=null;

        try {
            ps=conn.prepareStatement(sql);
            JDBCUtil.handleParams(ps, params);
            rs=ps.executeQuery();
            return back.doExecute(conn, ps, rs);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }finally{
            DBManager.close(null, ps, conn);
        }
    }
    
    /**
     *    执行一条DML语句 
     * @param sql 要执行的sql语句
     * @param params sql语句参数
     * @return 影响的记录行数
     */
    public int executeDML(String sql, Object[] params) {
        Connection conn=DBManager.getConnection();
        int count=0;
        
        PreparedStatement ps=null;
        
        try {
            ps=conn.prepareStatement(sql);
            JDBCUtil.handleParams(ps, params);
            count=ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            DBManager.close(null, ps, conn);
        }
        return count;
    }
    
    /**
     * 将一个对象储存到数据库中
     * @param obj 要储存的对象
     */
    public void save(Object obj) {
        Class c=obj.getClass();
        List<Object> params =new ArrayList<Object>();
        TableInfo tableInfo = TableContext.poClassTableMap.get(c);
        StringBuilder sql=new StringBuilder("insert into "+tableInfo.getTabName()+" (");
        Field[] fs=c.getDeclaredFields();
        int fieldNotNullCount=0;

        for(Field field:fs){
            String fieldName=field.getName();
            Object fieldValue = ReflectUtil.invokeGet(fieldName, obj);

            if(fieldValue!=null){
                fieldNotNullCount++;
                sql.append(fieldName+",");
                params.add(fieldValue);
            }
        }
        sql.setCharAt(sql.length()-1, ')');
        sql.append(" values (");
        for(int i=0;i<fieldNotNullCount;i++){
            sql.append("?,");
        }
        sql.setCharAt(sql.length()-1, ')');

        this.executeDML(sql.toString(), params.toArray());
    }
    
    /**
     *    删除数据库中的记录 
     * @param clazz 对象类型
     * @param id 主键id
     * @return 影响的记录行数
     */
    @SuppressWarnings("rawtypes")
    public int delete(Class clazz, Object id) {
        // TODO Auto-generated method stub
        //通过class找TableInfo
        TableInfo tableInfo=TableContext.poClassTableMap.get(clazz);
        //主键
        ColumnInfo onlyPriKey=tableInfo.getPriKey();
        
        String sql="delete from "+tableInfo.getTabName()+" where  "+onlyPriKey.getColName()+"=?";
        
        return executeDML(sql, new Object[]{id});

    }
    
    /**
     *    删除对应数据库中的记录 
     * @param obj 要删除的对象
     * @return 影响的记录行数
     */

    public int delete(Object obj) {
        // TODO Auto-generated method stub
        Class c = obj.getClass();
        TableInfo tableInfo = TableContext.poClassTableMap.get(c);
        ColumnInfo onlyPrikey  = tableInfo.getPriKey();
        
        //反射
        Object priKeyValue=ReflectUtil.invokeGet(onlyPrikey.getColName(), obj);
        return delete(c, priKeyValue);
        
    }

    /**
     *     更新对象对应的记录
     * @param obj 对象
     * @return 影响的记录行数
     */
    public int update(Object obj ,String[] fieldNames) {
        // TODO Auto-generated method stub
        Class c=obj.getClass();
        List<Object> params =new ArrayList<Object>();
        TableInfo tableInfo = TableContext.poClassTableMap.get(c);
        ColumnInfo priKey = tableInfo.getPriKey();
        StringBuilder sql=new StringBuilder("update  "+tableInfo.getTabName()+" set ");

        for(String fieldName: fieldNames){
            Object fvalue = ReflectUtil.invokeGet(fieldName, obj);
            params.add(fvalue);
            sql.append(fieldName+"=?,");
        }
        params.add(ReflectUtil.invokeGet( priKey.getColName(),obj));

        sql.setCharAt(sql.length()-1,' ');
        sql.append(" where ");
        sql.append(priKey.getColName()+"=? ");
        System.out.println(sql.toString());
        return this.executeDML(sql.toString(), params.toArray());
    }
    
    /**
     *    查询数据库返回多条记录 
     * @param sql  sql语句
     * @param clazz 封装javabean类的Class对象
     * @param params sql语句参数
     * @return 查询得到的结果集
     */
    @SuppressWarnings("rawtypes")
    public List queryRows(String sql, final Class clazz, Object[] params) {
        // TODO Auto-generated method stub
        return (List) executeQueryTemplate(sql, params, clazz, new CallBack() {

            @Override
            public Object doExecute(Connection conn, PreparedStatement ps,
                    ResultSet rs) {
                ResultSetMetaData metaDate;
                List list=null;
                try {
                    metaDate = rs.getMetaData();
                    while(rs.next()){
                        if(list==null)
                            list=new ArrayList<>();
                        Object rowObj=clazz.newInstance();
                        for(int i=0;i<metaDate.getColumnCount();i++){
                            String columnName = metaDate.getColumnLabel(i+1);
                            Object columnValue = rs.getObject(i+1);
                            //通过反射调用rowObj的set方法
                            ReflectUtil.invokeSet(rowObj, columnName, columnValue);
                            
                        }
                    list.add(rowObj);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return list;
            }
        });
        
    }
    

    /**
     *    查询数据库返回一条记录 
     * @param sql  sql语句
     * @param clazz 封装javabean类的Class对象
     * @param params sql语句参数
     * @return 查询得到的结果对象
     */
    @SuppressWarnings("rawtypes")
    public Object queryUniqueRows(String sql, Class clazz,
            Object[] params) {
        // TODO Auto-generated method stub
        List list=queryRows(sql, clazz, params);
        return (list==null||list.size()==0)?null:list.get(0);
    }

    /**
     *    查询数据库返回一个值( 一行一列)
     * @param sql  sql语句
     * @param params sql语句参数
     * @return 查询得到的结果对象
     */
    public Object queryValue(String sql, Object[] params) {
        // TODO Auto-generated method stub
        
        return executeQueryTemplate(sql, params, null, new CallBack() {
            
            @Override
            public Object doExecute(Connection conn, PreparedStatement ps,
                    ResultSet rs) {
                Object value = null;
                // TODO Auto-generated method stub
                try {
                    while(rs.next()){
                        value=rs.getObject(1);
                    }
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return value ;
            }
        });
    }
    
    /**
     *    查询数据库返回一个数字
     * @param sql  sql语句
     * @param params sql语句参数
     * @return 查询得到的结果数字
     */
    public Number queryNumber(String sql, Object[] params) {
        // TODO Auto-generated method stub
        return (Number) queryValue(sql, params);
    }
    
    /**
     * 分页查询 
     * @param pageNum 当前页
     * @param pageSize每页显示的记录条数
     * @return
     */
//    public abstract Object queryPagenate(int pageNum,int pageSize);
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }

}
package com.frank.stom.core;

/**
 * 创建query工厂类
 * @author frank
 *
 */
public class QueryFactory {

    private static QueryFactory factory=new QueryFactory();
    private static Query prototypeObj;
    static{
        try {
            Class c=Class.forName(DBManager.getConf().getQueryClass());
            prototypeObj=(Query) c.newInstance();
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    private QueryFactory(){
    }
    
    public static QueryFactory getInstance(){
        return factory;
    }
    
    public Query creatyFactory(){
        try {
            return (Query) prototypeObj.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
        
    }
}
package com.frank.stom.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.Map;

import com.frank.stom.bean.ColumnInfo;
import com.frank.stom.bean.TableInfo;
import com.frank.stom.core.imp.MysqlTypeConvertor;
import com.frank.stom.util.JavaFileUtil;
import com.frank.stom.util.StringUtil;

/**
 * 负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构。
 * @author
 *
 */
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.getConnection();
            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 HashMap<String, ColumnInfo>(), new ArrayList<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(ColumnInfo.PRIMARY_KEY);  //设置为主键类型
                    ti.getPriKeys().add(ci2);
                }
                
                if(ti.getPriKeys().size()>0){  //取唯一主键。。方便使用。如果是联合主键。则为空!
                    ti.setPriKey(ti.getPriKeys().get(0));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //更新类结构
        updateJavaPOFile();
        
        //加载po包下的所有的类
        loadPOTables();
        
    
    }
    /**
     * 根据表结构,更新配置po包下的java类
     */
    public static void updateJavaPOFile(){
        Map<String,TableInfo> map=tables;
        for(TableInfo t:map.values()){
            JavaFileUtil.createJavaPOFile(t, new MysqlTypeConvertor());
        }
    }
    /**
     * 加载po包下的类
     */
    public static void loadPOTables(){
        for(TableInfo tableInfo:tables.values()){
            try {
                Class c = Class.forName(DBManager.getConf().getPoPackage()+
                        "."+StringUtil.firstChar2UpperCase(tableInfo.getTabName()));
                poClassTableMap.put(c, tableInfo);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
    
    public static void main(String[] args) {
         Map<String,TableInfo>  tables = TableContext.tables;
         for(String v: tables.keySet()) {
            System.out.println(v); 
         }
         for(TableInfo f:tables.values()){
            System.out.println(f.getPriKey().getColName()); 
         }
         System.out.println(tables);
    }

}
package com.frank.stom.core;

/**
 *    负责java类型和数据库类型的相互转换  
 * @author frank
 */

public interface TypeConvertor {
    
    /**
     * 将数据库类型转换为java类型 
     * @param columnType 数据库字段类型
     * @return java类型
     */
    public String databaseType2JavaType(String columnType);
    
    /**
     * 将java类型转换为数据库类型 
     * @param javaType java类型
     * @return 数据库类型
     */
    public String javaType2DatabaseType(String  javaType);

}
package com.frank.stom.util;

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.frank.stom.bean.ColumnInfo;
import com.frank.stom.bean.JavaFieldGetSet;
import com.frank.stom.bean.TableInfo;
import com.frank.stom.core.DBManager;
import com.frank.stom.core.TypeConvertor;


/**
 * 封装生成java源文件的常用操作
 * @author frank
 *
 */
public class JavaFileUtil {
    
    /**
     *根据字段信息生成java属性信息 
     * @param colum 字段信息
     * @param convertor 类型转换器
     * @return java属性的set/get方法
     */
    public static JavaFieldGetSet createFieldGetSetSRC(ColumnInfo colum,TypeConvertor convertor){
        JavaFieldGetSet fieldSet = new JavaFieldGetSet();

        String javaFieldType= convertor.databaseType2JavaType(colum.getDataType());

        fieldSet.setFieldInfo("\tprivate "+javaFieldType+" "+colum.getColName()+";\n");

        StringBuffer getSrc=new StringBuffer();
        //public String getUser(){
        //生成get方法源码
        getSrc.append("\tpublic "+javaFieldType+" get"+StringUtil.firstChar2UpperCase(colum.getColName())+"(){\n"   );
        getSrc.append("\t\treturn "+colum.getColName()+";\n");
        getSrc.append("\t}\n");
        fieldSet.setGetInfo(getSrc.toString());
        
        //生成set方法源码
        StringBuffer setSrc= new StringBuffer();
        setSrc.append("\tpublic void set"+StringUtil.firstChar2UpperCase(colum.getColName())+"("   );
        setSrc.append(javaFieldType+" "+colum.getColName()+"){\n");
        setSrc.append("\t\tthis."+colum.getColName()+"="+colum.getColName()+";\n");
        setSrc.append("\t}\n");
        fieldSet.setSetInfo(setSrc.toString());
        return fieldSet;
    }
        

    /**
     * 根据表信息生成java类源码 
     * @param tableInfo 表信息
     * @param convertor 数据类型转换器
     * @return java类源码
     */
    public  static String createJavaSrc(TableInfo tableInfo, TypeConvertor convertor){
        StringBuffer src= new StringBuffer();
        
        Map<String,ColumnInfo> columns=tableInfo.getColumns();
        List<JavaFieldGetSet> javaFields=new ArrayList<JavaFieldGetSet>();
        for(ColumnInfo c:columns.values()){
            javaFields.add(createFieldGetSetSRC(c,convertor));
        }
        //生成package语句
        src.append("package "+DBManager.getConf().getPoPackage()+";\n\n");
        
        //生成import语句
        src.append("import java.sql.*;\n");
        src.append("import java.util.*;\n\n");
        //生成类声明语句
        src.append("public class "+StringUtil.firstChar2UpperCase(tableInfo.getTabName())+" {\n\n");
//        System.out.println("public class "+StringUtil.firstChar2UpperCase(tableInfo.getTabName())+" {\n\n");

        
        //生成属性列表
        for(JavaFieldGetSet f:javaFields){
            src.append(f.getFieldInfo());
        }
        src.append("\n\n");
        
        //生成get方法列表
        for(JavaFieldGetSet f:javaFields){
            src.append(f.getGetInfo());
        }
        
        //生成set方法列表
        for(JavaFieldGetSet f:javaFields){
            src.append(f.getSetInfo());
        }
        
        //生成类结束
        src.append("}\n");
//        System.out.println(src);
        return src.toString();

    }
    /**
     *根据表信息生成java文件 
     * @param table 表信息
     * @param convertor 类型转换器
     */
    public static void createJavaPOFile(TableInfo table,TypeConvertor convertor){
        String src=createJavaSrc(table, convertor);
        
        String srcPath=DBManager.getConf().getSrcPath()+"//";
        String packagePath=DBManager.getConf().getPoPackage().replaceAll("\\.", "/");
        File f=new File(srcPath+packagePath);

        System.out.println(f.getAbsolutePath());
        
        if(!f.exists()){
            f.mkdirs();
        }

        BufferedWriter bw=null;
        try {
            bw=new BufferedWriter(new FileWriter(f.getAbsoluteFile()+"/"+StringUtil.firstChar2UpperCase(table.getTabName())+".java") );
            bw.write(src);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}
package com.frank.stom.util;

import java.sql.PreparedStatement;
import java.sql.SQLException;


/**
 * 封装jdbc常用的操作
 * @author frank
 *
 */
public class JDBCUtil {
    
    /**
     *给preparedStatement传如参数  
     * @param ps PreparedStatement
     * @param params 参数
     */
    public static void handleParams( PreparedStatement ps,Object[] params){

        if(params!=null){
            for(int i=0;i<params.length;i++){
                try {
                    ps.setObject(i+1,params[i]);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
package com.frank.stom.util;

import java.lang.reflect.Method;

/**
 * 封装反射的常用操作
 * @author frank
 *
 */
public class ReflectUtil {
    
    /**
     * 调用obj对象对应属性的get方法
     * @param c
     * @param fieldName
     * @param obj
     * @return
     */
    public static Object invokeGet(String fieldName, Object obj){
        //通过反射机制,调用属性的get方法
                try {
                    Class c=obj.getClass();
                    Method m=c.getDeclaredMethod("get"+StringUtil.firstChar2UpperCase(fieldName), null);
                     return m.invoke(obj, null);
                } catch (Exception  e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
    }
    
    /**
     * 调用obj对象对应属性的set方法
     * @param c
     * @param fieldName
     * @param obj
     */
    public static void  invokeSet( Object obj ,String fieldName,Object fieldValue){
        //通过反射机制,调用属性的set方法
                try {
                    Class c=obj.getClass();
                    Method m=c.getDeclaredMethod("set"+StringUtil.firstChar2UpperCase(fieldName), fieldValue.getClass());
                    m.invoke(obj, fieldValue);
                } catch (Exception  e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    }

}
package com.frank.stom.util;

/**
 * 封装String 类型的常用操作
 * @author frank
 *
 */
public class StringUtil {
    
    /**
     * 将目标字符串首字母变为大写
     * @param str 目标字符串
     * @return 首字母大写的字符串
     */
    public static String firstChar2UpperCase(String str){
        
        return str.toUpperCase().substring(0,1)+str.substring(1);
        
    }

}
package com.frank.stom.test;

import java.util.List;

import com.frank.po.Student;
import com.frank.stom.core.Query;
import com.frank.stom.core.QueryFactory;

public class TestMain {

    public static void main(String[] args) {
        String sql = "SELECT * FROM student WHERE id = ?";
        
        Student stu1  = new Student(); //这一new 产生一个Student对象,一个Class对象
        Class clazz = stu1.getClass();
        
        Object[] params = new Object[1];
        params[0] = "1";
        
        QueryFactory aueryFactory = QueryFactory.getInstance();
        Query query = aueryFactory.creatyFactory();
        Object obj = query.queryUniqueRows(sql, clazz, params);
        System.out.println(obj);
        
        System.out.println();
        
        sql = "SELECT * FROM student";
        params = null;
        List<Student> list = query.queryRows(sql, clazz, params);
        for(Student student : list) {
            System.out.println(student);
        }
    }

}

对于数据库表的实体类 po包下面的类 是自动生成的,运行TableContext里面的main()方法,提前生成好实体类,可以根据需要添加实体类的toStirng(),hashCode()等方法。

生成完实体类之后,运行TestMain()进行一些查询,结果为:

 

 

转自:https://www.cnblogs.com/frankM/p/4590338.html

 

posted @ 2019-05-09 16:12  myseries  阅读(445)  评论(0编辑  收藏  举报