PreparedStatement IN clause alternatives?

前端 未结 30 3884
情歌与酒
情歌与酒 2020-11-21 05:19

What are the best workarounds for using a SQL IN clause with instances of java.sql.PreparedStatement, which is not supported for multiple values du

30条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-21 05:41

    Here's a complete solution in Java to create the prepared statement for you:

    /*usage:
    
    Util u = new Util(500); //500 items per bracket. 
    String sqlBefore  = "select * from myTable where (";
    List values = new ArrayList(Arrays.asList(1,2,4,5)); 
    string sqlAfter = ") and foo = 'bar'"; 
    
    PreparedStatement ps = u.prepareStatements(sqlBefore, values, sqlAfter, connection, "someId");
    */
    
    
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Util {
    
        private int numValuesInClause;
    
        public Util(int numValuesInClause) {
            super();
            this.numValuesInClause = numValuesInClause;
        }
    
        public int getNumValuesInClause() {
            return numValuesInClause;
        }
    
        public void setNumValuesInClause(int numValuesInClause) {
            this.numValuesInClause = numValuesInClause;
        }
    
        /** Split a given list into a list of lists for the given size of numValuesInClause*/
        public List> splitList(
                List values) {
    
    
            List> newList = new ArrayList>(); 
            while (values.size() > numValuesInClause) {
                List sublist = values.subList(0,numValuesInClause);
                List values2 = values.subList(numValuesInClause, values.size());   
                values = values2; 
    
                newList.add( sublist);
            }
            newList.add(values);
    
            return newList;
        }
    
        /**
         * Generates a series of split out in clause statements. 
         * @param sqlBefore ""select * from dual where ("
         * @param values [1,2,3,4,5,6,7,8,9,10]
         * @param "sqlAfter ) and id = 5"
         * @return "select * from dual where (id in (1,2,3) or id in (4,5,6) or id in (7,8,9) or id in (10)"
         */
        public String genInClauseSql(String sqlBefore, List values,
                String sqlAfter, String identifier) 
        {
            List> newLists = splitList(values);
            String stmt = sqlBefore;
    
            /* now generate the in clause for each list */
            int j = 0; /* keep track of list:newLists index */
            for (List list : newLists) {
                stmt = stmt + identifier +" in (";
                StringBuilder innerBuilder = new StringBuilder();
    
                for (int i = 0; i < list.size(); i++) {
                    innerBuilder.append("?,");
                }
    
    
    
                String inClause = innerBuilder.deleteCharAt(
                        innerBuilder.length() - 1).toString();
    
                stmt = stmt + inClause;
                stmt = stmt + ")";
    
    
                if (++j < newLists.size()) {
                    stmt = stmt + " OR ";
                }
    
            }
    
            stmt = stmt + sqlAfter;
            return stmt;
        }
    
        /**
         * Method to convert your SQL and a list of ID into a safe prepared
         * statements
         * 
         * @throws SQLException
         */
        public PreparedStatement prepareStatements(String sqlBefore,
                ArrayList values, String sqlAfter, Connection c, String identifier)
                throws SQLException {
    
            /* First split our potentially big list into lots of lists */
            String stmt = genInClauseSql(sqlBefore, values, sqlAfter, identifier);
            PreparedStatement ps = c.prepareStatement(stmt);
    
            int i = 1;
            for (int val : values)
            {
    
                ps.setInt(i++, val);
    
            }
            return ps;
    
        }
    
    }
    

提交回复
热议问题