JdbcTemplate的query方法
JdbcTemplate的query中sql是用?
佔位符的方式進行傳參的。
方法定義如下:
<T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper)
這個方法本身不支持in查詢,我們在調用前,可以自己封裝一層方法,變相的實現in查詢。
public <T> List<T> querySupportIn(String sql, Object[] args, RowMapper<T> rowMapper) throws DataAccessException {
Object[] obj = this.changeMessage(sql, args);
return this.getJdbcTemplate().query((String)obj[0], (Object[])obj[1], (int[])obj[2], rowMapper);
}
private Object[] changeMessage(String sql, Object[] args) throws DataAccessException {
List<Object> params = new ArrayList<Object>();
List<Integer> types = new ArrayList<Integer>();
List<Object[]> paramList = new ArrayList<Object[]>();
for(int i=0;i<args.length;i++){
Object arg = args[i];
if(arg.getClass().isArray()){
Object[] array = (Object[]) arg;
if(array.length == 0){
throw new RuntimeException("Array param can not be empty!");
}
Integer type = null;
for(Object obj : array){
if(type == null){
type = this.getTypes(obj);
}
params.add(obj);
types.add(type);
}
if(array.length > 1){
paramList.add(new Object[]{i, getParamSymbol(array.length)});
}
}else if(Collection.class.isAssignableFrom(arg.getClass()) ){
Collection<?> list = (Collection<?>) arg;
if(list.size() == 0){
throw new RuntimeException("Collection param can not be empty!");
}
Integer type = null;
for(Object obj : list){
if(type == null){
type = this.getTypes(obj);
}
params.add(obj);
types.add(type);
}
if(list.size() > 1){
paramList.add(new Object[]{i, getParamSymbol(list.size())});
}
}else{
params.add(arg);
types.add(this.getTypes(arg));
}
}
//根據序號替換單個?爲多個數組?
if(!paramList.isEmpty()){
StringBuffer sqlb = new StringBuffer();
String sqls = sql.toString();
int count = -1;
int index = -1;
for(Object[] obj : paramList){
int paramIndex = (Integer)obj[0];
while(true){
count++;
index = sqls.indexOf("?", index + 1);
if(index == -1 ){
throw new RuntimeException("Paramater size > '?' size!");
}
if(paramIndex == count){
sqlb.append(sqls.substring(0,index))
.append((String)obj[1]);
sqls = sqls.substring(index+1);
index = -1;
break;
}
}
}
sqlb.append(sqls);
sql = sqlb.toString();
}
int[] tys = new int[types.size()];
for(int i=0;i<types.size();i++){
tys[i] = types.get(i);
}
if(logger.isInfoEnabled()){
logger.info("sql : "+sql.toString());
logger.info("param: "+params);
logger.info("types: "+types);
}
return new Object[]{sql , params.toArray(), tys};
}
changeMessage方法的主要作用就是獲取Object[] args參數中所有的個數(包括數組套數組的個數),根據args的個數,把傳入的String sql參數中的所有?
佔位符重新替換一遍。
使用如下方式調用
String sql = "SELECT * FROM t1 WHERE type = ? AND id IN (?)";
String[] ids = new String[]{"a", "b"};
Object[] params = new Object[]{sql, ids};
List<Test> result = this.querySupportIn(sql, params, new BeanPropertyRowMapper<>(Test.class));
在querySupportIn內部調用的changeMessage方法中,處理後的sql就變成SELECT * FROM t1 WHERE type = ? AND id IN (?,?)
了,這樣就變相實現了in查詢。
NamedParameterJdbcTemplate的queryForList方法
NamedParameterJdbcTemplate的queryForList方法中sql是用具名參數SQL按名稱(以冒號開頭)
的方式進行傳參的。
方法定義如下:
<T> List<T> queryForList(String sql, SqlParameterSource paramSource, Class<T> elementType) throws DataAccessException
使用如下方式調用
String sql = "SELECT * FROM t1 WHERE type = :type AND id IN (:ids)";
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("type", 1);
String[] ids = new String[]{"a", "b"};
paramsMap.put("ids", ids);
List<Test> result = namedParameterJdbcTemplate.query(sql, paramsMap, new BeanPropertyRowMapper<>(Test.class));
NamedParameterJdbcTemplate的query方法,本身就支持in查詢,此處不再做封裝處理。
總結
NamedParameterJdbcTemplate的使用好處:如果參數比較多,並且參數位置或順序可能變化的情況下,使用NamedParameterJdbcTemplate是非常方便的!