日期:2014-05-16  浏览次数:20385 次

使用有限多例模式管理数据库结构信息

多例模式是一个类可以有多个实例的模式,它是单例模式的自然推广。它的特点是:

   1、该类可以有多个实例;

   2、由类本身创建管理它的实例;

   3、由类本身向外界提供它的实例。

JadePool使用有限多例模式管理数据库结构信息

在JadePool开源工具中,具体的说就是由DbCenter负责管理事务型数据库的数据库结构信息,由DbAccess负责管理非事务型数据库的数据库结构信息,它们共同遵守Db规划的方法。它们管理各自的Table、Field对象。本篇将以DbCenter为例,简要介绍数据库结构信息管理的实现过程。

为什么选择有限多例模式管理数据库结构信息?

这可能是最合理的选择,数据库结构信息作为整个软件系统中的共享资源,可能需要大量使用,因此这种资源应当驻留在内存中。DbCenter目前提供了四个实例,每个实例负责管理一个数据库的结构信息,软件系统在理论上可以同时最多管理四个数据库,通常情况下用户只需要一个实例,如果需要实现两个不同数据库的交互操作,用户可以实例化两个实例。使用有限多例模式保证了用户对几个不同数据库同时操作。

DbCenter做了哪些工作?

   1、根据用户请求如:ProcessVO构造方法的请求,创建对应的DbCenter实例,并初始化该实例,并将该实例提交给用户;

   2、实例化的类的属性,包括:数据库驱动器名称、数据库框架名称、数据库名称、数据库表的名称的集合。

   3、为数据库的每一个表创建Table对象;

   4、为每个表的字段创建Field对象。

通过以上四步工作,把整个数据库的结构信息完整地提取出来,供应用程序下一步调用。


以下是部分源代码,详细的原代码,可以下载JadePool-1.0-GBK的资源文件获取。

    synchronized private void init(Connection _con) {
        this.con = _con;
        try {
            //schema=con.getSchema();
            catalog = con.getCatalog();//数据库名
            dm = con.getMetaData();
            driverName = dm.getDriverName();
            Set<String> tableNameSet = new java.util.LinkedHashSet();//表名集合
            String[] types = {"TABLE"};

            ResultSet rs = dm.getTables(null, null, null, types);//获取数据库中所有表的名称
            while (rs.next()) {
                String tableName = rs.getString("TABLE_NAME");
                tableNameSet.add(tableName);
            }
            Object[] o = tableNameSet.toArray();
            tableNames_tmp = new String[o.length];
            tableNames = new String[o.length];
            for (int i = 0; i < o.length; i++) {
                tableNames_tmp[i] = (String) o[i].toString();
                tableNames[i] = (String) o[i].toString().toLowerCase();
            }

            if (tableNames_tmp != null) {
                for (int i = 0; i < tableNames_tmp.length; i++) {
                    initTableMap(tableNames_tmp[i]);//大写
                }
            }

            instance_times++;

        } catch (SQLException ex) {
            Logger.getLogger(DbCenter.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        } finally {
            //con.close();共享con,不能关闭,由调用 Db实例.getCon()的用户关闭
        }

    }

    /**
     * 应当在此,还要初始化字段Field及各表的键值信息 注意事项: 使用ResultSet rs = dm.getColumns(catalog,
     * null, tableName, null);/使用derby数据库时,大小写是敏感的, 因此
     *
     * @param tableName的值,只能通过dm原型获取的值,这样造成了大小写问题,在运算过程中,不能转换大小写,只能在最后统一转换成小写,
     */
    synchronized private void initTableMap(String tableName) throws SQLException {
        Table table = getTable(tableName.toLowerCase());
        if (table == null) {
            table = new Table();
        }
        table.setName(tableName.toLowerCase());
        Set fieldSet = new java.util.LinkedHashSet();
        Set keySet = new java.util.LinkedHashSet();
        if (con != null) {
            ResultSet rs = dm.getColumns(catalog, null, tableName, null);//获取表中所有字段 //参考ResultSet rs = dm.getProcedureColumns(catalog, catalog, driverName, tableName);//?
            Map<String, Field> field_map = new LinkedHashMap();
            while (rs.next()) {
                String name = rs.getString("COLUMN_NAME");//参数值可参考dm.getColumns(catalog, null, tableName,