1 概述

1.1 简介

为了使JDBC更加易于使用,Spring在JDBC的API上定义了一个抽象层,以此建立一个JDBC存取框架。

JdbcTemplate类对可变部分采用CallBack回调接口方式实现,在CallBack接口实现类的Connection处于自动提交状态,在CallBack接口实现类的方法中不能进行事物管理。

1.2 目的

JDBC模板的设计目的是为不同类型的JDBC操作提供模板方法,通过这种方式,可以在尽可能保留灵活性的情况下,将数据库存取的工作量降到最低。

可以将Spring的JdbcTemplate看作是一个小型的轻量级持久化层框架,和DBUtils的风格非常接近。

2 导包

2.1 IOC容器需要的包

commons-logging-1.1.1.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar

2.2 AOP需要的包

spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar

2.3 JdbcTemplate需要的包

spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar

2.4 数据库驱动和数据源需要的包

c3p0-0.9.1.2.jar
mysql-connector-java-5.1.7-bin.jar

3 使用

3.1 数据库连接信息属性文件

在类路径下创建jdbc.properties文件。

user=root
password=root
jdbcUrl=jdbc:mysql:///query_data
driverClass=com.mysql.jdbc.Driver
initialPoolSize=30
minPoolSize=10
maxPoolSize=100
acquireIncrement=5
maxStatements=1000
maxStatementsPerConnection=10

3.2 配置XML文件

将数据库连接属性文件引入到XML文件中,并注册数据源Bean,使用SpEL表达式将外部文件中的配置信息赋值给数据源Bean。

还需要注册一个Spring框架中JDBC的核心组件JdbcTemplate的Bean,并设置dataSource属性引用数据源Bean。

<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="user" value="${user}"/><property name="password" value="${password}"/><property name="jdbcUrl" value="${jdbcUrl}"/><property name="driverClass" value="${driverClass}"/><property name="initialPoolSize" value="${initialPoolSize}"/><property name="minPoolSize" value="${minPoolSize}"/><property name="maxPoolSize" value="${maxPoolSize}"/><property name="acquireIncrement" value="${acquireIncrement}"/><property name="maxStatements" value="${maxStatements}"/><property name="maxStatementsPerConnection" value="${maxStatementsPerConnection}"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><constructor-arg ref="comboPooledDataSource" />
</bean>

3.3 获取JdbcTemplate组件

获取到组件之后就可以进行增删改查操作了。

public class JdbcTemplateTest {ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");@Testpublic void test() throws Exception {// 获取容器的JdbcTemplate组件。JdbcTemplate jdbcTemplate = (JdbcTemplate) ioc.getBean(JdbcTemplate.class);}
}

4 详细说明

4.1 回调类

4.1.1 预编译语句创建回调及存储过程创建回调

用于根据JdbcTemplate提供的Connection创建语句。

PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建PreparedStatement。
CallableStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建CallableStatement。

4.1.2 预编译语句设值回调

用于给预编译语句的参数设值。

PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由用户来给预编译语句的参数设值。
BatchPreparedStatementSetter:类似于PreparedStatementSetter,但用于批处理,需要指定批处理大小。

4.1.3 自定义功能回调

提供给用户一个扩展点,用户可以在指定类型的扩展点执行需要的操作,包括将预设值参数设置到预编译语句中。

ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,用户可在该Connection执行操作。
StatementCallback:通过回调获取JdbcTemplate提供的Statement,用户可以在该Statement执行操作。
PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,用户可以在该PreparedStatement执行操作。
CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,用户可以在该CallableStatement执行操作。

4.1.4 结果集处理回调

通过回调处理ResultSet或将ResultSet转换为需要的形式。

RowMapper:用于封装结果集数据到指定类型,需要重写mapRow方法,每次封装一行数据,无需执行rs.next()。
RowCallbackHandler:用于处理结果集数据而无需保存到内存,需重写processRow方法,每次处理一行数据,无需执行rs.next()。
ResultSetExtractor:用于结果集数据提取,需要重写extractData方法,一次处理整个结果集,需要执行rs.next()。

4.2 主要方法

4.2.1 增加、删除、修改

执行一条语句:

// int update(String sql, Object... args);
String sql = "update bs_book set title=? where id=?";
jdbcTemplate.update(sql, "新书", 10);

执行一条语句并返回自增主键:

// int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder);
String sql = "insert into bs_book(title, author) values(?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {@Overridepublic PreparedStatement createPreparedStatement(Connection con)throws SQLException {PreparedStatement prepareStatement = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);prepareStatement.setString(1, "平凡的世界");prepareStatement.setString(2, "路遥");return prepareStatement;}
}, keyHolder);
System.out.println("id=" + keyHolder.getKey().intValue());

批量执行多条语句:

// int[] batchUpdate(String sql, List<Object[]> batchArgs);
String sql = "insert into bs_book(title, author) values(?, ?)";
List<Object[]> books = new ArrayList<Object[]>();
books.add(new Object[]{"梦里花落知多少", "三毛"});
books.add(new Object[]{"雨季不再来", "三毛"});
int[] counts = jdbcTemplate.batchUpdate(sql, books);
for (int i : counts) {System.out.println("count=" + i);
}

4.2.2 查询

查询一条数据并封装到基本类型中返回:

// <T> T queryForObject(String sql, Class<T> requiredType, Object... args);
String sql = "select count(id) from bs_book where author=?";
int count = jdbcTemplate.queryForObject(sql, Integer.class, "三毛");
System.out.println("count=" + count);

查询一条数据并封装到指定类型中返回:

// <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args);
String sql = "select * from bs_book where id=?";
Book book = jdbcTemplate.queryForObject(sql, new RowMapper<Book>() {@Overridepublic Book mapRow(ResultSet rs, int rowNum) throws SQLException {System.out.println("rowNum=" + rowNum);Book book = new Book();book.setId(rs.getInt("id"));book.setTitle(rs.getString("title"));book.setAuthor(rs.getString("author"));return book;}
}, "10");
// 也可以使用RowMapper的实现类BeanPropertyRowMapper来自动封装结果。
// Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), "10");
System.out.println("book=" + book);

查询一条数据并封装到Map中返回:

// Map<String,Object> queryForMap(String sql, Object... args);
String sql = "select * from bs_book where id=?";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 10);
map.forEach((key, value) -> System.out.println(key + "=" + value));

查询多条数据并封装到基本类型中最后以List类型返回:

// <T> List<T> queryForList(String sql, Class<T> elementType, Object... args);
String sql = "select title from bs_book where id<?";
List<String> list = jdbcTemplate.queryForList(sql, String.class, 10);
list.forEach(title -> System.out.println(title));

查询多条数据并封装到Map中最后以List类型返回:

// List<Map<String,Object>> queryForList(String sql, Object... args);
String sql = "select title, author from bs_book where id<?";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 10);
list.forEach(map -> System.out.println(map));

查询多条数据并封装到指定类型中最后以List类型返回:

// <T> List<T>query(String sql, RowMapper<T> rowMapper, Object... args);
String sql = "select * from bs_book where id<?";
List<Book> books = jdbcTemplate.query(sql, new RowMapper<Book>(){@Overridepublic Book mapRow(ResultSet rs, int rowNum) throws SQLException {Book book = new Book();book.setId(rs.getInt("id"));book.setTitle(rs.getString("title"));book.setAuthor(rs.getString("author"));return book;}
}, 10);
//也可以使用RowMapper的实现类BeanPropertyRowMapper来自动封装结果。
// List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Book.class), 10);
books.forEach(book -> System.out.println(book));

查询多条数据并封装到指定类型中最后以自定义类型返回:

// <T> T query(String sql, ResultSetExtractor<T> rse, Object... args);
String sql = "select * from bs_book where id<?";
Book book = jdbcTemplate.query(sql, new ResultSetExtractor<Book>() {@Overridepublic Book extractData(ResultSet rs) throws SQLException,DataAccessException {Book book = new Book();while (rs.next()) {book.setId(rs.getInt("id"));book.setTitle(rs.getString("title"));book.setAuthor(rs.getString("author"));if ("百年孤独".equals(book.getTitle())) {break;}}return book;}
}, 10);

查询多条数据并封装到指定类型中处理最后不返回:

// void query(String sql, RowCallbackHandler rch, Object... args);
String sql = "select * from bs_book where id<?";
jdbcTemplate.query(sql, new RowCallbackHandler() {@Overridepublic void processRow(ResultSet rs) throws SQLException {Book book = new Book();book.setId(rs.getInt("id"));book.setTitle(rs.getString("title"));book.setAuthor(rs.getString("author"));System.out.println(book);}
}, 10);

5 使用具名参数

5.1 关于具名参数

相对于基于位置的参数,具名参数具有更好的可维护性,在SQL语句中参数较多时可以考虑使用具名参数。

在Spring中可以通过NamedParameterJdbcTemplate类的对象使用带有具名参数的SQL语句。

5.2 通过IOC容器创建NamedParameterJdbcTemplate对象

NamedParameterJdbcTemplate类没有提供无参的构造器,不能使用属性方式只能通过构造器方式创建Bean。

<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"><constructor-arg ref="comboPooledDataSource" />
</bean>

5.3 获取IOC容器的NamedParameterJdbcTemplate对象

NamedParameterJdbcTemplate namedParameterJdbcTemplate = ioc.getBean(NamedParameterJdbcTemplate.class);

5.4 具名参数在SQL语句中的格式

可以在SQL语句中使用“:属性名”的方式进行参数传递。

INSERT INTO depts (id, name) VALUES (:id, :name)

5.5 具名参数传入并执行

5.5.1 使用Map

通过Map对象传入,Map的键是参数名,值是参数值。

// NamedParameterJdbcTemplate.update(String sql, Map<String, ?> paramMap);
public void test() {String sql = "insert into employee(id, name) values(:id, :name)";HashMap<String, Object> map = new HashMap<>();map.put("id", 100);map.put("name", "Tom");namedParameterJdbcTemplate.update(sql, map);
}

5.5.2 使用SqlParameterSource

通过SqlParameterSource对象传入,使用该接口下的BeanPropertySqlParameterSource的实例。

// NamedParameterJdbcTemplate.update(String sql, SqlParameterSource paramSource);
public void test() {String sql = "insert into employee(id, name) values(:id, :name)";Employee employee = new Employee(100, "Sam");int update = namedParameterJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(employee));System.out.println(update);
}

004Spring事务001JdbcTemplate相关推荐

  1. Redis 笔记(08)— 事务(一次执行多条命令、命令 watch/multi/exec/discard、错误处理)

    1. 事务概念 Redis 中的事务 (transaction)是一组命令的集合.事务同命令一样是 Redis 的最小执行单位,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的 ...

  2. etcd 笔记(06)— Client 结构定义、客户端(初始化、KV存储Get、Put、事务 Txn、压缩 Compact、Watch、Lease

    1. Client 定义 Client 定义如下: type Client struct {ClusterKVLeaseWatcherAuthMaintenance// 认证的用户名Username ...

  3. Redis 高级特性(1)—— 事务 过期时间 排序

    1. Redis 高级特性 -- 事务 事务概念 Redis 中的事务 (transaction)是一组命令的集合.事务同命令一样是 Redis 的最小执行单位,一个事务中的命令要么都执行,要么都不执 ...

  4. 【spring】编程式事务控制

    结构: AccountServiceImpl package com.itheima.service.impl;import com.itheima.dao.IAccountDao; import c ...

  5. 【Spring】spring基于纯注解的声明式事务控制

    结构 去掉bean.xml config JdbcConfig package com.itheima.config;import org.springframework.beans.factory. ...

  6. 【Spring】spring基于注解的声明式事务控制

    结构 domin package com.itheima.domain;import java.io.Serializable;public class Account implements Seri ...

  7. 【spring】spring基于xml的声明式事务控制

    结构 domain package com.itheima.domain;import java.io.Serializable;public class Account implements Ser ...

  8. 【Spring】事务控制API

    Spring事务控制需要明确 1. JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计==业务层==的事务处理解决方案. 2. Spring框架提供了一组事务控制的接口.在S ...

  9. 【Spring】基于xml实现事务控制(银行转账)

    代码结构 domain类 package com.itheima.domain;import java.io.Serializable;/*** 账户的实体类*/ public class Accou ...

  10. 【Spring】通过动态代理改进银行转账事务控制

    前情 银行转账的案例中,通过给业务层实现类中每个方法中通过事务控制方法添加事务控制,保证每个方法在执行时只有一个数据库连接,通过事务保证整个方法要成功全部成功,要失败都失败. 问题 业务层实现类添加事 ...

最新文章

  1. 利用Python让你的命令行像坤坤一样会打篮球
  2. Fabric--启动网络自动
  3. php sqlserver jdbc,jdbc sqlserver 分页
  4. Premiere Pro CC2017教程(二) 修改导入静态图片的时间
  5. echart 动画 饼图_echarts构建关系图,节点可收缩和展开,可添加点击事件
  6. 将字符串中的小写字母转换成大写字母 (信息学奥赛一本通-T1138)
  7. webstorm怎么跑项目_看不懂代码,不会用框架,新手程序员入职后如何快速上手项目?...
  8. Arduino采集Microzone遥控器信号(ROSMicrozoneBridge)
  9. python背包问题递归_想问下大神python的背包问题的源代码(最好玩也有伪代码,请用递归法实现),因为只学过递归法,所...
  10. MySQL online create index实现原理
  11. Junit4测试报错:java.lang.NoClassDefFoundError: org/junit/runner/manipulation/Filter
  12. 计算机应用基础学生指导评语,计算机应用基础评课稿范本
  13. 用acdsee制作html,应用文论文写作 - - 计算机 - 计算机网络 - ACDSee的HTML相册生成...
  14. 图片无损放大器有什么软件推荐?这个不要错过
  15. WPS无法用backspace删除空白页怎么办?
  16. Hibernate的一对一,一对多/多对一关联保存
  17. 测试结果OK、NG、NT、POK的意思
  18. thinkPHP集成workman扩展
  19. 在Linux环境下怎么编译Android源码?
  20. 表单二维码怎么做?二维码怎么统计信息?

热门文章

  1. 6个实用的 Python 自动化脚本,告别加班,你学会了吗?
  2. 子域名劫持漏洞详解、挖掘和防护
  3. 日本知名汽车零部件公司巡礼系列之株式会社70
  4. 实现圣杯布局的三种方式
  5. 使用Python发送邮件(图片、表格、附件) 系列二: 同时发送图片和附件实际案例
  6. 区块链Baas应用服务平台开发搭建
  7. 用Python多线程抓取并验证代理(转)
  8. 【原创】/Restarting/ Splay树 (普通平衡树 文艺平衡树 bzoj1895 poj 2580 SuperMemo 题解)
  9. 同时虚拟多个3D桌面
  10. 【新手案例】Python3.7如何获取网络时间