2012-04-24 72 views
0

我很難從多個表中檢索數據。它將成爲一個搜索表單及其關係數據庫。如何從Java Servlet中的多個表(PostgreSQL)中檢索數據?

問題1:如何從多個表中檢索數據?

問題2:同時我面臨的另一個問題是,我不能得到任何結果,如果我嘗試只能通過名稱或姓氏進行搜索。只有當我使用出生日期時纔會得到結果。爲什麼?

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

     java.io.PrintWriter out = response.getWriter(); 
     Connection conn = null;{ // while there is no connections, proceed to the next step 
     try { 
      Class.forName("org.postgresql.Driver"); // importing the driver to use the getConnection method 
      conn = DriverManager.getConnection(
        "jdbc:postgresql://localhost:5432/caglar", "postgres", //?searchpath=cag 
        "abracadabra"); 
      System.out.println("Connected to the database"); // console message 
      String agent_name = request.getParameter("givenname"); // variable - reads from user input 
      String agent_lastname = request.getParameter("familyname"); // variable - reads from user input 
      String dob = request.getParameter("birthyear"); // variable - reads from user input 

      ArrayList al=null; 
      ArrayList agent_list =new ArrayList(); 

      //Problem 1: If dob is not given, it is not searching by name or lastname. 

      //String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' or birthyear='"+dob+"' order by givenname"; 

      String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' "; 
      if(dob!=null && !"".equals(dob)) // if date of birth fiel is left blank, it will still proceed to the results page 
       query = query + " or birthyear='"+dob+"'"; // if date of birth exists, it will take it into account as well 

      query = query+ "order by givenname"; // ordering by first name 


      System.out.println("query" + query); // console message 
      Statement st = conn.createStatement(); // connection statement 
      ResultSet rs = st.executeQuery(query); // executing our query 


      while(rs.next()) 
      { 
       al = new ArrayList(); 

       al.add(rs.getString(1));//id 
       al.add(rs.getString(2));//dob 
       al.add(rs.getString(3));//name 
       al.add(rs.getString(4));//lastname 
       System.out.println("al :: "+al); 
       agent_list.add(al); 
      } 

      request.setAttribute("agentList",agent_list); 
+2

哇,這段代碼極易受SQL注入攻擊。想象一下,如果某人提交給定名稱(不含雙引號)「myname」; DROP TABLE agent; - 「會發生什麼情況。您至少需要使用參數化查詢。 – 2012-04-24 03:11:36

+0

雖然不是直接的答案,但我強烈建議您查看(a)Facelets/JSF2和(b)JPA2。無論如何,請顯示您正在從工作和非工作測試用例生成的查詢文本。 – 2012-04-24 03:14:13

+0

據推測,如果DoB沒有被給出,它不會匹配任何東西。這意味着您的給定名稱/姓氏WHERE子句總是評估爲false。沒有數據,爲什麼很難說。這可能是大小寫敏感,引用或各種各樣的事情。 – 2012-04-24 03:17:09

回答

2

爲了重申別人在上面指出的內容,這是「危險的」代碼。通過不使用PreparedStatements,您可以自己開始使用SQL注入攻擊 - 通過這種攻擊,惡意用戶可以製作SQL語句以刪除表中的所有數據。正如@ craig-ringer所指出的那樣,提交數據將會從數據庫中刪除表。

已經指出了這一點,強調了幾次,在熒光黃色標記突出它,讓我們繼續前進,並嘗試回答您的問題:

1)您可以通過使用SQL連接查詢從多個表中的數據。 Here's a PostgreSQL tutorial on JOINS - 那裏還有很多其他的東西,我只是挑選了我發現的第一個。

2)如果沒有數據庫中的確切數據以及提供的確切參數,很難回答 - 但是,我認爲問題是區分大小寫。 PostgreSQL中的比較區分大小寫 - 所以如果數據庫中的姓氏是'Smith'並且參數是'smith',則不會找到任何數據。因此,爲了簡單起見,您需要將參數和數據轉換爲相同的情況,例如降低。例如SELECT * FROM agent where LOWER(familyname)='smith'

我還想指出,您可能遇到日期格式化問題 - 這也將通過使用預處理語句解決。

看來你對java,SQL和JDBC來說是相當新的東西;我建議你嘗試一些教程並閱讀一些書。有很多事情需要處理 - 祝你好運!

+0

請注意,連接並不總是從多個表中檢索數據集的最佳方法。除非它們都是純粹的1:1關係,否則您通常不得不去除重複的內容。我經常喜歡從一個表中取出,然後從另一個SELECT中的另一個表中取出。它是否比加入速度快很多,取決於往返時間與帶寬與CPU成本等因素,但它肯定會更好地閱讀,並且在DB上更容易。看起來PostgreSQL將能夠很快返回結構化的JSON或YAML查詢結果:-) – 2012-04-24 13:30:53

+0

你怎麼做兩次Craig? – krest 2012-04-25 16:55:09