fanstatic

使用PreparedStatement为有in的sql语句动态赋值

这个方法意思是动态加载?,再给?动态赋值.这个方法意思是动态加载?,再给?动态赋值.可能有好多青年在刚刚学习java 的 PreparedStatement类的时候有过这样一个疑问,如果我想根据多个ID来查找数据的时候怎么写呢?用SELECT my_column FROM my_table where search_column IN (?)

那么?要赋什么样的值呢?setInt(),还是setString(); 

preparedStatement.setString( 1, "'A', 'B', 'C'" ),这样做很明显是不正确的。

 

 

 

网上有很多解决方法,这里我汇集了一下,把一些好的给摘要了下来,
方法一:先写一个方法如下
public static String preparePlaceHolders(int length) {
   
StringBuilder builder = new StringBuilder();
   
for (int i = 0; i < length;) {
        builder
.append("?");
       
if (++i < length) {
            builder
.append(",");
       
}
   
}
   
return builder.toString();
}

public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
   
for (int i = 0; i < values.length; i++) {
        preparedStatement
.setObject(i + 1, values[i]);
   
}
}
方法使用如下
这个方法意思是动态加载?,再给?动态赋值.
private static final String SQL_FIND = "SELECT id, name, value FROM data WHERE id IN (%s)";

public List<Data> find(Set<Long> ids) throws SQLException {
   
Connection connection = null;
   
PreparedStatement statement = null;
   
ResultSet resultSet = null;
   
List<Data> list = new ArrayList<Data>();
   
String sql = String.format(SQL_FIND, preparePlaceHolders(ids.size()));

   
try{
        connection
= database.getConnection();
        statement
= connection.prepareStatement(sql);
        setValues
(statement, ids.toArray());
        resultSet
= statement.executeQuery();
       
while (resultSet.next()) {
           
Data data = new Data();
            data
.setId(resultSet.getLong("id"));
            data
.setName(resultSet.getString("name"));
            data
.setValue(resultSet.getInt("value"));
            list
.add(data);
       
}
   
} finally {
        close
(connection, statement, resultSet);
   
}

   
return list;
}
这个方法意思是动态加载?,再给?动态赋值.

方法二:创建一个sql函数


create or replace type split_tbl as table of varchar(32767);
/

create
or replace function split
(
  p_list varchar2
,
  p_del varchar2
:= ','
) return split_tbl pipelined
is
  l_idx    pls_integer
;
  l_list    varchar2
(32767) := p_list;
  l_value    varchar2
(32767);
begin
  loop
    l_idx
:= instr(l_list,p_del);
   
if l_idx > 0 then
      pipe row
(substr(l_list,1,l_idx-1));
      l_list
:= substr(l_list,l_idx+length(p_del));
   
else
      pipe row
(l_list);
     
exit;
   
end if;
 
end loop;
 
return;
end split;
/

 

使用好下
select * from table(split('one,two,three'))
  one
  two
  three

select * from TABLE1 where COL1 in (select * from table(split('value1,value2')))
  value1 AAA
  value2 BBB
PreparedStatement可以使用好下
 "select * from TABLE where COL in (select * from table(split(?)))"

此方法的意思是创建一个split的sql函数把以“1,2,3”形式的字符串劈开返回
  1
  2
  3
形式的表这样就可以用子查询了。
引用:http://stackoverflow.com/questions/178479/preparedstatement-in-clause-alternatives
不知道为什么jdk不为PreparedStatement类提供一个setList()方法。这样就避免了不少面向结构化的开发。

 

posted on 2011-08-02 14:32  fanstatic  阅读(4571)  评论(3编辑  收藏  举报