Spring框架JdbcTemplate类中查询方法介绍
本文使用Spring2.5.6.SEC02和JDK1.4作为讲解环境。</span> Spring框架中org.springframework.jdbc.core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,其他模板类都是基于它封装完成的。 Spring除了提供JdbcTemplate核心类外,还提供了基于JdbcTemplate实现的NamedParameterJdbcTemplate类用于支持命名参数绑定、 SimpleJdbcTemplate类用于支持JDK5+的可变参数及自动装箱拆箱等特性。本文主要介绍JdbcTemplate核心类。 JdbcTemplate类主要提供以下四类方法: 下面将主要介绍query方法及queryForXXX方法的返回值和相关异常。 首先我们先大概了解下query方法及queryForXXX方法的调用层次。 下图是不需要设置sql参数的方法的调用层次: 下图是需要设置sql参数的方法的调用层次: 其中Object[] args就是设置参数用的,而int[] argTypes则是指定参数类型,参数类型定义在java.sql.Types类中。 接下来我们来看看不需要设置sql参数的查询方法在0行1列,1行1列和5行1列结果集中的返回值 0行1列 1行1列 5行1列 List query 大小为0的List 大小为1的List 大小为5的List Map queryForMap org.springframework.dao. 以列名为key,大小为1的Map org.springframework.dao. Object queryForObject org.springframework.dao. Object org.springframework.dao. Object queryForObject org.springframework.dao. 类型为requiredType的Object org.springframework.dao. long queryForLong org.springframework.dao. long org.springframework.dao. int queryForInt org.springframework.dao. int org.springframework.dao. List queryForList 大小为0的List 大小为1的List 大小为5的List List queryForList 大小为0的List List中包含1个以列名为key的Map List中包含5个以列名为key的Map 其他不支持多列结果集的查询方法则会抛出IncorrectResultSetColumnCountException异常。 设置sql参数的查询方法的返回值和上述结果类似。 从上面的结果可以看出只有返回值类型为List的方法可以接收零到多行结果集而不抛出异常,所以在使用query方法及queryForXXX方法时需要注意处理EmptyResultDataAccessException和IncorrectResultSizeDataAccessException这两个异常,这两个异常反映出数据库表中数据可能出现了缺失或冗余。如果返回值不符合期望值时,则需要排查业务流程或者数据了。 最后我们来看看RowMapper接口,这个接口的实现类的功能是将结果集中的每一行数据封装成用户定义的结构,所以在查询方法中经常会被用到。 Spring框架为我们提供了BeanPropertyRowMapper/ParameterizedBeanPropertyRowMapper,ColumnMapRowMapper和SingleColumnRowMapper这三大便利类。 BeanPropertyRowMapper类与ParameterizedBeanPropertyRowMapper类的功能完全相同,当POJO对象和数据库表字段完全对应或者驼峰式与下划线式对应时,该类会根据构造函数中传递的class来自动填充数据。只是ParameterizedBeanPropertyRowMapper类使用泛型需要JDK5+支持。这里需要注意虽然这两个类提供了便利,但是由于使用反射导致性能下降,所以如果需要高性能则还是需要自己去实现RowMapper接口来包装数据。 ColumnMapRowMapper类返回一个List对象,对象中的每一个元素都是一个以列名为key的Map对象。 SingleColumnRowMapper类也返回一个List对象,对象中的每个元素是数据库中的某列的值。注意结果集必须是单列,不然会抛出IncorrectResultSetColumnCountException异常。 现在在Spring2.5.6.SEC02和JDK1.4环境下建个项目来了解下上述三个便利类。 建立数据库表: 插入5条测试数据: 新建一个Java项目,准备依赖Jar包,Spring配置文件appContext.xml,配置数据源。 建立POJO对象: 建立带main方法的类 先来了解BeanPropertyRowMapper类: 输出结果如下: [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类: 输出结果为: [{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类: 输出结果为: [1, 2, 3, 4, 5] 现在大家初步了解JdbcTemplate类中查询方法了吧!
</span>
(String sql,
RowMapper rowMapper)
(String sql)
EmptyResultDataAccessException:
Incorrect result size: expected 1, actual 0
IncorrectResultSizeDataAccessException:
Incorrect result size: expected 1, actual 5
(String sql,
RowMapper rowMapper)
EmptyResultDataAccessException:
Incorrect result size: expected 1, actual 0
IncorrectResultSizeDataAccessException:
Incorrect result size: expected 1, actual 5
(String sql,
Class requiredType)
EmptyResultDataAccessException:
Incorrect result size: expected 1, actual 0
IncorrectResultSizeDataAccessException:
Incorrect result size: expected 1, actual 5
(String sql)
EmptyResultDataAccessException:
Incorrect result size: expected 1, actual 0
IncorrectResultSizeDataAccessException:
Incorrect result size: expected 1, actual 5
(String sql)
EmptyResultDataAccessException:
Incorrect result size: expected 1, actual 0
IncorrectResultSizeDataAccessException:
Incorrect result size: expected 1, actual 5
(String sql,
Class elementType)
(String sql)
其中下面这些查询方法支持多列结果集:
create table T_SPRINGJDBC_TEST ( my_number NUMBER, my_varchar VARCHAR2(10), my_date DATE )
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 + "}"; } }
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); }
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); }
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); }