JDBC事务和连接池
JDBC 事务控制
-
-
操作:
-
开启事务:mysql----->start transaction
-
提交事务:commit
-
回滚事务:rollback
-
-
使用Connection对象来管理事务
-
开启事务: setAutoCommit(boolean autoCommit): 指定该方法里面传入false值,手动开启事务。
在执行sql语句之前开启事务。
-
提交事务:commit();---->当所有的sql语句执行完毕才提交事务
-
回滚事务:rollback();---->当事务中发生异常时回滚事务 回滚事务放在catch语句。
-
-
示例:以银行转账为例:让张三给李四转账10000钱
1 // 含有事务的转账
2 public static void transform02() {
3 // 让张三给李四转账10000钱
4 /*
5 * 首先让张三的钱减少10000
6 * 然后让李四的钱增加10000
7 */
8 //定义实现转账的两条sql语句
9 double money = 10000;
10 String username01 = "张三";
11 String username02= "李四";
12
13 String sql01 = "update account set balance = balance-? where username = ?";
14 String sql02 = "update account set balance = balance+? where username = ?";
15 // 使用Connection对象手动开启事务 setAutoCommit(boolean autoCommit):
16 Connection con = DBUtil.getConnection();
17 try {
18 con.setAutoCommit(false);
19 // 通过con获取预处理对象 先让张三的钱减少10000
20 ps01 = con.prepareStatement(sql01);
21 ps01.setDouble(1, money);
22 ps01.setString(2, username01);
23 // 执行sql语句
24 int count = ps01.executeUpdate();
25 // 手动制造一个异常
26 int i = 1 / 0;
27 // 再让李四的钱增加10000
28 // 通过con获取预处理对象
29 ps02 = con.prepareStatement(sql02);
30 ps02.setDouble(1, money);
31 ps02.setString(2, username02);
32 // 执行sql语句
33 int coun02 = ps02.executeUpdate();
34 // 提交事务
35 con.commit();
36 System.out.println("转账成功!");
37 } catch (Exception e) {
38 // 事务回滚
39 try {
40 con.rollback();
41 System.out.println("转账失败!");
42 } catch (SQLException e1) {
43 e1.printStackTrace();
44 }
45 e.printStackTrace();
46 }finally {
47 // 把打开的各种连接对象释放掉
48 try {
49 ps02.close();
50 ps01.close();
51 con.close();
52 } catch (SQLException e) {
53 e.printStackTrace();
54 }
55 }
56 }
连接池
-
什么连接池:其实就是一个容器,在这个容器当中存放着多个连接对象。
-
好处:
-
可以大大节省系统开销
-
可以提高访问的速度。
3.实现操作:
javax.sql 连接池
JNDI -----> Java Naming and Directory Interface Java命名和目录接口
使用JNDI 降低程序和数据库的耦合度,使你的程序更加方便配置和维护以及部署。
是JavaEE中规范中的重要规范之一。是EJB的相关的知识。
DataSource接口 它里面并不提供具体的实现,而是由驱动程序供应商(数据库厂商)提供
-
c3p0: 它是数据库连接池的一套技术
-
druid:也是一套数据据库连接池的技术,由阿里巴巴提供的。
-
4.C3p0:数据库连接池技术
步骤:
-
-
去官网下载两个jar包:c3p0-0.9.5.2.jar 和 mchange-commons-java-0.2.12.jar
-
植入到工程的classpath类路径下,不要忘记导入mysql驱动jar包 mysql-connector-java.jar
-
定义配置文件:
-
文件类型:c3p0.properties 或者 c3p0-config.xml
-
路径:放到classpath类路径下 对于工程来说直接放到src下面即可
-
-
获取DataSource对象 : 数据库连接池对象 通过实例化ComboPooledDataSource来获取
-
从连接池中获取连接对象。 getConnection()
-
5.Druid 德鲁伊连接池技术
-
-
步骤:
-
去官网去下载一个德鲁伊的jar ---> druid-1.0.9.jar
-
定义配置文件:使用properties文件类型的,名字随便起
-
手动加载配置文件信息: Properties集合
-
获取DataSource对象 :通过工厂方式来实现的,DruidDataSourceFactory
-
从连接池中获取连接对象:getConnection()
-
-
JDBC Template
-
Spring框架提供了对JDBC操作的简单封装,使用JDBCTemplate对象来简化JDBC开发流程。
-
步骤:
-
从官网下载对应的spring-jdbc相关的jar包,导入工程类路径下,放到lib文件夹下面即可
-
创建JDBCTemplate对象。依赖于DataSouce连接池(数据源)
-
使用JDBCTemplate对象中的api方法实现crud操作
-
DML操作: update()
-
DQL操作: 查询 不用select,使用query
-
query(): 将查询的结果集封装成JavaBean对象
-
query()方法的参数:RowMapper
-
手动装配:使用匿名内部类,自定义装配查询的每条记录值
-
自动装配:使用Spring提供的BeanPropertyRowMapper实现类,完成对数据的自动装配
具体操作-->new BeanPropertyRowMapper<类型>(类型.class)
-
-
-
queryForMap(): 将查询的结果集封装成map集合,只能封装一条记录:键key是字段名,值value是字段值,结果集记录数只能是1
-
queryForList():将结果集封装成List集合,在list集合中有多条记录,每一条记录都是一个map集合
List<Map<Object,Object>> list ;
-
queryFoObject():将结果集封装成一个对象,一般用于聚合函数 查询总记录数 int count()
-
-
具体操作:
-
-
// 增删改动作
// 修改数据
public static void modifyData() {
int count = jdbcTemplate.update("update account set username = ? where username = ?", "小五","王五");
System.out.println(count);
}
// 删除数据
public static void deleteData() {
int count = jdbcTemplate.update("delete from account where username = ?", "小五");
System.out.println(count);
}
// 插入一条数据
public static void insertDate() {
int count = jdbcTemplate.update("insert into account values(null,?,?)", "王五",5000);
System.out.println(count);
}
public static void test() {
// 查询张三的这条信息 封装到账户对象中
String username = "张三";
String sql = "select * from account where username = ?";
Map<String, Object> map = jdbcTemplate.queryForMap(sql,username);
System.out.println(map);// {id=1, username=张三, balance=20000.0}
}
// 简化手动封装的方法
public static void queryAll() {
String sql = "select * from account";
// Incorrect column count: expected 1, actual 3
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
System.out.println(list);
}
// 使用query方法优化queryBean方法
public static void queryBean2() {
List<Account> list = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
System.out.println(list);
}
// 将查询到结果集封装成JavaBean对象
public static void queryBean() {
String sql = "select * from account where username = '张三'";
// RowMapper<T>
List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>() {
@Override
public Account mapRow(ResultSet set, int arg1) throws SQLException {
// 封装查询到每一条记录值
Account account = new Account();
int id = set.getInt(1);
String username = set.getString(2);
double balance = set.getDouble(3);
account.setId(id);
account.setUsername(username);
account.setBalance(balance);
return account;
}
});
System.out.println(list);// [Account [id=1, username=张三, balance=20000.0]]
}
// 查询总记录 查询account表中的所有记录数
public static void queryTotalNum() {
// queryFoObject()
Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class);
System.out.println(count);// 4
}