2

Possible Duplicate:
PreparedStatement IN clause alternatives?

I want to select from MYSQL based on checkbox selection. (Checkbox has ID's, and the select from database should select where ID= ? -> the IDs which are selected)

I organize it with MVC architecture:

  • in jsp is my form (which is dynamic, so there can be more)

      <input type="checkbox" name="checkboxes" value="1">XY
      <input type="checkbox" name="checkboxes" value="2">XY
      <input type="checkbox" name="checkboxes" value="3">XY
    
  • in servlet I get the values

      String[] catids  = request.getParameterValues("checkboxes");
    
      //Forward to bean -> doesnt work because catids is like an array
      FrageBean f=FragenBean.getRandomQuestionByCategory(catids);
    
  • My bean is:

    public static FrageBean getRandomQuestionByCategory(String catids) {
    ArrayList<Integer> alleFragenIds = new ArrayList<Integer>();
    
    DatabaseMetaData dbmd;
    Statement sql;
    Connection db = null;
    
    
    try {
        Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException ex) {
        System.out.println("driver not found");
    }
    try {
        db = DriverManager
                .getConnection("jdbc:mysql://localhost:3306/xyz?"
                + "user=root&password=xyz");
        dbmd = db.getMetaData();
    
        System.out.println("Connected with: " + dbmd.getUserName() + " | "
                + "Connection to: " + dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion() + " successful.\n");
        sql = db.createStatement();
    } catch (SQLException ex) {
        System.out.println("Error: " + ex);
    }
    
    try {
    
        String query = "select id from quest where quest_id=?";
        PreparedStatement prest = db.prepareStatement( query);
    
        prest.setString(1, catids);
    
    
        ResultSet rs = prest.executeQuery();
        ArrayList fragenliste = new ArrayList();
        while (rs.next()) {
            int fragenid = rs.getInt("id");
            alleFragenIds.add(fragenid);
    
        }
    
        rs.close();
        db.close();
    
    
    } catch (SQLException ex) {
        System.out.println("Error: " + ex);
    }
    
    Random r = new Random();
    int frageIndex = r.nextInt(alleFragenIds.size());
     System.out.println("Contents of al: " + alleFragenIds);
    return new FrageBean(alleFragenIds.get(frageIndex));
    
    }
    

At the moment it worked only for one id (Because I had only one choice). How can I do it with the checkboxes? How is it possible to forward "catids" to bean and to create the mysql-query dynamic? (select id from fragen where kategorie_id= [ALL CHECKED BOXES] )

Thanks in advance!!!!

Community
  • 1
  • 1
pythoniosIV
  • 237
  • 5
  • 18
  • 1
    that is what you need http://stackoverflow.com/questions/178479/preparedstatement-in-clause-alternatives – nano_nano Dec 13 '12 at 12:03

2 Answers2

2

Create below method in your class. Put proper driver clas and url connection and pass the catids as an string array.

Assumption : I am assuming column "quest_id" is of type int in table quest.

 public  void displayRecords(String[] catids)
{
    try
    {

        String queryStart = "select id from quest where quest_id in ( ";
        String queryMiddle = "";
        String prefix = "";
        String queryEnd = " )";
        String query = "";

        if (catids != null && catids.length > 0)
        {
            for (String id : catids)
            {
                queryMiddle = queryMiddle + prefix + id;
                prefix = ",";
            }

            query = queryStart + queryMiddle + queryEnd;
            System.out.println(query);

            Class.forName("DriverClass....................");
            Connection conn = DriverManager.getConnection("connection url ..................");
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(query);

            while (rs.next())
            {
                int fragenid = rs.getInt("id");
                System.out.println("ID = " + fragenid);
            }
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}
Rais Alam
  • 6,970
  • 12
  • 53
  • 84
  • Thank you so much! My other problem is, to give the catids from servlet to the bean: "FrageBean f=FragenBean.getRandomQuestionByCategory(catids);" How can I give the variable which is String[] to my bean? thanks – pythoniosIV Dec 13 '12 at 12:39
  • 1
    This is actually a dangerous answer. Think "SQL injection"!!! – Stephen C Dec 13 '12 at 12:48
  • @StephenC = You are true if you are working with **java.sql.Satement** then it is vulnerable to sql injection. You need to take care and validate your input before sending it to database. But its required some time that is the reason because of **sunmicrosystem** had not deprecated this Interface yet. Thanks – Rais Alam Dec 14 '12 at 04:23
  • @user1880437 Please describe the question in detail. I am unable to understand your next question. – Rais Alam Dec 14 '12 at 04:28
  • @RaisAlam - 1) it is possible to use Statement (with parameters) safely if you are very careful with validating your input, but it is much simpler (and by implication safer) to use a `PreparedStatement`. 2) The reason Statement is not deprecated is that it has lots of use-cases that are perfectly safe. But this is NOT one of those use-cases. – Stephen C Dec 14 '12 at 11:49
1

@RaisAlam's answer is dangerous as it is vulnerable to SQL injection. Here's a fixed version:

public  void displayRecords(String[] catids) {
    try {
        String queryStart = "select id from quest where quest_id in ( ";
        String queryMiddle = "";
        String prefix = "";
        String queryEnd = " )";
        String query = "";

        if (catids != null && catids.length > 0) {
            for (String id : catids) {
                queryMiddle = queryMiddle + prefix + "?";
                prefix = ",";
            }
            query = queryStart + queryMiddle + queryEnd;
            System.out.println(query);
            Class.forName(....);
            Connection conn = DriverManager.getConnection(....);
            PreparedStatement stmt = conn.createPreparedStatement(query);
            int i = 1;
            for (String id : catids) {
                stmt.setInt(i++, Integer.parseInt(id));
            }
            ResultSet rs = stmt.executeQuery(query);
            while (rs.next()) {
                int fragenid = rs.getInt("id");
                System.out.println("ID = " + fragenid);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Using a PreparedStatement with a placeholder for each parameter is the "best practice" way to avoid SQL injection.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thank you so much! My other problem is, to give the catids from servlet to the bean: "FrageBean f=FragenBean.getRandomQuestionByCategory(catids);" How can I give the variable which is String[] to my bean? thanks – pythoniosIV Dec 13 '12 at 13:05
  • Why don't you declare the formal parameter of `getRandomQuestionByCategory` to be an array? – Stephen C Dec 14 '12 at 11:52