博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring JDBC详解
阅读量:6321 次
发布时间:2019-06-22

本文共 7051 字,大约阅读时间需要 23 分钟。

《Spring JDBC详解》

本文旨在讲述Spring JDBC模块的用法。Spring JDBC模块是Spring框架的基础模块之一。

一、概述

在Spring JDBC模块中,所有的类可以被分到四个单独的包:

1)core

即核心包,它包含了JDBC的核心功能。此包内有很多重要的类,包括:JdbcTemplate类、SimpleJdbcInsert类,SimpleJdbcCall类,以及NamedParameterJdbcTemplate类。

2)datasource

即数据源包,访问数据源的实用工具类。它有多种数据源的实现,可以在JavaEE容器外部测试JDBC代码。

3)object

即对象包,以面向对象的方式访问数据库。它允许执行查询并返回结果作为业务对象。它可以在数据表的列和业务对象的属性之间映射查询结果。

4)support

即支持包,是core包和object包的支持类。例如提供了异常转换功能的SQLException类。


二、配置

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

@Configuration@ComponentScan("com.ch.myalbumjdbc")public class SpringJdbcConfig {    @Bean    public DataSource mysqlDataSource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName("com.mysql.jdbc.Driver");        dataSource.setUrl("jdbc:mysql://localhost:3306/springjdbc");        dataSource.setUsername("guest_user");        dataSource.setPassword("guest_password");        return dataSource;    }}

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

@Beanpublic DataSource dataSource() {    return new EmbeddedDatabaseBuilder()        .setType(EmbeddedDatabaseType.HSQL)        .addScript("classpath:jdbc/schema.sql")        .addScript("classpath:jdbc/test-data.sql").build();}

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

 

三、JdbcTemplate的使用和运行查询
1、基本的查询
JDBC模板是Spring JDBC模块中主要的API,它提供了常见的数据库访问功能:
int result = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class);

下面是简单的插入功能:

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

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


2、查询与命名参数

要获得命名参数的支持,我们需要使用Spring JDBC提供的其它JDBC模板——NamedParameterJdbcTemplate。

此类封装了JbdcTemplate,并提供了使用“?”来替代指定参数的传统语法。它使用传递的参数来替换占位符“?”,以执行传参的查询:

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

请注意,我们使用的是MapSqlParameterSource来提供值的命名参数。

下面是使用bean类的属性来确定命名参数简单例子:

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

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


3、把查询结果映射到Java对象

还有一个非常有用的功能是把查询结果映射到Java对象——通过实现RowMapper接口。

例如,对于查询返回的每一行结果,Spring会使用该行映射来填充Java bean:

public class EmployeeRowMapper implements RowMapper {    @Override    public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {        Employee employee = new Employee();        employee.setId(rs.getInt("ID"));        employee.setFirstName(rs.getString("FIRST_NAME"));        employee.setLastName(rs.getString("LAST_NAME"));        employee.setAddress(rs.getString("ADDRESS"));        return employee;    }}

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

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

四、异常转换

Spring提供了自己的开箱即用的数据异常分层——DataAccessException作为根异常,它负责转换所有的原始异常。

所以开发者无需处理底层的持久化异常,因为Spring JDBC模块已经在DataAccessException类及其子类中封装了底层的异常。

这样可以使异常处理机制独立于当前使用的具体数据库。

除了默认的SQLErrorCodeSQLExceptionTranslator类,开发者也可以提供自己的SQLExceptionTranslator实现。

下面是一个自定义SQLExceptionTranslator实现的简单例子,当出现完整性约束错误时自定义错误消息:

public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTranslator {    @Override    protected DataAccessException customTranslate      (String task, String sql, SQLException sqlException) {        if (sqlException.getErrorCode() == -104) {            return new DuplicateKeyException(                "Custom Exception translator - Integrity constraint violation.", sqlException);        }        return null;    }}

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

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

五、使用SimpleJdbc类实现JDBC操作

SimpleJdbc类提供简单的方法来配置和执行SQL语句。这些类使用数据库的元数据来构建基本的查询。 SimpleJdbcInsert类和SimpleJdbcCall类提供了更简单的方式来执行插入和存储过程的调用。

1、SimpleJdbcInsert类

下面,让我们来看看执行简单的插入语句的最低配置,基于SimpleJdbcInsert类的配置产生的INSERT语句。

所有您需要提供的是:表名、列名和值。让我们先创建SimpleJdbcInsert:

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

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

public int addEmplyee(Employee emp) {    Map parameters = new HashMap();    parameters.put("ID", emp.getId());    parameters.put("FIRST_NAME", emp.getFirstName());    parameters.put("LAST_NAME", emp.getLastName());    parameters.put("ADDRESS", emp.getAddress());    return simpleJdbcInsert.execute(parameters);}

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

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

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


2、用SimpleJdbcCall调用存储过程

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

SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)		                     .withProcedureName("READ_EMPLOYEE");public Employee getEmployeeUsingSimpleJdbcCall(int id) {    SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);    Map out = simpleJdbcCall.execute(in);    Employee emp = new Employee();    emp.setFirstName((String) out.get("FIRST_NAME"));    emp.setLastName((String) out.get("LAST_NAME"));    return emp;}

六、批处理操作

另一个简单的用例——把多种操作合在一起实现批处理

1、使用JdbcTemplate执行基本的批处理操作

使用JdbcTemplate类,通过batchUpdate() API来执行基本的批处理操作:

注意BatchPreparedStatementSetter实现是很有趣的。

public int[] batchUpdateUsingJdbcTemplate(List employees) {    return jdbcTemplate.batchUpdate("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)",        new BatchPreparedStatementSetter() {            @Override            public void setValues(PreparedStatement ps, int i) throws SQLException {                ps.setInt(1, employees.get(i).getId());                ps.setString(2, employees.get(i).getFirstName());                ps.setString(3, employees.get(i).getLastName());                ps.setString(4, employees.get(i).getAddress();            }            @Override            public int getBatchSize() {                return 50;            }        });}

2、使用NamedParameterJdbcTemplate执行批处理操作

对于批处理操作,还可以选择使用NamedParameterJdbcTemplate的batchUpdate() API来执行。

此API比先前的更简单——无需实现任何额外的接口来设置参数,因为它有一个内部的预准备语句的setter来传递预设的参数值。

参数值可以通过batchUpdate()方法传递给SqlParameterSource的数组。

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

七、结论

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

转载地址:http://ibtaa.baihongyu.com/

你可能感兴趣的文章
统计数字
查看>>
卷积神经网络LeNet Convolutional Neural Networks (LeNet)
查看>>
CSS浮动属性Float到底什么怎么回事,下面详细解释一下
查看>>
06hibernate_one2one_pk_2(you can forget)
查看>>
Lucene学习总结之一:全文检索的基本原理
查看>>
jeasyui 造成$.data(...) is undefined报错的原因及解决
查看>>
谷歌浏览器javascript调试教程
查看>>
BugFree的7种解决方案各自的含义是什么?
查看>>
基于Predictive Parsing的ABNF语法分析器(3)——ABNF语法解析器的基本框架
查看>>
【学习opencv第七篇】图像的阈值化
查看>>
protobuf中的编码规则
查看>>
微信公众帐号开发教程第7篇-各种消息的接收与响应------- 此项目的源码在文章的末尾...
查看>>
Windows Phone 开发——相机功能开发
查看>>
【TYVJ】1467 - 通向聚会的道路(spfa+特殊的技巧)
查看>>
eclipse的使用
查看>>
Codeforces Round #221 (Div. 1) B. Maximum Submatrix 2 dp排序
查看>>
持久化API(JPA)系列(三)实体Bean的开发技术-建立与数据库的连接
查看>>
SpringMVC 理论与有用技术(一) 简单、有用、易懂的几个实例
查看>>
网上书城+源码
查看>>
HTML5使用Div标签来实现表格
查看>>