SpringJDBC的in查询用法

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是非常方便的!

参考资料
详解jdbcTemplate和namedParameterJdbcTemplate

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值