Vul een DefaultMutableTreeNode uit vanuit de database

Ik ben vrij nieuw voor Java en ik wil een klasse DefaultMutableTreeNode maken die Map-objecten bevat.

Ik heb een TreeNodeMap-klasse geschreven die erft van een meer generieke TreeNode-klasse die op zijn beurt wordt overgenomen van DefaultMutableTreeNode.

De klasse TreeNodeMap bevat de methode vullen waarvoor een vrij lange lijst met parameters nodig is. Ik ben van plan de leesbaarheid van de methoden te verbeteren door een aantal van deze parameters in een enkel object om te zetten en de methode te overbelasten, zodat ik in de eerste call geen reeks null's hoef te passeren (is recursief).

Note:If you don't care for my verbose explanation of the method skip directly to the code from here

In eerste instantie maak ik een leeg knooppunt dat alleen kinderen bevat maar geen gegevens, dit is WORTEL. Het idee is om een ​​methode te hebben waarmee de beller elke query kan doorgeven met de kolommen 'field_id', 'field_label' en 'parent_id'. Bij het eerste gesprek wordt de query doorgegeven met een Where-component waarbij de 'parent_id is null' en dus alle knooppunten zonder bovenliggend element krijgt. Al deze knooppunten worden toegevoegd aan het ROOT-knooppunt. Terwijl iterating over de Resultset de methode vullen voor elk knooppunt wordt aangeroepen, wordt nu een 'Where-component' doorgegeven waarbij parent_id = [huidig ​​knooppunt-id] vandaar alle kinderen voor dat knooppunt krijgt. Dit gebeurt recursief totdat alle knooppunten met een hiërarchie zijn gemaakt.

code (Remember, I'm new to JAVA so any feedback is appreciated)

public void populate( boolean isRoot, String parentFieldId, String parentFieldLabel, String childFieldId, String childFieldLabel, 
            int parentId, String tableName, String whereClause, String orderByClause, String additionalColumns, List> 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 childNodeData = new HashMap(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) {  }
        }
    }   

De eerste aanroep van de methode ziet er ongeveer zo uit:

treeNode.populate(true, "supervisor_id", "supervisor", "employee_id", "employee", 0, "vw_employee", null, null, null, queryParams);

Het probleem dat ik zie met deze benadering is dat de DB X keer wordt bevraagd en met een grote gegevensset zou ik denken dat dit enkele problemen zal veroorzaken. Ik open ook een verbinding voor elke vraag! Dus ik dacht erover om de Connection aan de methode door te geven nadat deze was gemaakt (in de recursieve aanroepen), maar dan weet ik niet zeker hoe ik deze op de juiste manier moet sluiten. Ik zou een voorwaardelijke kunnen schrijven om te controleren of het knooppunt de WORTEL is, sluit dan de verbinding maar dan wat er gebeurt als de code tussentijds faalt.

Dus eindelijk mijn vragen: 1- Wat is de beste manier om dit te benaderen? 2- Moet ik de verbinding rond doorgeven zodat er slechts één verbinding open blijft tijdens de populatie van de boom? Zo ja, hoe sluit ik dit dan goed af? 3- Moet ik de Resultset opslaan in een ArrayList en dat in plaats daarvan gebruiken?

1

1 antwoord

Uw prestatie betreft mogelijk een garantie. In plaats daarvan,

  1. Implement TreeModel, as shown in this FileTreeModel. In this way, only visible nodes need be queried. There's a related example here.

  2. Pass javax.sql.DataSource, rather than Connection.

  3. Your class that implements TreeModel can encapsulate any cached data, but also provide some means to update stale entries. After displaying cached values, consider using SwingWorker to refresh the model, as shown here. Instead of List, you might want to look at Map.

3
toegevoegd
Hartelijk dank voor uw advies @trashgod. Er zijn verschillende dingen om te verteren hier en ik ben al aan het kijken naar uw suggesties. Ik was niet op de hoogte van de javax.sql.Datasource, lijkt hetzelfde te doen wat ik deed met mijn DBConnection-klasse en het is niet nodig om het wiel opnieuw uit te vinden, dus hoogstwaarschijnlijk zal ik dat gebruiken. Ik zal verder lezen en contact met u opnemen zodra ik al uw suggesties begrijp. Nogmaals bedankt!
toegevoegd de auteur Lostlinkpr, de bron