天天看点

JdbcTemplate对象

描述

使用 

例子 

插入

修改

删除

查询

queryForMap():查询结果,将结果集封装为map集合

queryForList():查询结果,将结果集封装为list集合

query():查询结果,将结果集封装为JavaBean对象

queryForObject:查询结果,将结果集封装为对象

描述

JdbcTemplate是Spring框架对JDBC的简单封装,依赖于数据源DataSource

使用 
要是用得先导包
JdbcTemplate对象
JdbcTemplate对象
调用JdbcTemplate的方法来完成CRUD的操作
  • update():执行DML语句。增、删、改语句
  • queryForMap():查询结果,将结果集封装为map集合
  • queryForList():查询结果,将结果集封装为list集合
  • query():查询结果,将结果集封装为JavaBean对象
  • queryForObject:查询结果,将结果集封装为对象
例子 
下面我们用一个例子说明,为何封装方便,例子用到:
  • druid连接池以及Jdbc工具类
  • 单元测试
package com.lingaolu;

import org.springframework.jdbc.core.JdbcTemplate;

/**
 * @author 林高禄
 * @create 2020-06-28-9:43
 */
public class TemplateDemo {

    private JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDataSource());
    
    
}
           
用到的数据库表
  • 学生表 
JdbcTemplate对象
  • 班级表
JdbcTemplate对象

插入

@Test
    public void insert() {
        String sql = "insert into student(name,class_id,ageNum) values('王帅',2,22)";
        int update = template.update(sql);
        System.out.println(update);
    }           

运行输出:

1

运行后学生表中的数据多了一条王帅
JdbcTemplate对象

修改

@Test
    public void update(){
        String sql = "update student set name=? where name=?";
        int update = template.update(sql,"王丑","王帅");
        System.out.println(update);
    }           

运行输出:

1

运行后表中的数据,王帅变成了王丑
JdbcTemplate对象

删除

@Test
    public void delete(){
        String sql = "delete from student where name=?";
        int delete = template.update(sql, "王丑");
        System.out.println(delete);
    }           

运行输出:

1

运行后表中的数据,王丑删除了
JdbcTemplate对象

查询

queryForMap():查询结果,将结果集封装为map集合

@Test
    public void queryForMap(){
        String sql = "select * from student";
        Map<String, Object> stringObjectMap = template.queryForMap(sql);
        System.out.println(stringObjectMap);
    }           

运行输出:

org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 3

......

......

因为queryForMap()只能需要一条结果,而我们查出来的是3条,所以报错,所以我们修改一下sql,值查出一条
@Test
    public void queryForMap(){
        String sql = "select * from student limit 0,1";
        Map<String, Object> stringObjectMap = template.queryForMap(sql);
        System.out.println(stringObjectMap);
    }           

运行输出:

{id=1, name=林帅, class_id=2, ageNum=23}

queryForList():查询结果,将结果集封装为list集合

@Test
    public void queryForList(){
        String sql = "select * from student";
        List<Map<String, Object>> maps = template.queryForList(sql);
        maps.forEach(System.out::println);
    }           

运行输出:

{id=1, name=林帅, class_id=2, ageNum=23}

{id=2, name=徐帅, class_id=2, ageNum=24}

{id=3, name=吴帅, class_id=1, ageNum=27}

query():查询结果,将结果集封装为JavaBean对象

我们先把学生表的字段和值修改一下,原来的ageNum改为num_age,并且把“徐帅”的num_age置为null
JdbcTemplate对象
再来一个实体类StudentVo
package com.lingaolu;

/**
 * @author 林高禄
 * @create 2020-06-28-10:54
 */
public class StudentVo {
    private int id;
    private String name;
    private int ageNum;
    private String classname;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAgeNum() {
        return ageNum;
    }

    public void setAgeNum(int ageNum) {
        this.ageNum = ageNum;
    }

    public String getClassname() {
        return classname;
    }

    public void setClassname(String classname) {
        this.classname = classname;
    }

    @Override
    public String toString() {
        return "StudentVo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", ageNum=" + ageNum +
                ", classname='" + classname + '\'' +
                '}';
    }
}
           
@Test
    public void query() {
        String sql = "select t.*,c.name class_name from student t left join class c on t.class_id = c.id";
        List<StudentVo> query = template.query(sql, new BeanPropertyRowMapper<StudentVo>(StudentVo.class));
        query.forEach(System.out::println);
    }           

运行输出:

org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'null' to required type 'int' for property 'ageNum'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [null] to type [int] for value 'null'; nested exception is java.lang.IllegalArgumentException: A null value cannot be assigned to a primitive type

......

......

A null value cannot be assigned to a primitive type,空值不能分配给基元类型,这就是我特意把其中一个num_age置为空的原因,所以我们以后为了防止报错,写实体类的属性要用包装类对象,而不用基本类型
修改后的StudentVo的代码
package com.lingaolu;

/**
 * @author 林高禄
 * @create 2020-06-28-10:54
 */
public class StudentVo {
    private Integer id;
    private String name;
    private Integer ageNum;
    private String classname;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAgeNum() {
        return ageNum;
    }

    public void setAgeNum(Integer ageNum) {
        this.ageNum = ageNum;
    }

    public String getClassname() {
        return classname;
    }

    public void setClassname(String classname) {
        this.classname = classname;
    }

    @Override
    public String toString() {
        return "StudentVo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", ageNum=" + ageNum +
                ", classname='" + classname + '\'' +
                '}';
    }
}
           

再次运行输出:

StudentVo{id=1, name='林帅', ageNum=23, classname='null'}

StudentVo{id=2, name='徐帅', ageNum=null, classname='null'}

StudentVo{id=3, name='吴帅', ageNum=27, classname='null'}

发现没有,我们的classname全是空的,奇怪,数据库里的age_num能赋值到Student属性里的ageNum,为何sql查出来的class_name不能赋值到Student属性里的classname呢,因为表里属性下划线查出来后能转为驼峰命名,但是classname并不是驼峰命名,className才是驼峰命名,所以这里我们要改一下,第一种改法是把StudentVo类里的classname改为className,第二种改法是sql语句取别名和StudentVo类的对应,这里我们采用第一种,规范一下命名,建议sql的别名最好也要规范一下和属性一致,看着舒服,当然不改也行。
package com.lingaolu;

/**
 * @author 林高禄
 * @create 2020-06-28-10:54
 */
public class StudentVo {
    private Integer id;
    private String name;
    private Integer ageNum;
    private String className;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAgeNum() {
        return ageNum;
    }

    public void setAgeNum(Integer ageNum) {
        this.ageNum = ageNum;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    @Override
    public String toString() {
        return "StudentVo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", ageNum=" + ageNum +
                ", className='" + className + '\'' +
                '}';
    }
}
           
测试例子还是原来的代码
@Test
    public void query() {
        String sql = "select t.*,c.name class_name from student t left join class c on t.class_id = c.id";
        List<StudentVo> query = template.query(sql, new BeanPropertyRowMapper<StudentVo>(StudentVo.class));
        query.forEach(System.out::println);
    }           

 运行输出:

StudentVo{id=1, name='林帅', ageNum=23, className='优秀班'}

StudentVo{id=2, name='徐帅', ageNum=null, className='优秀班'}

StudentVo{id=3, name='吴帅', ageNum=27, className='尖子班'}

queryForObject:查询结果,将结果集封装为对象

@Test
    public void queryForObject() {
        String sql = "select count(*) from student";
        Map map = template.queryForObject(sql, Map.class);
        System.out.println(map);

    }           

运行输出:

org.springframework.dao.TypeMismatchDataAccessException: Type mismatch affecting row number 0 and column type 'BIGINT': Value [3] is of type [java.lang.Long] and cannot be converted to required type [java.util.Map]

Long不能转为Map,queryForObject方法一般是适用于聚合函数,返回的是Long值,所以我们要把测试代码修改下
@Test
    public void queryForObject() {
        String sql = "select count(*) from student";
        Long aLong = template.queryForObject(sql, Long.class);
        System.out.println(aLong);
    }