21JDBC_事务&JDBCTemplate
一、JDBC_事务
1.API介绍
void setAutoCommit(boolean autoCommit) throws SQLException;
false:开启事务, ture:关闭事务
void commit() throws SQLException;
提交事务
void rollback() throws SQLException;
回滚事务
void setAutoCommit(boolean autoCommit) throws SQLException;
false:开启事务, ture:关闭事务
void commit() throws SQLException;
提交事务
void rollback() throws SQLException;
回滚事务
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTransactionTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 1. 获取连接对象
conn = JDBCUtils.getConnection();
// 第一步 : 开启事务
conn.setAutoCommit(false);
// 2. 操作数据
// 2.1 账户转出
String outSql = "update account set money = money - ? where name = ?;";
stmt = conn.prepareStatement(outSql);
stmt.setInt(1, 1000);
stmt.setString(2, "tom");
stmt.executeUpdate();
// 模拟异常 ...
// int num = 10 / 0;
// 2.2 账户转入
String inSql = "update account set money = money + ? where name = ?;";
stmt = conn.prepareStatement(inSql);
stmt.setInt(1, 1000);
stmt.setString(2, "jery");
stmt.executeUpdate();
// 第二步 : 提交事务
conn.commit();
System.out.println("转账成功!");
} catch (Exception e) {
// 如果出现异常, 需要进行事务回滚.
// 第三步 : 回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("转账失败!");
} finally {
// 3. 释放资源
JDBCUtils.release(conn, stmt);
}
}
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTransactionTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement stmt = null;
try {
// 1. 获取连接对象
conn = JDBCUtils.getConnection();
// 第一步 : 开启事务
conn.setAutoCommit(false);
// 2. 操作数据
// 2.1 账户转出
String outSql = "update account set money = money - ? where name = ?;";
stmt = conn.prepareStatement(outSql);
stmt.setInt(1, 1000);
stmt.setString(2, "tom");
stmt.executeUpdate();
// 模拟异常 ...
// int num = 10 / 0;
// 2.2 账户转入
String inSql = "update account set money = money + ? where name = ?;";
stmt = conn.prepareStatement(inSql);
stmt.setInt(1, 1000);
stmt.setString(2, "jery");
stmt.executeUpdate();
// 第二步 : 提交事务
conn.commit();
System.out.println("转账成功!");
} catch (Exception e) {
// 如果出现异常, 需要进行事务回滚.
// 第三步 : 回滚事务
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("转账失败!");
} finally {
// 3. 释放资源
JDBCUtils.release(conn, stmt);
}
}
}
二、jdbcTemplate
1.API介绍
public JdbcTemplate(DataSource dataSource)
创建JdbcTemplate对象,方便执行SQL语句
public void execute(final String sql)
execute可以执行所有SQL语句,因为没有返回值,一般用于执行DML语句。
public JdbcTemplate(DataSource dataSource)
创建JdbcTemplate对象,方便执行SQL语句
public void execute(final String sql)
execute可以执行所有SQL语句,因为没有返回值,一般用于执行DML语句。
2.使用步骤
2. 导入依赖的jar包- spring-beans-5.0.2.RELEASE.jar- spring-core-5.0.2.RELEASE.jar- spring-jdbc-5.0.2.RELEASE.jar- spring-tx-5.0.2.RELEASE.jar- com.springsource.org.apache.commons.logging-1.1.1.jar3. 创建JdbcTemplate对象,传入c3p0连接池4. 调用execute、update、queryXxx等方法
3.案例
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,c3p0框架默认加载这段默认配置 -->
<default-config>
<!-- 配置JDBC 四个基本属性 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">111</property>
</default-config>
<!-- 可以自定义配置,为这段配置起一个名字,c3p0指定名称加载配置 -->
<named-config name="xxxxx">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">111</property>
</named-config>
</c3p0-config>
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,c3p0框架默认加载这段默认配置 -->
<default-config>
<!-- 配置JDBC 四个基本属性 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">111</property>
</default-config>
<!-- 可以自定义配置,为这段配置起一个名字,c3p0指定名称加载配置 -->
<named-config name="xxxxx">
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">111</property>
</named-config>
</c3p0-config>
public class JDBCUtils {
// 核心连接池类
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource() {
return dataSource;
}
// 获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 释放资源
public static void release(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
release(conn, stmt);
}
public static void release(Connection conn, Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
public class JDBCUtils {
// 核心连接池类
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
public static DataSource getDataSource() {
return dataSource;
}
// 获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 释放资源
public static void release(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
release(conn, stmt);
}
public static void release(Connection conn, Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
public class JDBCTemplateExecute {
public static void main(String[] args) {
// 1. 创建表的SQL语句
String sql = "create table product (" +
"pid int primary key auto_increment," +
"pname varchar(20)," +
"price double" +
");";
// 2. 创建 jdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 3. 使用 jdbcTemplate 对象调用 execute 方法, 执行 sql 语句, 创建数据库表.
jdbcTemplate.execute(sql);
}
}
public class JDBCTemplateExecute {
public static void main(String[] args) {
// 1. 创建表的SQL语句
String sql = "create table product (" +
"pid int primary key auto_increment," +
"pname varchar(20)," +
"price double" +
");";
// 2. 创建 jdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 3. 使用 jdbcTemplate 对象调用 execute 方法, 执行 sql 语句, 创建数据库表.
jdbcTemplate.execute(sql);
}
}
4通过jdbcTemplate实现增删改
// org.springframework.jdbc.core.JdbcTemplate类方便执行SQL语句
public int update(final String sql)
用于执行`INSERT`、`UPDATE`、`DELETE`等DML语句
// org.springframework.jdbc.core.JdbcTemplate类方便执行SQL语句
public int update(final String sql)
用于执行`INSERT`、`UPDATE`、`DELETE`等DML语句
@Test
public void insert() {
// 1. 创建一个 JdbcTemplate 对象, 并将连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 编写 sql 语句
String sql = "insert into product values(null, ?, ?);";
// 3. 执行 update 方法.
jdbcTemplate.update(sql, "iPhone3GS", 3333);
jdbcTemplate.update(sql, "iPhone4", 5000);
jdbcTemplate.update(sql, "iPhone4S", 5001);
jdbcTemplate.update(sql, "iPhone5", 5555);
jdbcTemplate.update(sql, "iPhone5C", 3888);
jdbcTemplate.update(sql, "iPhone5S", 5666);
jdbcTemplate.update(sql, "iPhone6", 6666);
jdbcTemplate.update(sql, "iPhone6S", 7000);
jdbcTemplate.update(sql, "iPhone6SP", 7777);
jdbcTemplate.update(sql, "iPhoneX", 8888);
}
@Test
public void insert() {
// 1. 创建一个 JdbcTemplate 对象, 并将连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 编写 sql 语句
String sql = "insert into product values(null, ?, ?);";
// 3. 执行 update 方法.
jdbcTemplate.update(sql, "iPhone3GS", 3333);
jdbcTemplate.update(sql, "iPhone4", 5000);
jdbcTemplate.update(sql, "iPhone4S", 5001);
jdbcTemplate.update(sql, "iPhone5", 5555);
jdbcTemplate.update(sql, "iPhone5C", 3888);
jdbcTemplate.update(sql, "iPhone5S", 5666);
jdbcTemplate.update(sql, "iPhone6", 6666);
jdbcTemplate.update(sql, "iPhone6S", 7000);
jdbcTemplate.update(sql, "iPhone6SP", 7777);
jdbcTemplate.update(sql, "iPhoneX", 8888);
}
@Test
public void update() {
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 update 语句
String sql = "update product set pname = ?, price = ? where pid = ?;";
int count = jdbcTemplate.update(sql, "XVIII", 18888, 10);
System.out.println("count = " + count);
}
@Test
public void update() {
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 update 语句
String sql = "update product set pname = ?, price = ? where pid = ?;";
int count = jdbcTemplate.update(sql, "XVIII", 18888, 10);
System.out.println("count = " + count);
}
@Test
public void delete() {
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 delete 操作
String sql = "delete from product where pid = ?;";
int count = jdbcTemplate.update(sql, 7);
System.out.println("count = " + count);
}
@Test
public void delete() {
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 delete 操作
String sql = "delete from product where pid = ?;";
int count = jdbcTemplate.update(sql, 7);
System.out.println("count = " + count);
}
小结:
5 jdbcTemplate实现查询
// 单行单列的查询
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args):
传入参数, 执行查询语句,返回一个指定类型的数据。
// 单行多列
public Map<String, Object> queryForMap(String sql, Object... args)
传入参数,执行查询语句,将一条记录放到一个Map中。
// 多行多列
public List<Map<String, Object>> queryForList(String sql, Object... args)
传入参数,执行查询语句,返回一个List集合,List中存放的是Map类型的数据。
// 返回一个List 存放对象数据
public <T> List<T> query(String sql, RowMapper<T> rowMapper)
执行查询语句,返回一个List集合,List中存放的是RowMapper指定类型的数据。
// 提供了一个上述方法的一个实现类 RowMapper 行映射接口 BeanPropertyRowMapper 实体类属性行映射
public class BeanPropertyRowMapper<T> implements RowMapper<T>
BeanPropertyRowMapper类实现了RowMapper接口
// 单行单列的查询
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args):
传入参数, 执行查询语句,返回一个指定类型的数据。
// 单行多列
public Map<String, Object> queryForMap(String sql, Object... args)
传入参数,执行查询语句,将一条记录放到一个Map中。
// 多行多列
public List<Map<String, Object>> queryForList(String sql, Object... args)
传入参数,执行查询语句,返回一个List集合,List中存放的是Map类型的数据。
// 返回一个List 存放对象数据
public <T> List<T> query(String sql, RowMapper<T> rowMapper)
执行查询语句,返回一个List集合,List中存放的是RowMapper指定类型的数据。
// 提供了一个上述方法的一个实现类 RowMapper 行映射接口 BeanPropertyRowMapper 实体类属性行映射
public class BeanPropertyRowMapper<T> implements RowMapper<T>
BeanPropertyRowMapper类实现了RowMapper接口
@Test
public void test1() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 queryForObject 方法
String sql = "select pname from product where price = 7777";
String pname = jdbcTemplate.queryForObject(sql, String.class);
System.out.println("pname = " + pname);
}
@Test
public void test2() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 queryForMap 方法
String sql = "select * from product where pid = ?;";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 6);
System.out.println("map = " + map);
}
@Test
public void test3() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 objectForList 方法
String sql = "select * from product where pid < ?;";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 8);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
@Test
public void test4() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 query 方法
String sql = "select * from product;";
List<Product> list = jdbcTemplate.query(sql, new RowMapper<Product>() {
@Override
public Product mapRow(ResultSet rs, int i) throws SQLException {
Product product = new Product();
int pid = rs.getInt("pid");
String pname = rs.getString("pname");
double price = rs.getDouble("price");
product.setPid(pid);
product.setPname(pname);
product.setPrice(price);
return product;
}
});
// 遍历 list 集合
for (Product product : list) {
System.out.println(product);
}
}
@Test
public void test5() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 query 方法
String sql = "select * from product;";
List<Product> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Product.class));
// 3. 遍历 list 集合
for (Product product : list) {
System.out.println(product);
}
}
@Test
public void test1() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 queryForObject 方法
String sql = "select pname from product where price = 7777";
String pname = jdbcTemplate.queryForObject(sql, String.class);
System.out.println("pname = " + pname);
}
@Test
public void test2() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 queryForMap 方法
String sql = "select * from product where pid = ?;";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 6);
System.out.println("map = " + map);
}
@Test
public void test3() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 objectForList 方法
String sql = "select * from product where pid < ?;";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 8);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
@Test
public void test4() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 query 方法
String sql = "select * from product;";
List<Product> list = jdbcTemplate.query(sql, new RowMapper<Product>() {
@Override
public Product mapRow(ResultSet rs, int i) throws SQLException {
Product product = new Product();
int pid = rs.getInt("pid");
String pname = rs.getString("pname");
double price = rs.getDouble("price");
product.setPid(pid);
product.setPname(pname);
product.setPrice(price);
return product;
}
});
// 遍历 list 集合
for (Product product : list) {
System.out.println(product);
}
}
@Test
public void test5() {
// 1. 创建一个 JdbcTemplate 对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
// 2. 执行 query 方法
String sql = "select * from product;";
List<Product> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Product.class));
// 3. 遍历 list 集合
for (Product product : list) {
System.out.println(product);
}
}
小结:
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
21JDBC_事务&JDBCTemplate的更多相关文章
- CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)
JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...
- 春天JDBC事务管理
JDBC事务管理 春天提供编程式的事务管理(编程式事务管理)与声明式的事务管理(声明式事务management),为不同的事务实现提供了一致的编程模型,这节以JDBC事务为例,介绍Spring的事务管 ...
- Mysql事务开启方式(客户端+java手动+Spring Boot)
一:概念 作为单个逻辑单元执行一系列操作,要么完全执行,要么完全不执行.举例 我们需要向数据库插入3条数据(我们希望这三条数据要么全部插入成功,要么全部失败), 比如第一条数据插入成功,插入第二条数据 ...
- 【Spring实战】—— 16 基于JDBC持久化的事务管理
前面讲解了基于JDBC驱动的Spring的持久化管理,本篇开始则着重介绍下与事务相关的操作. 通过本文你可以了解到: 1 Spring 事务管理的机制 2 基于JDBC持久化的事务管理 Spring的 ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- Spring 学习,看松哥这一篇万余字干货就够了!
1. Spring 简介 我们常说的 Spring 实际上是指 Spring Framework,而 Spring Framework 只是 Spring 家族中的一个分支而已.那么 Spring 家 ...
- 单点突破:Spring(上)
Spring概述 我们常说的 Spring 实际上是指 Spring Framework,而 Spring Framework 只是 Spring 家族中的一个分支而已.Spring 是为了解决企 ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- JdbcTemplate与事务
JdbcTemplate操作采用的是JDBC默认的AutoCommit模式,也就是说我们还无法保证数据操作的原子性(要么全部生效,要么全部无效),如: JdbcTemplate jdbcTemplat ...
随机推荐
- [HNOI2019]多边形[二叉树建模、组合计数]
题意 题目链接 分析 不难发现终态一定是 \([2,n-2]\) 中的每个点都与 \(n\) 连边. 关于凸多边形的划分问题,可以将它看作一棵二叉树:每个树点可以看做点可以看做边. 本题中看做点来处理 ...
- JavaScript技巧总结和本地存储(二)
离线检测 检测是否离线,html5为此定义了一个navigator.onLine属性,这个属性为true表示设备能上网,false表示离线,这个属性还有点兼容问题.因此单独使用这个属性不能确定网络是否 ...
- 史上最全面的Docker容器引擎使用教程
目录 1.Docker安装 1.1 检查 1.2 安装 1.3 镜像加速 1.4 卸载Docker 2.实战Nginx 3.Docker命令小结 4.DockerFile创建镜像 4.1 Docker ...
- Java发送Email邮件及SpringBoot集成
一:普通方式发送 1.导包 <!--Java MAil 发送邮件API--> <dependency> <groupId>javax.mail</groupI ...
- 升级MySQL5.7,开发不得不注意的坑
前段时间,将线上MySQL数据库升级到了5.7.考虑到可能产生的不兼容性,在升级之前,确实也是战战兢兢,虽然测试环境,开发环境早在半年前就已提前升级. 基于前期的调研和朋友的反馈,与开发相关的主要有两 ...
- .Net Core 在 Linux-Centos上的部署实战教程(一)
pa我是在VS2017上写好项目然后来部署的,我的宗旨能截图就少BB 服务器系统: Asp.Net Core版本: 1.往服务器安装.net core 2.1 https://www.microsof ...
- Python-常见面试题-持续更新
1.请你简要介绍一下Python的生成器是什么 答:Python生成器是一个返回可以迭代对象的函数,可以被用作控制循环的迭代行为. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用 ...
- debian6保存iptables规则
iptables规则不保存,一旦机器重启规则就清空了,所以需要保存: iptables-save >/etc/iptables-script vi /etc/rc.local 然后在文件中输入: ...
- 个人博客作业-week5-敏捷开发方法读后感
满篇英文对一个非单词狂魔来说真的是很吃力啊… 敏捷软件开发方法是一种从1990年代开始逐渐引起广发关注的一些新型软件开发方法,是一种应对快速变化的需求的一种软件开发能力,他们的具体名称.理念.过程.术 ...
- 爬虫——selenium基础
Selenium,自动化浏览器技术.主要用于web应用自动测试和自动完成web基本任务管理.官方网站:https://selenium-python.readthedocs.io/getting-st ...