Spring框架JdbcTemplate类中查询方法介绍

jopen 10年前

本文使用Spring2.5.6.SEC02JDK1.4作为讲解环境。</span>
 </span>

Spring框架中org.springframework.jdbc.core包提供了JDBC模板类,其中JdbcTemplatecore包的核心类,其他模板类都是基于它封装完成的。

Spring除了提供JdbcTemplate核心类外,还提供了基于JdbcTemplate实现的NamedParameterJdbcTemplate类用于支持命名参数绑定、 SimpleJdbcTemplate类用于支持JDK5+的可变参数及自动装箱拆箱等特性。本文主要介绍JdbcTemplate核心类。

JdbcTemplate类主要提供以下四类方法:

  1. execute方法:用于执行任何SQL语句,一般用于执行DDL语句;
  2. update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句,batchUpdate方法用于执行批处理相关语句;
  3. query方法及queryForXXX方法:用于执行查询相关语句;
  4. call方法:用于执行存储过程、函数相关语句。

下面将主要介绍query方法及queryForXXX方法的返回值和相关异常。

首先我们先大概了解下query方法及queryForXXX方法的调用层次。

下图是不需要设置sql参数的方法的调用层次:


下图是需要设置sql参数的方法的调用层次:

其中Object[] args就是设置参数用的,而int[] argTypes则是指定参数类型,参数类型定义在java.sql.Types类中。


接下来我们来看看不需要设置sql参数的查询方法在01列,11列和51结果集中的返回值

 

01

11

51


List query
(String sql,
RowMapper rowMapper)

大小为0List

大小为1List

大小为5List


Map queryForMap
(String sql)

org.springframework.dao.
EmptyResultDataAccessException:

 Incorrect result size: expected 1, actual 0

以列名为key,大小为1Map

org.springframework.dao.
IncorrectResultSizeDataAccessException:

 Incorrect result size: expected 1, actual 5


Object queryForObject
(String sql,
RowMapper rowMapper)

org.springframework.dao.
EmptyResultDataAccessException:

 Incorrect result size: expected 1, actual 0

Object

org.springframework.dao.
IncorrectResultSizeDataAccessException:

Incorrect result size: expected 1, actual 5


Object queryForObject
(String sql,
Class requiredType)

org.springframework.dao.
EmptyResultDataAccessException:

Incorrect result size: expected 1, actual 0

类型为requiredTypeObject

org.springframework.dao.
IncorrectResultSizeDataAccessException:

 Incorrect result size: expected 1, actual 5


long queryForLong
(String sql)

org.springframework.dao.
EmptyResultDataAccessException:

 Incorrect result size: expected 1, actual 0

long

org.springframework.dao.
IncorrectResultSizeDataAccessException:

 Incorrect result size: expected 1, actual 5


int queryForInt
(String sql)

org.springframework.dao.
EmptyResultDataAccessException:

 Incorrect result size: expected 1, actual 0

int

org.springframework.dao.
IncorrectResultSizeDataAccessException:

 Incorrect result size: expected 1, actual 5


List queryForList
(String sql,
Class elementType)

大小为0List

大小为1List

大小为5List


List queryForList
(String sql)

大小为0List

List中包含1个以列名为keyMap

List中包含5个以列名为keyMap



    其中下面这些
查询方法支持多列结果集:

  • List query(String sql, RowMapper rowMapper)
  • Map queryForMap(String sql)
  • Object queryForObject(String sql, RowMapper rowMapper)
  • List queryForList(String sql)

其他不支持多列结果集的查询方法则会抛出IncorrectResultSetColumnCountException异常。

设置sql参数的查询方法的返回值和上述结果类似。

从上面的结果可以看出只有返回值类型为List的方法可以接收零到多行结果集而不抛出异常,所以在使用query方法及queryForXXX方法时需要注意处理EmptyResultDataAccessExceptionIncorrectResultSizeDataAccessException这两个异常,这两个异常反映出数据库表中数据可能出现了缺失或冗余。如果返回值不符合期望值时,则需要排查业务流程或者数据了。

最后我们来看看RowMapper接口,这个接口的实现类的功能是将结果集中的每一行数据封装成用户定义的结构,所以在查询方法中经常会被用到。

Spring框架为我们提供了BeanPropertyRowMapper/ParameterizedBeanPropertyRowMapperColumnMapRowMapperSingleColumnRowMapper这三大便利类。

BeanPropertyRowMapper类与ParameterizedBeanPropertyRowMapper类的功能完全相同,当POJO对象和数据库表字段完全对应或者驼峰式与下划线式对应时,该类会根据构造函数中传递的class来自动填充数据。只是ParameterizedBeanPropertyRowMapper类使用泛型需要JDK5+支持。这里需要注意虽然这两个类提供了便利,但是由于使用反射导致性能下降,所以如果需要高性能则还是需要自己去实现RowMapper接口来包装数据。

ColumnMapRowMapper类返回一个List对象,对象中的每一个元素都是一个以列名为keyMap对象。

SingleColumnRowMapper类也返回一个List对象,对象中的每个元素是数据库中的某列的值。注意结果集必须是单列,不然会抛出IncorrectResultSetColumnCountException异常。

现在在Spring2.5.6.SEC02JDK1.4环境下建个项目来了解下上述三个便利类。

建立数据库表:

create table T_SPRINGJDBC_TEST    (      my_number  NUMBER,      my_varchar VARCHAR2(10),      my_date    DATE    )


插入5条测试数据:


新建一个Java项目,准备依赖Jar包,Spring配置文件appContext.xml,配置数据源。

建立POJO对象:

public class MyPojo {        private long my_Number;        private Date my_Date;        private String my_Varchar;        //本文在此处省略了setter和getter方法        public String toString() {            return "MyPojo :{my_Number=" + my_Number + ", my_Date=" + my_Date                    + ", my_Varchar=" + my_Varchar + "}";        }    }


建立带main方法的类

先来了解BeanPropertyRowMapper:

public static void main(String[] args) {            ApplicationContext ctx = new FileSystemXmlApplicationContext(                    "classpath:appContext.xml");            DataSource dataSource = (DataSource) ctx.getBean("dataSource");            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);            List result = jdbcTemplate.query("select * from t_springjdbc_test",                    new BeanPropertyRowMapper(MyPojo.class));            System.out.println(result);        }


输出结果如下:

[MyPojo :{my_Number=1, my_Date=2013-10-10 01:00:00.0, my_Varchar=a}, MyPojo :{my_Number=2, my_Date=2013-10-11 02:00:00.0, my_Varchar=b}, MyPojo :{my_Number=3, my_Date=2013-10-12 03:00:00.0, my_Varchar=c}, MyPojo :{my_Number=4, my_Date=2013-10-13 04:00:00.0, my_Varchar=d}, MyPojo :{my_Number=5, my_Date=2013-10-14 05:00:00.0, my_Varchar=e}]

再来了解ColumnMapRowMapper:

public static void main(String[] args) {            ApplicationContext ctx = new FileSystemXmlApplicationContext(                    "classpath:appContext.xml");            DataSource dataSource = (DataSource) ctx.getBean("dataSource");            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);            List result = jdbcTemplate.query("select * from t_springjdbc_test",                    new ColumnMapRowMapper());            System.out.println(result);        }


输出结果为:

[{MY_NUMBER=1, MY_VARCHAR=a, MY_DATE=2013-10-10 01:00:00.0}, {MY_NUMBER=2, MY_VARCHAR=b, MY_DATE=2013-10-11 02:00:00.0}, {MY_NUMBER=3, MY_VARCHAR=c, MY_DATE=2013-10-12 03:00:00.0}, {MY_NUMBER=4, MY_VARCHAR=d, MY_DATE=2013-10-13 04:00:00.0}, {MY_NUMBER=5, MY_VARCHAR=e, MY_DATE=2013-10-14 05:00:00.0}]

最后了解SingleColumnRowMapper类:

public static void main(String[] args) {            ApplicationContext ctx = new FileSystemXmlApplicationContext(                    "classpath:appContext.xml");            DataSource dataSource = (DataSource) ctx.getBean("dataSource");            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);            List result = jdbcTemplate.query(                    "select my_number from t_springjdbc_test",                    new SingleColumnRowMapper());            System.out.println(result);        }


输出结果为:

[1, 2, 3, 4, 5]

现在大家初步了解JdbcTemplate类中查询方法了吧!