21JDBC_事务&JDBCTemplate
一、JDBC_事务
通过JDBC来操作银行转账的事务
1.API介绍
Connection接口中与事务有关的方法
void setAutoCommit(boolean autoCommit) throws SQLException;
false:开启事务, ture:关闭事务
void commit() throws SQLException;
提交事务
void rollback() throws SQLException;
回滚事务
6
1
void setAutoCommit(boolean autoCommit) throws SQLException;
2
false:开启事务, ture:关闭事务
3
void commit() throws SQLException;
4
提交事务
5
void rollback() throws SQLException;
6
回滚事务
案例:
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);
}
}
}
57
1
import java.sql.Connection;
2
import java.sql.PreparedStatement;
3
import java.sql.SQLException;
4
5
public class JDBCTransactionTest {
6
public static void main(String[] args) {
7
8
Connection conn = null;
9
PreparedStatement stmt = null;
10
11
try {
12
// 1. 获取连接对象
13
conn = JDBCUtils.getConnection();
14
15
// 第一步 : 开启事务
16
conn.setAutoCommit(false);
17
18
// 2. 操作数据
19
// 2.1 账户转出
20
String outSql = "update account set money = money - ? where name = ?;";
21
stmt = conn.prepareStatement(outSql);
22
stmt.setInt(1, 1000);
23
stmt.setString(2, "tom");
24
stmt.executeUpdate();
25
26
// 模拟异常 ...
27
// int num = 10 / 0;
28
29
// 2.2 账户转入
30
String inSql = "update account set money = money + ? where name = ?;";
31
stmt = conn.prepareStatement(inSql);
32
stmt.setInt(1, 1000);
33
stmt.setString(2, "jery");
34
stmt.executeUpdate();
35
36
// 第二步 : 提交事务
37
conn.commit();
38
39
System.out.println("转账成功!");
40
41
} catch (Exception e) {
42
// 如果出现异常, 需要进行事务回滚.
43
// 第三步 : 回滚事务
44
try {
45
conn.rollback();
46
} catch (SQLException e1) {
47
e1.printStackTrace();
48
}
49
50
System.out.println("转账失败!");
51
52
} finally {
53
// 3. 释放资源
54
JDBCUtils.release(conn, stmt);
55
}
56
}
57
}
二、jdbcTemplate
1.API介绍
org.springframework.jdbc.core.JdbcTemplate类方便执行SQL语句
public JdbcTemplate(DataSource dataSource)
创建JdbcTemplate对象,方便执行SQL语句
public void execute(final String sql)
execute可以执行所有SQL语句,因为没有返回值,一般用于执行DML语句。
4
1
public JdbcTemplate(DataSource dataSource)
2
创建JdbcTemplate对象,方便执行SQL语句
3
public void execute(final String sql)
4
execute可以执行所有SQL语句,因为没有返回值,一般用于执行DML语句。
2.使用步骤
1. 准备DruidDataSource连接池
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.案例
(1)c3p0-config.xml配置文件
<?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>
18
1
<?xml version="1.0" encoding="UTF-8"?>
2
<c3p0-config>
3
<!-- 默认配置,c3p0框架默认加载这段默认配置 -->
4
<default-config>
5
<!-- 配置JDBC 四个基本属性 -->
6
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
7
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
8
<property name="user">root</property>
9
<property name="password">111</property>
10
</default-config>
11
<!-- 可以自定义配置,为这段配置起一个名字,c3p0指定名称加载配置 -->
12
<named-config name="xxxxx">
13
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
14
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=utf-8</property>
15
<property name="user">root</property>
16
<property name="password">111</property>
17
</named-config>
18
</c3p0-config>
(2)JDBCUtils工具类
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;
}
}
}
48
1
public class JDBCUtils {
2
3
// 核心连接池类
4
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
5
6
public static DataSource getDataSource() {
7
return dataSource;
8
}
9
10
// 获取连接
11
public static Connection getConnection() throws SQLException {
12
return dataSource.getConnection();
13
}
14
15
// 释放资源
16
public static void release(Connection conn, Statement stmt, ResultSet rs) {
17
if (rs != null) {
18
try {
19
rs.close();
20
} catch (SQLException e) {
21
e.printStackTrace();
22
}
23
rs = null;
24
}
25
26
release(conn, stmt);
27
}
28
29
public static void release(Connection conn, Statement stmt) {
30
if (stmt != null) {
31
try {
32
stmt.close();
33
} catch (SQLException e) {
34
e.printStackTrace();
35
}
36
stmt = null;
37
}
38
39
if (conn != null) {
40
try {
41
conn.close();
42
} catch (SQLException e) {
43
e.printStackTrace();
44
}
45
conn = null;
46
}
47
}
48
}
jdbcTemplate的exeucte方法
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);
}
}
17
1
public class JDBCTemplateExecute {
2
public static void main(String[] args) {
3
4
// 1. 创建表的SQL语句
5
String sql = "create table product (" +
6
"pid int primary key auto_increment," +
7
"pname varchar(20)," +
8
"price double" +
9
");";
10
11
// 2. 创建 jdbcTemplate 对象, 并将数据库连接池作为参数传入
12
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
13
14
// 3. 使用 jdbcTemplate 对象调用 execute 方法, 执行 sql 语句, 创建数据库表.
15
jdbcTemplate.execute(sql);
16
}
17
}
4通过jdbcTemplate实现增删改
API介绍
// org.springframework.jdbc.core.JdbcTemplate类方便执行SQL语句
public int update(final String sql)
用于执行`INSERT`、`UPDATE`、`DELETE`等DML语句
5
1
// org.springframework.jdbc.core.JdbcTemplate类方便执行SQL语句
2
public int update(final String sql)
3
用于执行`INSERT`、`UPDATE`、`DELETE`等DML语句
4
5
使用步骤:
1.创建JdbcTemplate对象
2.编写SQL语句
3.使用JdbcTemplate对象的update方法进行增删改
insert 增加数据 :
@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);
}
21
1
2
public void insert() {
3
4
// 1. 创建一个 JdbcTemplate 对象, 并将连接池作为参数传入
5
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
6
7
// 2. 编写 sql 语句
8
String sql = "insert into product values(null, ?, ?);";
9
10
// 3. 执行 update 方法.
11
jdbcTemplate.update(sql, "iPhone3GS", 3333);
12
jdbcTemplate.update(sql, "iPhone4", 5000);
13
jdbcTemplate.update(sql, "iPhone4S", 5001);
14
jdbcTemplate.update(sql, "iPhone5", 5555);
15
jdbcTemplate.update(sql, "iPhone5C", 3888);
16
jdbcTemplate.update(sql, "iPhone5S", 5666);
17
jdbcTemplate.update(sql, "iPhone6", 6666);
18
jdbcTemplate.update(sql, "iPhone6S", 7000);
19
jdbcTemplate.update(sql, "iPhone6SP", 7777);
20
jdbcTemplate.update(sql, "iPhoneX", 8888);
21
}
update 修改数据 :
@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);
}
11
1
2
public void update() {
3
4
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
5
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
6
7
// 2. 执行 update 语句
8
String sql = "update product set pname = ?, price = ? where pid = ?;";
9
int count = jdbcTemplate.update(sql, "XVIII", 18888, 10);
10
System.out.println("count = " + count);
11
}
delete 删除数据 :
@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);
}
10
1
2
public void delete() {
3
// 1. 创建一个 JdbcTemplate 对象, 并将数据库连接池作为参数传入
4
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
5
6
// 2. 执行 delete 操作
7
String sql = "delete from product where pid = ?;";
8
int count = jdbcTemplate.update(sql, 7);
9
System.out.println("count = " + count);
10
}
小结:
JdbcTemplate的update方法用于执行DML语句。同时还可以在SQL语句中使用?占位,在update方法的Object... args可变参数中传入对应的参数。
5 jdbcTemplate实现查询
API介绍
queryForObject返回一个指定类型
// 单行单列的查询
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接口
16
1
// 单行单列的查询
2
public <T> T queryForObject(String sql, Class<T> requiredType, Object... args):
3
传入参数, 执行查询语句,返回一个指定类型的数据。
4
5
// 单行多列
6
public Map<String, Object> queryForMap(String sql, Object... args)
7
传入参数,执行查询语句,将一条记录放到一个Map中。
8
9
// 多行多列
10
public List<Map<String, Object>> queryForList(String sql, Object... args)
11
传入参数,执行查询语句,返回一个List集合,List中存放的是Map类型的数据。
12
13
// 返回一个List 存放对象数据
14
public <T> List<T> query(String sql, RowMapper<T> rowMapper)
15
执行查询语句,返回一个List集合,List中存放的是RowMapper指定类型的数据。
16
17
// 提供了一个上述方法的一个实现类 RowMapper 行映射接口 BeanPropertyRowMapper 实体类属性行映射
18
public class BeanPropertyRowMapper<T> implements RowMapper<T>
19
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);
}
}
x
1
2
public void test1() {
3
4
// 1. 创建一个 JdbcTemplate 对象
5
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
6
7
// 2. 执行 queryForObject 方法
8
String sql = "select pname from product where price = 7777";
9
String pname = jdbcTemplate.queryForObject(sql, String.class);
10
System.out.println("pname = " + pname);
11
}
12
13
14
public void test2() {
15
16
// 1. 创建一个 JdbcTemplate 对象
17
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
18
19
// 2. 执行 queryForMap 方法
20
String sql = "select * from product where pid = ?;";
21
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 6);
22
System.out.println("map = " + map);
23
}
24
25
26
public void test3() {
27
28
// 1. 创建一个 JdbcTemplate 对象
29
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
30
31
// 2. 执行 objectForList 方法
32
String sql = "select * from product where pid < ?;";
33
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, 8);
34
for (Map<String, Object> map : list) {
35
System.out.println(map);
36
}
37
}
38
39
40
41
42
public void test4() {
43
44
// 1. 创建一个 JdbcTemplate 对象
45
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
46
47
// 2. 执行 query 方法
48
String sql = "select * from product;";
49
List<Product> list = jdbcTemplate.query(sql, new RowMapper<Product>() {
50
51
public Product mapRow(ResultSet rs, int i) throws SQLException {
52
53
Product product = new Product();
54
int pid = rs.getInt("pid");
55
String pname = rs.getString("pname");
56
double price = rs.getDouble("price");
57
product.setPid(pid);
58
product.setPname(pname);
59
product.setPrice(price);
60
61
return product;
62
}
63
});
64
65
// 遍历 list 集合
66
for (Product product : list) {
67
System.out.println(product);
68
}
69
}
70
71
72
73
74
public void test5() {
75
76
// 1. 创建一个 JdbcTemplate 对象
77
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
78
79
// 2. 执行 query 方法
80
String sql = "select * from product;";
81
List<Product> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Product.class));
82
83
// 3. 遍历 list 集合
84
for (Product product : list) {
85
System.out.println(product);
86
}
87
}
小结:
JDBCTemplate的query方法用于执行SQL语句,简化JDBC的代码。同时还可以在SQL语句中使用?占位,在query方法的Object... args可变参数中传入对应的参数。
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
Powers a lot like real estate.Its all about location, location, location.The closer you are to the source,the higher your property value.