简体   繁体   中英

Java/ JDBC – Multi Parameter Search Using JDBC PreparedStatement

I want to create multi parameter search using JDBC prepared statement so as to prevent SQL injection attack and improve performance. As I couldn't find the best way to do it on the net.

I've tried to implement on my own as follow.

In this program I want to allow the user to search an employee by either first name, last name or department id.

I want to know

  1. if my implementation would prevent SQL injection
  2. If I am using prepared statement correctly? I have some doubt on this line
    PreparedStatement stat = conn.prepareStatement(sql.toString());

Let's say two users search by using the same parameters, and thus it would result the same sql string. According to my implementation, would the database have to prepare that sql twice or just once?

    public class EmpDAO {

        public static List<Employee> findByCriteria(Employee e)
                throws SQLException, IOException {

            try (Connection conn = getConnection()) {

                StringBuilder sql = new StringBuilder("SELECT * FROM Employee ");

                //collect user supplied parameters
                Map<String, String> params = new HashMap<String, String>();
                if (e.getFname() != null && e.getFname().length() != 0) {
                    params.put(EmpDAO.FNAME, e.getFname());
                }
                if (e.getLname() != null && e.getLname().length() != 0) {
                    params.put(EmpDAO.LNAME, e.getLname());
                }

                if (e.getDepid() > 0) {
                    params.put(EmpDAO.DEPT_ID, new Integer(e.getDepid()).toString());
                }

                //construct prepared statement based on the parameters

                Set<String> colSet = params.keySet();
                if (colSet != null && !colSet.isEmpty()) {
                    StringBuilder whereClause = new StringBuilder(" WHERE");
                    String andOp = "";
                    for (String colName : colSet) {                 
                        whereClause.append(andOp);
                        whereClause.append(" ");
                        whereClause.append(colName);
                        whereClause.append("=? ");
                        andOp = " AND ";
                    }

                    sql.append(whereClause);
                }

                PreparedStatement stat = conn.prepareStatement(sql.toString());
                int paramPos = 1;
                for (String colName : colSet) {
                    if (colName.equals(EmpDAO.FNAME)) {
                        stat.setString(paramPos, params.get(colName));
                    }

                    if (colName.equals(EmpDAO.LNAME)) {
                        stat.setString(paramPos, params.get(colName));
                    }

                    if (colName.equals(EmpDAO.DEPT_ID)) {
                        stat.setInt(paramPos, Integer.parseInt(params.get(colName)));
                    }
                    paramPos++;
                }

                List<Employee> emp1 = new ArrayList<>();
                try (ResultSet result = stat.executeQuery()) {

                    while (result.next()) {
                        Employee emp = new Employee();
                        emp.setDepid(result.getInt("DEPT_ID"));
                        emp.setEmpid(result.getInt("EMP_ID"));
                        emp.setFname(result.getString("FNAME"));
                        emp.setJobid(result.getInt("JOB_ID"));
                        emp.setLname(result.getString("LNAME"));
                        emp.setMangid(result.getInt("MANAGER_EMP_ID"));
                        emp.setSalary(result.getInt("SALARY"));
                        emp1.add(emp);
                    }
                }
                return emp1;
            }
        }

        public static Connection getConnection() throws SQLException, IOException {
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            return DriverManager.getConnection("jdbc:mysql://localhost:3306/test",
                    "root", "root");
        }

        public static final String FNAME = "FNAME";
        public static final String LNAME = "FNAME";
        public static final String DEPT_ID = "FNAME";
    }

Yes -- as written this will prevent SQL injection attacks and yes, that is how you use .prepareStatement . You should probably post this code on https://codereview.stackexchange.com/ if you want a critique of how it's done.

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