004Spring事务001JdbcTemplate
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相关推荐
- Redis 笔记(08)— 事务(一次执行多条命令、命令 watch/multi/exec/discard、错误处理)
1. 事务概念 Redis 中的事务 (transaction)是一组命令的集合.事务同命令一样是 Redis 的最小执行单位,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的 ...
- etcd 笔记(06)— Client 结构定义、客户端(初始化、KV存储Get、Put、事务 Txn、压缩 Compact、Watch、Lease
1. Client 定义 Client 定义如下: type Client struct {ClusterKVLeaseWatcherAuthMaintenance// 认证的用户名Username ...
- Redis 高级特性(1)—— 事务 过期时间 排序
1. Redis 高级特性 -- 事务 事务概念 Redis 中的事务 (transaction)是一组命令的集合.事务同命令一样是 Redis 的最小执行单位,一个事务中的命令要么都执行,要么都不执 ...
- 【spring】编程式事务控制
结构: AccountServiceImpl package com.itheima.service.impl;import com.itheima.dao.IAccountDao; import c ...
- 【Spring】spring基于纯注解的声明式事务控制
结构 去掉bean.xml config JdbcConfig package com.itheima.config;import org.springframework.beans.factory. ...
- 【Spring】spring基于注解的声明式事务控制
结构 domin package com.itheima.domain;import java.io.Serializable;public class Account implements Seri ...
- 【spring】spring基于xml的声明式事务控制
结构 domain package com.itheima.domain;import java.io.Serializable;public class Account implements Ser ...
- 【Spring】事务控制API
Spring事务控制需要明确 1. JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计==业务层==的事务处理解决方案. 2. Spring框架提供了一组事务控制的接口.在S ...
- 【Spring】基于xml实现事务控制(银行转账)
代码结构 domain类 package com.itheima.domain;import java.io.Serializable;/*** 账户的实体类*/ public class Accou ...
- 【Spring】通过动态代理改进银行转账事务控制
前情 银行转账的案例中,通过给业务层实现类中每个方法中通过事务控制方法添加事务控制,保证每个方法在执行时只有一个数据库连接,通过事务保证整个方法要成功全部成功,要失败都失败. 问题 业务层实现类添加事 ...
最新文章
- 利用Python让你的命令行像坤坤一样会打篮球
- Fabric--启动网络自动
- php sqlserver jdbc,jdbc sqlserver 分页
- Premiere Pro CC2017教程(二) 修改导入静态图片的时间
- echart 动画 饼图_echarts构建关系图,节点可收缩和展开,可添加点击事件
- 将字符串中的小写字母转换成大写字母 (信息学奥赛一本通-T1138)
- webstorm怎么跑项目_看不懂代码,不会用框架,新手程序员入职后如何快速上手项目?...
- Arduino采集Microzone遥控器信号(ROSMicrozoneBridge)
- python背包问题递归_想问下大神python的背包问题的源代码(最好玩也有伪代码,请用递归法实现),因为只学过递归法,所...
- MySQL online create index实现原理
- Junit4测试报错:java.lang.NoClassDefFoundError: org/junit/runner/manipulation/Filter
- 计算机应用基础学生指导评语,计算机应用基础评课稿范本
- 用acdsee制作html,应用文论文写作 - - 计算机 - 计算机网络 - ACDSee的HTML相册生成...
- 图片无损放大器有什么软件推荐?这个不要错过
- WPS无法用backspace删除空白页怎么办?
- Hibernate的一对一,一对多/多对一关联保存
- 测试结果OK、NG、NT、POK的意思
- thinkPHP集成workman扩展
- 在Linux环境下怎么编译Android源码?
- 表单二维码怎么做?二维码怎么统计信息?
热门文章
- 6个实用的 Python 自动化脚本,告别加班,你学会了吗?
- 子域名劫持漏洞详解、挖掘和防护
- 日本知名汽车零部件公司巡礼系列之株式会社70
- 实现圣杯布局的三种方式
- 使用Python发送邮件(图片、表格、附件) 系列二: 同时发送图片和附件实际案例
- 区块链Baas应用服务平台开发搭建
- 用Python多线程抓取并验证代理(转)
- 【原创】/Restarting/ Splay树 (普通平衡树 文艺平衡树 bzoj1895 poj 2580 SuperMemo 题解)
- 同时虚拟多个3D桌面
- 【新手案例】Python3.7如何获取网络时间