最近,同事在空闲时间写了一个 Spring 的 demo,遇到了一个关于 JdbcTemplate 的小坑。今天我们一起来看看这个坑。
一般同事不喊我,一喊我准没好事。这次也不例外,他喊我并向我抛了一个异常:java.sql.SQLException: No value specified for parameter 3。并让我帮他检查代码,我基本上都是非常乐意的。因为帮助别人解决问题的过程中,我也能收获更多。不光是友谊,快乐和知识见识增长也是其中的一部分。
我看了他的代码,内容简化如下:
@Component("xttblogDao")
public class XttblogDaoImpl implements XttblogDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public List<Xttblog> selectByDynamicParams(List<Integer> idList, String name) {
StringBuffer sql = new StringBuffer();
sql.append("select * from xttblog where id in ( ");
// 拼装SQL
List<String> stringList = new ArrayList<>();
for (int i = 0;i < idList.size();i++){
stringList.add("?");
}
sql.append(String.join(",",stringList));
sql.append(" ) and name = ?");
System.err.println(sql.toString());
return jdbcTemplate.query(sql.toString(),new XttblogMapper(),idList,name);
}
}
然后测试上面的代码,发现最终报错:java.sql.SQLException: No value specified for parameter 3。
一时间,我仔细看了看 SQL,没问题。然后把“ ) and name = ?”这部分去掉,也就是去掉最后一个查询参数。发现 OK 了,不报错了。
这是我又想到了 Spring 提供的另外一个类:NamedParameterJdbcTemplate。然后改造代码,使用 NamedParameterJdbcTemplate 查询一下试一试。
// 从容器中将dataSource这个对象注入进来
@Autowired
private DataSource dataSource;
@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(){
// 要构造NamedParameterJdbcTemplate对象需要依赖dataSource
return new NamedParameterJdbcTemplate(dataSource);
}
同样的代码,换一个类就完全支持。
除此之外,JdbcTemplate 还有另外一个问题。比如,我们使用 SQL Server 的分页 top 时,同样无法使用 JdbcTemplate。因为 JdbcTemplate 只能将问号用于where语句中的参数。
关于 JDBC 的操作,Spring 提供了 3 个模板类供我们选择:
- JdbcTemplate:提供按照索引参数传递,用 in 的时候要特别注意,推荐使用 NamedParameterJdbcTemplate。
- NamedParameterJdbcTemplate:按照名字参数传递
- SimpleJdbcTemplate:支持Java5特性,如自动装箱、泛型和可变参数列表等
JdbcTemplate 的处理逻辑是一个 ?一个参赛。而 in 往往我们可能只留了一个 ?。NamedParameterJdbcTemplate 在处理 sql 中 in 范围查询,会根据实际传入参数的 List 个数,做了一些修改,而原生的 JdbcTemplate 则不会这么做。
以上这些内容,希望能够帮助大家排除一些坑。
: » 面试官:使用JdbcTemplate in 语句你遇到过哪些坑?
原创文章,作者:sunnyman218,如若转载,请注明出处:https://blog.ytso.com/252088.html