2011-03-10 88 views
0

我有一個動態的查詢字符串。我在數據庫中搜索的項目是基於用戶在html表單上的複選框中選擇的內容。用戶類型從下拉列表中選擇城市名稱。然後,用戶可以從城市的3個不同屬性中選擇:CountryCode(int),District(String)和Population(int)。Java - 解析從數據庫返回的數據時的問題

我沒有問題創建查詢。例如,如果用戶選擇塔爾薩並選擇區和人口,queryString SELECT District, Population FROM City WHERE name ='Tulsa'創建沒有問題。又如,如果用戶簡單地選擇了塔爾薩的國家代碼,則創建的查詢字符串將是SELECT CountryCode FROM City WHERE name ='Tulsa'

問題是解析數據並將其整齊地顯示在屏幕上。我不是數據庫程序員,所以我有一段艱難的時光。這是我的代碼的珍聞,所以你可以看到我在做什麼。

我可以正確做的唯一事情是如果用戶選擇區和人口。其他選擇不起作用。我基本上是硬編碼區和人口。我不知道如何動態解析它。這是代碼。查詢字符串是SELECT District, Population FROM City WHERE name ='Tulsa'。它是我唯一可以工作的人。

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); 
    } 

我希望你們明白我在問什麼。非常感謝您的幫助!

+0

老實說,這種方法有太多的錯誤,我強烈建議修改整個方法。這對SQL注入攻擊,連接超時,資源泄漏以及數據庫和用戶界面邏輯的緊密耦合非常敏感。 – BalusC 2011-03-10 19:25:04

+0

@BalusC - 雖然我同意...嬰兒的步驟。每個人都必須從某個地方開始。 – 2011-03-10 19:32:17

+0

謝謝......這是爲了我自己的小項目。試圖自學一些數據庫編程。這不會被髮送到真實的世界或任何東西。只是爲了我自己的快樂。謝謝!我也有工作:-) – Johnrad 2011-03-10 19:33:19

回答

3

如果您只想輸出數據,那麼您可以使用ResultSet.getString(index)將所有內容都設爲String,因爲您知道元數據中的列數。

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

怎麼我沒有看到這個答案已經發布? :/ – 2011-03-10 19:30:16

0

SELECT CountryCode FROM City WHERE name ='Tulsa' 

你在ResultSet中只有一列,但後來在你的代碼中得到的列數據和索引的情況下2

rs.getInt(2) 

您的主要問題有許多解決方案,從Spring JdbcTemplate開始,到像休眠一樣的ORM ...

+0

不錯,但我認爲爲此學習一些框架有點沉重,不是嗎?至於格式化表,應該很難。 – 2011-03-10 19:21:27

1

數據庫編程可能使用改進更現代化。

數據庫編程的典型設計是至少有一組實體類。實體類所做的是代表數據庫中的表。所以你會爲表中的每一列創建適當數據類型的私有字段。您可以充實自己想要的方式,但它可以基於數據庫設計爲應用程序提供結構。

然後,您可以寫一個基本的數據庫功能

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; 
} 

的典型,你會放置等基本功能,如createCity(市城市)deleteCity(市城市)updateCity(市市)全部變成一個類,這將是你的數據訪問對象或DAO,所以這可能是你的CityDAO。

然後在你展示的類文件中,你可以簡單地調用getCity函數並找出你需要從City對象獲取哪些字段。您也將對City對象的字段進行強類型檢查,這對HTML格式應該很好。

0
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>"); 
    } 
} 
0

要添加一些新的東西到現有的答案,這裏是我如何寫它的代碼。一些注意事項:

  • 第一種方法(getDataInternal)只涉及SQL查詢,而沒有進行錯誤處理。但萬一出現錯誤,ResultSet已被正確清理。
  • 第二種方法(getData)包裹了所有內容,提供了簡單的錯誤處理。
  • 無論是否發生異常,每種方法都會釋放其獲取的資源。

通過這種分離,代碼變得更容易閱讀和維護。

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(); 
    } 
}