JdbcTemplate的一次爬坑记录

  时隔三个多月,我终于想起我还有个博客,其实也不是忘了我这个博客,只是平时工作繁忙没时间去写博客,故今晚腾出时间来记录一下上次工作中遇到的一个问题,给园友们分享出来,以免入坑。

  上个星期在工作中使用JdbcTemplate执行了一个select * from table where id in (?,?,?) and name = ? 的SQL,这个SQL大家都明白什么意思吧,然后我得给这几个 "?" 赋值,没问题吧。可是在执行的时候给我报了一个异常:java.sql.SQLException: No value specified for parameter 3      纳尼?这就有点奇怪了,几个意思?是因为jdbcTemplate这个对象不支持括号内的问号和括号外的问号同时出现,什么意思呢?就是说  where id in (?) 是正确的  where name  = ? 也是正确的,但是  where id in (?) and name = ? 就不支持了;需要将 jdbcTemplate 对象换成 NamedParameterJdbcTemplate 即可,下面我会把代码贴出来,首先创建一个SpringBoot项目,将Web,MySQL,Jdbc,Lombok的依赖导入进去,然后我们开始撸代码:

  我们先来看一下数据库的数据:

  

  下面是建表语句,有需要的同志们可以复制过去:

CREATE TABLE `t_book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `isbn` varchar(255) DEFAULT NULL,
  `publish` varchar(255) DEFAULT NULL,
  `publisher` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
View Code

   实体类和表映射的RowMapper实现类的代码就不贴了,按照表字段去建一个就可以了,这一步跳过

  下面是controller和dao的代码:

@RestController
@RequestMapping("/api/v1/book")
public class BookRestController {

    @Resource
    private ObjectMapper jsonMapper;

    // 这里为了方便就省略service层,直接将dao注入进来了
    @Resource
    private BookDAO bookDAO;

    @GetMapping("/list")
    public JsonNode list(){
        ObjectNode respJson = jsonMapper.createObjectNode();
        List<Integer> idList = Arrays.asList(1, 2, 3);
        String name = "mybatis从入门到精通";
        List<TBook> bookList = bookDAO.selectByDynamicParams(idList, name);
        return respJson.putPOJO("data",bookList);
    }
}
View Code
@Component("bookDAO")
public class BookDAOImpl implements BookDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<TBook> selectByDynamicParams(List<Integer> idList, String name) {
        StringBuffer sql = new StringBuffer();
        sql.append("select * from t_book where id in ( ");
        // 拼装?
        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 BookMapper(),idList,name);

    }
}
View Code

  好了,执行一把,看一下结果吧,访问 localhost:8080/api/v1/book/list  ,控制台保如下错误:

  可以看出来,SQL语句的没有问题的,那么我们尝试换一种写法,使用 NamedParameterJdbcTemplate ,由于spring默认是加载jdbcTemplate的,所以NamedParameterJdbcTemplate 对象需要我们自己去配置,创建一个配置类或者直接在启动类配置也可以,启动类其实就是一个配置类,进行如下配置:

  

// 从容器中将dataSource这个对象注入进来
@Autowired
private DataSource dataSource;

@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(){
    // 要构造NamedParameterJdbcTemplate对象需要依赖dataSource
    return new NamedParameterJdbcTemplate(dataSource);
}

  dao层将NamedParameterJdbcTemplate 对象注入进来并执行SQL:

@Component("bookDAO")
public class BookDAOImpl implements BookDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Override
    public List<TBook> selectByDynamicParams(List<Integer> idList, String name) {
        String sql = "select * from t_book where id in (:idList) and name = :bookName";
        // 集合中的key一定要与sql中定义的参数变量相同,这里的集合里的参数不需要进行手动处理,直接将集合作为一个参数对象传进去即可
        Map<String,Object> params = new HashMap<>(2);
        params.put("idList",idList);
        params.put("bookName",name);
        return namedParameterJdbcTemplate.query(sql,params,new BookMapper());
    }
}

  这次再执行一把看一下结果:

  这次就执行成功了,控制台也没有报错,很舒服,我记得以前使用原生jdbc进行查询的时候当时使用的是sqlserver数据库,写了一条分页的SQL,当时也是有问号的,同样会报错,没想到spring的这个jdbc跟原生的jdbc一样坑,只能说技术这种东西学无止境呀。

  革命尚未成功,同志仍需努力!

猜你喜欢

转载自www.cnblogs.com/maolinjava/p/10743522.html