5
\$\begingroup\$

This is my table model code style:

public class MyModel extends DefaultTableModel {

static Vector data = new Vector();
static Vector column = new Vector();
Connection conn;
Statement statement;
ResultSet result;

public MyModel() {
super(data, column);
try {
    conn = DriverManager.getConnection(...);
    statement = conn.createStatement();
    result = statement.executeQuery("Select * from table");

    int col = result.getMetaData().getColumnCount();
    for (int i = 1; i <= col; i++) {
        column.add(result.getMetaData().getColumnName(i));
    }

    while (result.next()) {
        Vector newRow = new Vector(col);
        for (int i = 1; i <= col; i++) {
            newRow.add(result.getString(i));
        }
        data.add(newRow);
    }

} catch (SQLException e) {
    e.printStackTrace();
} 
}
// create methods for remove and add and edit a JTable selected row

}

//My GUI class that show jtable on own

Is this best way?

What is this way problems?

Any idea to be better?

\$\endgroup\$
5
\$\begingroup\$

This way your software is highly coupled. I can see three big responsibilities in it:

  • Get data from db
  • Format data in "TableModel way"
  • Create TableModel

Let's create a class to get data. I don't like the idea of let other classes deal with objects from jdbc api, so this class will format data too:

public class TableData {

    public TableContent getData() {
        Vector<String> headers = new Vector<String>();
        Vector<Vector<String>> content = new Vector<Vector<String>>();

        try {
            Connection conn = DriverManager.getConnection("");
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("Select * from table");

            headers = buildHeaders(rs);
            content = buildContent(rs);

        } catch (SQLException e) {
            e.printStackTrace();
        }

        return new TableContent(headers, content);
    }

    private Vector<String> buildHeaders(final ResultSet rs) throws SQLException {
        Vector<String> headers = new Vector<String>();

        int col = rs.getMetaData().getColumnCount();
        for (int i = 1; i <= col; i++) {
            headers.add(rs.getMetaData().getColumnName(i));
        }
        return headers;
    }

    private Vector<Vector<String>> buildContent(final ResultSet rs) throws SQLException {
        Vector<Vector<String>> content = new Vector<Vector<String>>();

        while (rs.next()) {
            int col = rs.getMetaData().getColumnCount();
            Vector<String> newRow = new Vector<String>(col);

            for (int i = 1; i <= col; i++) {
                newRow.add(rs.getString(i));
            }
            content.add(newRow);
        }
        return content;
    }
}

I've created TableContent just to wrap the result:

public class TableContent {

    private final Vector<String> headers;
    private final Vector<Vector<String>> content;

    public TableContent(final Vector<String> headers, final Vector<Vector<String>> content) {
        this.headers = headers;
        this.content = content;
    }

    public Vector<String> headers() {
        return headers;
    }

    public Vector<Vector<String>> content() {
        return content;
    }
}

Now, the TableModel. That way you don't need to extend the class DefaultTableModel, you can simply instantiate one:

TableContent data = new TableData().getData();
new DefaultTableModel(data.headers(), data.content());

The class TableData still has a problem, the ideal would be to receive the Connection by the constructor, because without it, it's not possible to test the class with unit tests. I didn't wanna make the solution more difficult.

\$\endgroup\$
  • \$\begingroup\$ Thanks Juliano , Great help, I am testing your solution... \$\endgroup\$ – Sajad Aug 28 '13 at 15:34
  • 2
    \$\begingroup\$ Rather than "getting" the data from the TableData class, consider create methods: DefaultTableModel dtm = new TableData().createTableContent().createTableModel(). No accessors necessary, in keeping with the concepts of information hiding and encapsulation. \$\endgroup\$ – Dave Jarvis Aug 28 '13 at 17:40
  • \$\begingroup\$ @DaveJarvis Nice, I want to add my optional methods (like add, remove, edit) to my model. before i added them to my extended from DefaultTableModel Class, Now how can i define this methods and where should do it? \$\endgroup\$ – Sajad Sep 2 '13 at 20:31
  • \$\begingroup\$ @APoliteBoy: I recommend asking another question, rather than asking a question in comments. You'll get more people reading it. :-) \$\endgroup\$ – Dave Jarvis Sep 3 '13 at 1:34
  • \$\begingroup\$ @DaveJarvis Ok.. \$\endgroup\$ – Sajad Sep 3 '13 at 20:25
3
\$\begingroup\$
  1. I'd use a simple List or ArrayList here. Vector is considered obsolete.

    (Make sure that accessing is properly synchronized if they're used by multiple threads.)

  2. printStackTrace() only catch clauses just postpone the errors and usually makes debugging harder. Clients of these class might use these values (or the empty collections) as valid data. You should handle the exception or throw another one with a helpful message. (The Pragmatic Programmer: From Journeyman to Master by Andrew Hunt and David Thomas: Dead Programs Tell No Lies.)

  3. Scope of these variables could be smaller:

    Connection conn;
    Statement statement;
    ResultSet result;
    

    You could declare them inside the constructor. (Effective Java, Second Edition, Item 45: Minimize the scope of local variables)

  4. I think creating a local variable for ResultSetMetaData would be a little bit more readable:

    ResultSetMetaData metaData = result.getMetaData();
    int col = metaData.getColumnCount();
    for (int i = 1; i <= col; i++) {
        column.add(metaData.getColumnName(i));
    }
    
  5. Don't forget to close your Connection, Statement and ResultSet. See Guideline 1-2: Release resources in all cases in Secure Coding Guidelines for the Java Programming Language

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.