首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从数据库中填充DefaultMutableTreeNode

从数据库中填充DefaultMutableTreeNode
EN

Stack Overflow用户
提问于 2012-06-24 05:40:38
回答 1查看 1.3K关注 0票数 2

我对Java相当陌生,我希望创建一个包含Map的DefaultMutableTreeNode类。

我编写了一个TreeNodeMap类,该类继承自一个更通用的TreeNode类,而后者又继承自DefaultMutableTreeNode。

TreeNodeMap类包含接受相当长的参数列表的方法填充。我计划通过将其中一些参数转换为单个对象并重载该方法来提高方法的可读性,这样我就不必在第一个调用中传递一组空值(是递归的)。

注意:如果您不关心我对该方法的详细解释,请从这里直接跳到代码

最初,我创建一个只包含子节点而不包含数据的空节点,这是根节点。这个方法允许调用者传递包含“field_id”、“field_label”、“parent_id”列的任何查询。在最初的调用中,查询通过Where子句传递,其中'parent_id为null‘,从而获得没有父节点的所有节点。所有这些节点都添加到根节点。在迭代Resultset时,每个节点的填充方法被称为现在传递一个'Where子句‘,其中parent_id =当前节点id,从而获得该节点的所有子节点。这将递归发生,直到使用层次结构创建所有节点为止。

代码(请记住,我是JAVA新手,所以很感谢您的反馈)

代码语言:javascript
复制
public void populate( boolean isRoot, String parentFieldId, String parentFieldLabel, String childFieldId, String childFieldLabel, 
            int parentId, String tableName, String whereClause, String orderByClause, String additionalColumns, List<Map<String, String>> queryParams) throws SQLException, Exception{
        ResultSet rs = null;
        Connection con = null;
        PreparedStatement ps = null;
        try{

            DBConnection dbConnection = new DBConnection("localhost", 3306, "root", "password", "test", DBDrivers.DBTYPE_MYSQL);
            con = dbConnection.getConnection();

            String treeNodeSql = "Select " + parentFieldId + ", " + parentFieldLabel + 
                                                ", " + childFieldId + ", " + childFieldLabel;
            if(additionalColumns != null && additionalColumns.trim().length() > 0)
                treeNodeSql +=  " ," + additionalColumns;

            treeNodeSql += " From " + tableName + " WHERE 1=1";

            if(whereClause != null && whereClause.trim().length() > 0 ){
                treeNodeSql += " AND " + whereClause;
            }

            if(isRoot){
                treeNodeSql += " AND " + parentFieldId + " is null";
            }else{
                if(parentFieldId == null || parentFieldId.trim().length() == 0)
                    throw new Exception(" The populate() method requires a parentId when isRoot is false.");
                treeNodeSql += " AND " + parentFieldId + " = ?";
            }
                //order clause append
            if(orderByClause != null && orderByClause.trim().length() > 0)
                treeNodeSql += " " + orderByClause;

                //prepare statement
             ps = con.prepareStatement(treeNodeSql); 
            int ixParam = 0;

                for(Map qParam : queryParams){
                    if(qParam.get("datatype") == "int"){
                        ps.setInt(++ixParam, Integer.parseInt((String) qParam.get("value")));
                    }else if(qParam.get("datatype") == "string"){
                        ps.setString(++ixParam, (String) qParam.get("value"));
                    }
                }

            out.println(treeNodeSql);
            if(parentId > 0){
                ps.setInt(queryParams.size()+1, parentId);
            }
            rs = ps.executeQuery();

            while(rs.next()){
                HashMap<String, Object> childNodeData = new HashMap<String, Object>(4);
                childNodeData.put("parentFieldId", parentFieldId);
                childNodeData.put("parentFieldIdValue", Integer.toString(rs.getInt(parentFieldId)));
                childNodeData.put("parentFieldLabel", parentFieldLabel);
                childNodeData.put("parentFieldLabelValue", rs.getString(parentFieldLabel));
                childNodeData.put("childFieldId", childFieldId);
                childNodeData.put("childFieldIdValue", Integer.toString(rs.getInt(childFieldId)));
                childNodeData.put("childFieldLabel", childFieldLabel);
                childNodeData.put("childFieldLabelValue", rs.getString(childFieldLabel));

                out.println("parentId: " + rs.getInt(parentFieldId)
                                + ", parentLabel: " + rs.getString(parentFieldLabel)
                                + ", childId: " + rs.getInt(childFieldId)
                                + ", childLabel: " + rs.getString(childFieldLabel));
                TreeNodeMap childNode = new TreeNodeMap(childNodeData);
                this.add(childNode);
                childNode.populate(false, parentFieldId, parentFieldLabel, childFieldId, childFieldLabel, rs.getInt(childFieldId), tableName, whereClause, orderByClause, additionalColumns, queryParams);
            }
        }catch(SQLException e){
            throw e;

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            out.println(e.getCause());
            out.println(e.getMessage());
            e.printStackTrace();
            throw e;
        }finally {
            try { rs.close(); } catch (Exception e) {  }
            try { ps.close(); } catch (Exception e) {  }
            try { con.close(); } catch (Exception e) {  }
        }
    }   

对该方法的初始调用如下所示:

代码语言:javascript
复制
treeNode.populate(true, "supervisor_id", "supervisor", "employee_id", "employee", 0, "vw_employee", null, null, null, queryParams);

我在这种方法中看到的问题是,数据库将被查询X次,而对于一个大数据集,我认为这会导致一些问题。我还为每个查询打开一个连接!因此,我考虑在方法创建后(在递归调用中)将连接传递给它,但是我不知道如何适当地关闭它。我可以编写一个条件来检查节点是否是根节点,然后关闭连接,但是如果代码在两者之间失败会发生什么。

最后,我的问题是: 1-什么是处理这个问题的最佳方法? 2-我应该把连接传递给周围,这样在树的种群中只有一个连接保持开放吗?如果是,那我该如何正确地关闭它。3-我应该将结果集缓存到一个ArrayList中并使用它吗?

EN

回答 1

Stack Overflow用户

发布于 2012-06-24 16:29:58

你的表现问题可能是有理由的。相反,

  1. 实现TreeModel,如本FileTreeModel所示。这样,只需要查询可见的节点。有一个相关的例子,这里
  2. 传递javax.sql.DataSource,而不是Connection
  3. 您的类implements TreeModel可以封装任何缓存的数据,但也提供了一些方法来更新陈旧的条目。显示缓存值之后,考虑使用SwingWorker刷新模型,如这里所示。与List<Record>不同,您可能需要查看Map<PrimaryKey, Record>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11175233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档