简体   繁体   中英

Java - Trouble Parsing Data Returned From Database

I have a query string that is dynamic. The items I am searching for in the database are based upon what the user selects in a checkbox on an html form. The user types selects a city name from a drop down list. Then the user can select from 3 different attributes to the city: CountryCode(int), District(String), and Population(int).

I have no problem creating the query. For example if the user selects Tulsa and selects District and Population the queryString SELECT District, Population FROM City WHERE name ='Tulsa' is created no problem. For another example if the user simply selected country code of Tulsa the query string created would be SELECT CountryCode FROM City WHERE name ='Tulsa' .

The problem is parsing the data and displaying it neatly to the screen. I am no database programmer so I am having a tough time. Here is a tidbit of my code so you can see what I'm doing.

The only thing I can do correctly is if the user selects District and Population. Any other selection doesn't work. I am basically hard coding District and Population. I am not sure how to parse it dynamically. Here is the code. Query string is SELECT District, Population FROM City WHERE name ='Tulsa' . Its the only one I can get to work.

public String getData( String c)
    {

        String query = c;
        ResultSet rs = null;
                StringBuffer back = new StringBuffer();

        try
        {
            rs = st.executeQuery(c);
            ResultSetMetaData rsmd = rs.getMetaData();

            int numColumns = rsmd.getColumnCount();
            back.append( "number of columns is " + numColumns);
                        back.append( "</br>");

            back.append( "<table border=\"10\" >\n" );
                        while(rs.next())
                        {
                            if(rsmd.getColumnTypeName(1).equals("CHAR"))
                                back.append("<tr><td>" + rsmd.getColumnName(1) + "</td>" + "<td>" + rs.getString(1) + "</trd</tr>");

                            if(rsmd.getColumnTypeName(2).equals("INT"))
                                back.append("<tr><td>" + rsmd.getColumnName(2) + "</td>" + "<td>" + Integer.toString(rs.getInt(2)) + "</td></tr>");

            }
            back.append( "</table>" );
        }
        catch( SQLException e )
        {
            back.append( "<h6>something bad is happening</h6>");
            e.printStackTrace();
            return null;
        }
        return new String( back );
    }

I hope you guys understand what I'm asking. Thanks alot for the help!

If all you want to do is output the data, you can just get everything as a String using ResultSet.getString(index) since you know the number of columns from your metadata.

while(rs.next())
{
    for (int i = 1; i <= numColumns; i++)
    {
        back.append("<tr><td>" + rsmd.getColumnName(i) +
                    "</td>" + "<td>" + rs.getString(i) + "</trd</tr>");
    }
}

The database programming could use improvement to be more modernized.

A typical design for database programming would be to at the least have a set of Entity classes. What an entity class does is represent a table in a database. So you would create private fields of the proper data type for each column in the table. You can flesh it out how you want, but it gives structure to your application based around your database design.

You can then write a basic database function

public City getCity(Object primaryKey){

     ... <run select query on the primary key and get result set> ...

     Entity ent = new Entity();
     ent.setDistrict( rs.getString( 0 ) );
     ent.setPopulation ( rs.getInt( 1 ) );
     ...

     return ent;
 }

Typical you would place other basic functions like createCity(City city) deleteCity(City city) updateCity(City city) all into a single class that would be you Data Access Object or DAO, so this could be your CityDAO.

Then in the class file you showed, you could simply call the getCity function and figure out which fields you need to grab from the City object. You will have strong type checking on the fields of the City object too which should be nice for HTML formatting.

In case of

SELECT CountryCode FROM City WHERE name ='Tulsa'

you have only one column in ResultSet, but later in your code you get data from column with index 2

rs.getInt(2)

your primary problem has many solutions, starting from Spring JdbcTemplate to ORM like Hibernate...

while(rs.next())  { 
  int numColumns = rs.getMetadata().getColumnCount();
  for (int i = 0; i < numColumns; ++i) {
    back.append("<tr><td>" + rsmd.getColumnName(i) + "</td>" + "<td>" + rs.getString(i) + "</td></tr>");
  }
} 

To add something new to the existing answers, here is the code how I would write it. Some notes:

  • The first method ( getDataInternal ) is only concerned with the SQL query, not with the error handling. But just in case there is an error, the ResultSet is properly cleaned up.
  • The second method ( getData ) is wrapped around everything, providing simple error handling.
  • Every method releases the resources it aquires, no matter if an exception occurs or not.

With this separation, the code becomes easier to read and maintain.

package so5264507;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.lang.StringEscapeUtils;

public class DatabaseDemo {

  public String getDataInternal(Statement st, String c) throws SQLException {
    ResultSet rs = st.executeQuery(c);
    try {
      ResultSetMetaData meta = rs.getMetaData();
      StringBuilder sb = new StringBuilder();
      while (rs.next()) {
        sb.append("<table border=\"10\">\n");
        for (int i = 1; i < meta.getColumnCount() + 1; i++) {
          sb.append("<tr>");
          sb.append("<td>" + StringEscapeUtils.escapeHtml(meta.getColumnName(i)) + "</td>");
          sb.append("<td>" + StringEscapeUtils.escapeHtml(rs.getString(i)) + "</td>");
          sb.append("</tr>\n");
        }
        sb.append("</table>\n\n");
      }
      return sb.toString();
    } finally {
      rs.close();
    }
  }

  public String getDataAsHtml(Statement st, String c) {
    try {
      return getDataInternal(st, c);
    } catch (SQLException e) {
      e.printStackTrace();
      return "<h6>Something bad happened.</h6>";
    }
  }

  public void run() throws SQLException {
    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/sodemo", "sodemo", "sodemo");
    try {
      Statement st = conn.createStatement();
      try {
        String html = getDataAsHtml(st, "SELECT District, Population FROM City");
        System.out.println(html);
      } finally {
        st.close();
      }
    } finally {
      conn.close();
    }
  }


  public static void main(String[] args) throws SQLException {
    new DatabaseDemo().run();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM