转载:博客主页:http://blog.csdn.NET/chszs

一、概述

在Spring JDBC模块中,所有的类可以被分到四个单独的包:
1)core
即核心包,它包含了JDBC的核心功能。此包内有很多重要的类,包括:JdbcTemplate类、SimpleJdbcInsert类,SimpleJdbcCall类,以及NamedParameterJdbcTemplate类。
2)datasource
即数据源包,访问数据源的实用工具类。它有多种数据源的实现,可以在JavaEE容器外部测试JDBC代码。
3)object
即对象包,以面向对象的方式访问数据库。它允许执行查询并返回结果作为业务对象。它可以在数据表的列和业务对象的属性之间映射查询结果。
4)support
即支持包,是core包和object包的支持类。例如提供了异常转换功能的SQLException类。

二、配置
下面我们以MySQL数据库为例,开始简单的数据源配置:

  1. @Configuration
  2. @ComponentScan("com.ch.myalbumjdbc")
  3. public class SpringJdbcConfig {
  4. @Bean
  5. public DataSource mysqlDataSource() {
  6. DriverManagerDataSource dataSource = new DriverManagerDataSource();
  7. dataSource.setDriverClassName("com.mysql.jdbc.Driver");
  8. dataSource.setUrl("jdbc:mysql://localhost:3306/springjdbc");
  9. dataSource.setUsername("guest_user");
  10. dataSource.setPassword("guest_password");
  11. return dataSource;
  12. }
  13. }

或者,您还可以利用嵌入式数据库进行开发或测试,比如用HSQL嵌入式数据库进行快速配置并创建实例:

  1. @Bean
  2. public DataSource dataSource() {
  3. return new EmbeddedDatabaseBuilder()
  4. .setType(EmbeddedDatabaseType.HSQL)
  5. .addScript("classpath:jdbc/schema.sql")
  6. .addScript("classpath:jdbc/test-data.sql").build();
  7. }

最后,也可以使用XML配置来实现前面的注释配置的效果:

  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
  2. destroy-method="close">
  3. <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  4. <property name="url" value="jdbc:mysql://localhost:3306/springjdbc"/>
  5. <property name="username" value="guest_user"/>
  6. <property name="password" value="guest_password"/>
  7. </bean>

三、JdbcTemplate的使用和运行查询
1、基本的查询
JDBC模板是Spring JDBC模块中主要的API,它提供了常见的数据库访问功能:

  1. int result = jdbcTemplate.queryForObject(
  2. "SELECT COUNT(*) FROM EMPLOYEE", Integer.class);

下面是简单的插入功能:

  1. public int addEmplyee(int id) {
  2. return jdbcTemplate.update(
  3. "INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)", 5, "Bill", "Gates", "USA");
  4. }

注意提供参数的标准语法——使用“?”字符。下面,让我们看看替代语法。

2、查询与命名参数
要获得命名参数的支持,我们需要使用Spring JDBC提供的其它JDBC模板——NamedParameterJdbcTemplate。
此类封装了JbdcTemplate,并提供了使用“?”来替代指定参数的传统语法。它使用传递的参数来替换占位符“?”,以执行传参的查询:

  1. SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("id", 1);
  2. return namedParameterJdbcTemplate.queryForObject(
  3. "SELECT FIRST_NAME FROM EMPLOYEE WHERE ID = :id", namedParameters, String.class);

请注意,我们使用的是MapSqlParameterSource来提供值的命名参数。
下面是使用bean类的属性来确定命名参数简单例子:

  1. Employee employee = new Employee();
  2. employee.setFirstName("James");
  3. String SELECT_BY_ID = "SELECT COUNT(*) FROM EMPLOYEE WHERE FIRST_NAME = :firstName";
  4. SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(employee);
  5. return namedParameterJdbcTemplate.queryForObject(SELECT_BY_ID, namedParameters, Integer.class);

请注意,我们是怎样利用BeanPropertySqlParameterSource的实现来替代指定的命名参数。

3、把查询结果映射到Java对象
还有一个非常有用的功能是把查询结果映射到Java对象——通过实现RowMapper接口。
例如,对于查询返回的每一行结果,Spring会使用该行映射来填充Java bean:

  1. public class EmployeeRowMapper implements RowMapper<Employee> {
  2. @Override
  3. public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
  4. Employee employee = new Employee();
  5. employee.setId(rs.getInt("ID"));
  6. employee.setFirstName(rs.getString("FIRST_NAME"));
  7. employee.setLastName(rs.getString("LAST_NAME"));
  8. employee.setAddress(rs.getString("ADDRESS"));
  9. return employee;
  10. }
  11. }

现在,我们传递行映射器给查询API,并得到完全填充好的Java对象:

  1. String query = "SELECT * FROM EMPLOYEE WHERE ID = ?";
  2. List<Employee> employees = jdbcTemplate.queryForObject(
  3. query, new Object[] { id }, new EmployeeRowMapper());

四、异常转换
Spring提供了自己的开箱即用的数据异常分层——DataAccessException作为根异常,它负责转换所有的原始异常。
所以开发者无需处理底层的持久化异常,因为Spring JDBC模块已经在DataAccessException类及其子类中封装了底层的异常。
这样可以使异常处理机制独立于当前使用的具体数据库。
除了默认的SQLErrorCodeSQLExceptionTranslator类,开发者也可以提供自己的SQLExceptionTranslator实现。
下面是一个自定义SQLExceptionTranslator实现的简单例子,当出现完整性约束错误时自定义错误消息:

  1. public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTranslator {
  2. @Override
  3. protected DataAccessException customTranslate
  4. (String task, String sql, SQLException sqlException) {
  5. if (sqlException.getErrorCode() == -104) {
  6. return new DuplicateKeyException(
  7. "Custom Exception translator - Integrity constraint violation.", sqlException);
  8. }
  9. return null;
  10. }
  11. }

要使用自定义的异常转换器,我们需要把它传递给JdbcTemplate——通过callingsetExceptionTranslator()方法:

  1. CustomSQLErrorCodeTranslator customSQLErrorCodeTranslator = new CustomSQLErrorCodeTranslator();
  2. jdbcTemplate.setExceptionTranslator(customSQLErrorCodeTranslator);

五、使用SimpleJdbc类实现JDBC操作
SimpleJdbc类提供简单的方法来配置和执行SQL语句。这些类使用数据库的元数据来构建基本的查询。 SimpleJdbcInsert类和SimpleJdbcCall类提供了更简单的方式来执行插入和存储过程的调用。
1、SimpleJdbcInsert类
下面,让我们来看看执行简单的插入语句的最低配置,基于SimpleJdbcInsert类的配置产生的INSERT语句。
所有您需要提供的是:表名、列名和值。让我们先创建SimpleJdbcInsert:

  1. SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("EMPLOYEE");

现在,让我们提供列名和值,并执行操作:

  1. public int addEmplyee(Employee emp) {
  2. Map<String, Object> parameters = new HashMap<String, Object>();
  3. parameters.put("ID", emp.getId());
  4. parameters.put("FIRST_NAME", emp.getFirstName());
  5. parameters.put("LAST_NAME", emp.getLastName());
  6. parameters.put("ADDRESS", emp.getAddress());
  7. return simpleJdbcInsert.execute(parameters);
  8. }

为了让数据库生成主键,我们可以使用executeAndReturnKey() API,我们还需要配置的实际自动生成的列:

  1. SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
  2. .withTableName("EMPLOYEE")
  3. .usingGeneratedKeyColumns("ID");
  4. Number id = simpleJdbcInsert.executeAndReturnKey(parameters);
  5. System.out.println("Generated id - " + id.longValue());

最后,我们还能使用BeanPropertySqlParameterSource和MapSqlParameterSource传递数据。

2、用SimpleJdbcCall调用存储过程
让我们看看如何执行存储过程——我们使用SimpleJdbcCall的抽象:

  1. SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)
  2. .withProcedureName("READ_EMPLOYEE");
  3. public Employee getEmployeeUsingSimpleJdbcCall(int id) {
  4. SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);
  5. Map<String, Object> out = simpleJdbcCall.execute(in);
  6. Employee emp = new Employee();
  7. emp.setFirstName((String) out.get("FIRST_NAME"));
  8. emp.setLastName((String) out.get("LAST_NAME"));
  9. return emp;
  10. }

六、批处理操作
另一个简单的用例——把多种操作合在一起实现批处理
1、使用JdbcTemplate执行基本的批处理操作
使用JdbcTemplate类,通过batchUpdate() API来执行基本的批处理操作:
注意BatchPreparedStatementSetter实现是很有趣的。

  1. public int[] batchUpdateUsingJdbcTemplate(List<Employee> employees) {
  2. return jdbcTemplate.batchUpdate("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)",
  3. new BatchPreparedStatementSetter() {
  4. @Override
  5. public void setValues(PreparedStatement ps, int i) throws SQLException {
  6. ps.setInt(1, employees.get(i).getId());
  7. ps.setString(2, employees.get(i).getFirstName());
  8. ps.setString(3, employees.get(i).getLastName());
  9. ps.setString(4, employees.get(i).getAddress();
  10. }
  11. @Override
  12. public int getBatchSize() {
  13. return 50;
  14. }
  15. });
  16. }

2、使用NamedParameterJdbcTemplate执行批处理操作
对于批处理操作,还可以选择使用NamedParameterJdbcTemplate的batchUpdate() API来执行。
此API比先前的更简单——无需实现任何额外的接口来设置参数,因为它有一个内部的预准备语句的setter来传递预设的参数值。
参数值可以通过batchUpdate()方法传递给SqlParameterSource的数组。

  1. SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(employees.toArray());
  2. int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(
  3. "INSERT INTO EMPLOYEE VALUES (:id, :firstName, :lastName, :address)", batch);
  4. return updateCounts;

七、结论
本文讲述了Spring框架中的JDBC抽象,覆盖了Spring JDBC模块内建的各种功能和实际的例子。

Spring JDBC的更多相关文章

  1. spring jdbc 查询结果返回对象、对象列表

    首先,需要了解spring jdbc查询时,有三种回调方式来处理查询的结果集.可以参考 使用spring的JdbcTemplate进行查询的三种回调方式的比较,写得还不错. 1.返回对象(queryF ...

  2. spring jdbc获取插入记录的主键id

    在JDBC3.0规范中,当新增记录时,允许将数据库自动产生的主键值绑定到Statement或PreparedStatement中.使用Statement时,可以通过以下方法绑定主键值: int exe ...

  3. Spring JDBC实现查询

    1 db.properties jdbc.user=root jdbc.password=920614 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbc ...

  4. Spring学习进阶(四) Spring JDBC

    Spring JDBC是Spring所提供的持久层技术.主要目的是降低使用JDBC API的门槛,以一种更直接,更简洁的方式使用JDBC API.在Spring JDBC里用户仅需要做哪些比不可少的事 ...

  5. Spring JDBC常用方法详细示例

    Spring JDBC使用简单,代码简洁明了,非常适合快速开发的小型项目.下面对开发中常用的增删改查等方法逐一示例说明使用方法 1 环境准备 启动MySQL, 创建一个名为test的数据库 创建Mav ...

  6. Spring JDBC 访问MSSQL

    在Spring中对底层的JDBC做了浅层的封装即JdbcTemplate,在访问数据库的DAO层完全可以使用JdbcTemplate完成任何数据访问的操作,接下来我们重点说说Spring JDBC对S ...

  7. Spring JDBC主从数据库配置

    通过昨天学习的自定义配置注释的知识,探索了解一下web主从数据库的配置: 背景:主从数据库:主要是数据上的读写分离: 数据库的读写分离的好处? 1. 将读操作和写操作分离到不同的数据库上,避免主服务器 ...

  8. Spring笔记——Spring+JDBC组合开发

      使用Spring+JDBC集成步骤如下:   1. 配置数据源 2. 配置事务.配置事务时,需要在xml配置文件中引入用于声明事务的tx命名空间,事务的配置方式有两种:注解方式和基于XML配置方式 ...

  9. Spring入门(10)-Spring JDBC

    Spring入门(10)-Spring JDBC 0. 目录 JdbcTemplate介绍 JdbcTemplate常见方法 代码示例 参考资料 1. JdbcTemplate介绍 JdbcTempl ...

随机推荐

  1. java中final 、finally、finalize的区别

    比较java中常用关键字以免混淆 final :用来修饰变量,表示变量为最终变量,不能被改变 finally:在处理异常的时候使用,表示最终要执行的代码块 finalize:java Object类中 ...

  2. (Array,位操作)137. Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  3. 【转】HTML5 jQuery图片上传前预览

    hTML5实现表单内的上传文件框,上传前预览图片,针刷新预览images,本例子主要是使用HTML5 的File API,建立一個可存取到该 file的url,一个空的img标签,ID为img0,把选 ...

  4. TFS 自动同步Server 端文件的批处理命令

    TFS 自动同步Server 端文件的批处理命令 目前在我们组的工作中很多时候需要将TFS上Server端的代码自动无人值守的同步到本地中来, 找到了一些解决方案的资料http://bbs.scmro ...

  5. JS数组push会覆盖前面的数据问题

    这是一个作用域和重新赋值的问题. 检查声明数组所在位置,特别在是多层嵌套中,检查是否在内层循环结束时 跳到外层循环就重新将 数组 赋值为空.

  6. HTML5移动端图片上传模块

    上传图片的功能是极为常用的,之前做过一个移动端上传文件的功能(基于jquery的),总结梳理一下. html <div class="uploadPic clearBox"& ...

  7. 简单三个表之间关联 与 case when语句的应用

    select p.conttract_id,l.order_code,jz.cur_branch from wy_auto_workflow_log l,wg_pjhsb p,wg_jzmb jz w ...

  8. 使用Maven来写j2ee项目

    第一步:使用Maven创建web项目 是不是很简单? 第二步 问题 很多人,创建好后是没有src/main/java的源文件的,解决办法: 1.直接new ResourceFloder,src/mai ...

  9. 设置MYECLIPSE的自动补全

    http://jingyan.baidu.com/article/d169e1869caf1e436611d8db.html

  10. for..in遍历,枚举器

    #pragma mark ------------for循环遍历集合中的元素------ //创建一个数组,包含5个字符串对象,倒序取出数组中的所有元素,并存储到另一可变数组中 NSArray *ar ...