欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JdbcTemplate的一次爬坑记录

程序员文章站 2022-09-10 15:19:41
时隔三个多月,我终于想起我还有个博客,其实也不是忘了我这个博客,只是平时工作繁忙没时间去写博客,故今晚腾出时间来记录一下上次工作中遇到的一个问题,给园友们分享出来,以免入坑。 上个星期在工作中使用JdbcTemplate执行了一个select * from table where id in (?, ......

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

 

  上个星期在工作中使用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的依赖导入进去,然后我们开始撸代码:

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

  JdbcTemplate的一次爬坑记录

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

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;

   实体类和表映射的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);
    }
}
@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);

    }
}

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

JdbcTemplate的一次爬坑记录

  可以看出来,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());
    }
}

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

JdbcTemplate的一次爬坑记录

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

 

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