MySQL JDBC事务处理、封装JDBC工具类
MySQL数据库学习笔记(十)----JDBC事务处理、封装JDBC工具类
一、JDBC事务处理:
我们已经知道,事务的概念即:所有的操作要么同时成功,要么同时失败。在MySQL中提供了Commit、Rollback命令进行事务的提交与回滚。实际上在JDBC中也存在事务处理,如果要想进行事务处理的话,则必须按照以下的步骤完成。
JDBC中事务处理的步骤:
1、要取消掉JDBC的自动提交:void setAutoCommit(boolean autoCommit)
2、执行各个SQL语句,加入到批处理之中
3、如果所有语句执行成功,则提交事务 commit();如果出现了错误,则回滚:rollback()
核心代码:

conn.setAutoCommit(false); // 取消自动提交 把SQL语句加入批处理 stmt.addBatch(…) () stmt.addBatch(…) //执行批处理操作 stmt.executeBatch(); conn.commit(); // 提交事务 //如果发生错误 conn.rollback();

代码举例:
首先在sql中创建一个空的数据库,现在在java中,使用PreparedStatement插入数据并修改数据。正常情况下,代码应该这样写:

1 package com.vae.jdbc;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.SQLException;
8
9 public class JDBCtest {
10
11
12 //数据库连接地址
13 public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb";
14 //用户名
15 public final static String USERNAME = "root";
16 //密码
17 public final static String PASSWORD = "smyh";
18 //驱动类
19 public final static String DRIVER = "com.mysql.jdbc.Driver";
20
21
22 public static void main(String[] args) {
23 // TODO Auto-generated method stub
24 //insert(p);
25 //update(p);
26 //delete(3);
27 insertAndQuery();
28 }
29
30
31 //方法:使用PreparedStatement插入数据、更新数据
32 public static void insertAndQuery(){
33 Connection conn = null;
34 try {
35 Class.forName(DRIVER);
36 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
37 String sql1 = "insert into user(name,pwd)values(?,?)";
38 String sql2 = "update user set pwd=? where name=?";
39 PreparedStatement ps = conn.prepareStatement(sql1);
40 ps.setString(1, "smyhvae");
41 ps.setString(2, "007");
42 ps.executeUpdate();
43
44 ps = conn.prepareStatement(sql2);
45 ps.setString(1, "008");
46 ps.setString(2, "smyh");
47 ps.executeUpdate();
48
49 ps.close();
50 conn.close();
51
52 } catch (ClassNotFoundException e) {
53 e.printStackTrace();
54 } catch (SQLException e) {
55 e.printStackTrace();
56 }
57 }
58
59 }

事务处理:
现在我们把上面的插入操作和修改操作变成一个事务,就要增加一部分代码了。修改上方的insertAndQuery()方法里面的代码:

1 //方法:使用PreparedStatement插入数据、更新数据
2 public static void insertAndQuery(){
3 Connection conn = null;
4 try {
5 Class.forName(DRIVER);
6 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
7 conn.setAutoCommit(false);//设置为手动提交事务
8 String sql1 = "insert into user(name,pwd)values(?,?)";
9 String sql2 = "update user set pwd=? where name=?";
10 PreparedStatement ps = conn.prepareStatement(sql1);
11 ps.setString(1, "smyhvae");
12 ps.setString(2, "007");
13 ps.executeUpdate();
14
15 ps = conn.prepareStatement(sql2);
16 ps.setString(1, "008");
17 ps.setString(2, "smyh");
18 ps.executeUpdate();
19 conn.commit(); //如果所有sql语句成功,则提交事务
20 ps.close();
21 conn.close();
22
23 } catch (ClassNotFoundException e) {
24 e.printStackTrace();
25 } catch (SQLException e) {
26 e.printStackTrace();
27 try {
28 conn.rollback();//只要有一个sql语句出现错误,则将事务回滚
29 } catch (SQLException e1) {
30 e1.printStackTrace();
31 }
32 }
33
34 }

核心代码是第07行、19行、28行。这三行代码就完成了事务处理的操作。两个sql语句中,只要有一个语句出现错误,程序将无法运行,说明事务提交失败,且报错如下:

二、封装JDBC工具类
之前的JDBC代码分析:
我们可以先回顾一下上一篇博文中的第五段:使用PreparedStatement重构增删改查。
通过分析可以发现有以下不足:有许多重复的代码、每次都要加载驱动、获取连接等。增删改查无非只是slq语句不一样而已。
封装工具类就是一个抽象的过程,我们可以把现在代码中非常公用的代码抽取出来,形成一个工具类。
- 第一步:抽象公共的代码到工具类。
- 第二步:为提高可以连接不同数据库的能力,将连接数据库的URL、用户名,密码等信息编写在一个属性文件(jdbc.properties)中,方便以后进行修改。
我们先把之前的文章中,使用PreparedStatement查询数据库的代码贴出来,方便和后面的内容进行对比,省的翻来翻去麻烦。
使用PreparedStatement查询数据库:(重构前)
在这之前,请建好一个Person类,参考上一篇博文就行了。然后,JDBCtest.java的代码如下:

1 package com.vae.jdbc;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.SQLException;
8
9 public class JDBCtest {
10
11
12 //数据库连接地址
13 public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb";
14 //用户名
15 public final static String USERNAME = "root";
16 //密码
17 public final static String PASSWORD = "smyh";
18 //驱动类
19 public final static String DRIVER = "com.mysql.jdbc.Driver";
20
21
22 public static void main(String[] args) {
23 // TODO Auto-generated method stub
24 Person p = new Person();
25
26 p = findById(2);
27 System.out.println(p);
28 }
29
30
31
32 // 使用PreparedStatement查询数据
33 public static Person findById(int id){
34 Person p = null;
35 try {
36 Class.forName(DRIVER);
37 Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
38 String sql = "select name,age,description from person where id=?";
39 PreparedStatement ps = conn.prepareStatement(sql);
40 //设置占位符对应的值
41 ps.setInt(1, id);
42
43 ResultSet rs = ps.executeQuery();
44 if(rs.next()){
45 p = new Person();
46 p.setId(id);
47 p.setName(rs.getString(1));
48 p.setAge(rs.getInt(2));
49 p.setDescription(rs.getString(3));
50
51 }
52 rs.close();
53 ps.close();
54 conn.close();
55
56
57 } catch (ClassNotFoundException e) {
58 e.printStackTrace();
59 } catch (SQLException e) {
60 e.printStackTrace();
61 }
62 return p;
63 }
64
65
66 }

接下来开始真正的工作了,从零开始。
封装工具类:
新建工程文件,结构如下:

(1)先新建一个DBUtils工具类:

1 package com.vae.jdbc;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8 import java.util.ResourceBundle;
9
10 /**
11 * 数据库操作工具类
12 * @author lamp
13 *
14 */
15 public class DBUtils {
16
17 //数据库连接地址
18 public static String URL;
19 //用户名
20 public static String USERNAME;
21 //密码
22 public static String PASSWORD;
23 //mysql的驱动类
24 public static String DRIVER;
25
26 private static ResourceBundle rb = ResourceBundle.getBundle("com.vae.jdbc.db-config");
27
28 private DBUtils(){}
29
30 //使用静态块加载驱动程序
31 static{
32 URL = rb.getString("jdbc.url");
33 USERNAME = rb.getString("jdbc.username");
34 PASSWORD = rb.getString("jdbc.password");
35 DRIVER = rb.getString("jdbc.driver");
36 try {
37 Class.forName(DRIVER);
38 } catch (ClassNotFoundException e) {
39 e.printStackTrace();
40 }
41 }
42 //定义一个获取数据库连接的方法
43 public static Connection getConnection(){
44 Connection conn = null;
45 try {
46 conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
47 } catch (SQLException e) {
48 e.printStackTrace();
49 System.out.println("获取连接失败");
50 }
51 return conn;
52 }
53
54 /**
55 * 关闭数据库连接
56 * @param rs
57 * @param stat
58 * @param conn
59 */
60 public static void close(ResultSet rs,Statement stat,Connection conn){
61 try {
62 if(rs!=null)rs.close();
63 if(stat!=null)stat.close();
64 if(conn!=null)conn.close();
65 } catch (SQLException e) {
66 e.printStackTrace();
67 }
68 }
69
70 }

28行:既然是工具类,一般不要实例化,此时可以采用单例设计模式,或者将构造方法私有化。
26行:很明显可以看到,我们是将连接数据库的URL、用户名,密码等信息编写在一个属性文件(jdbc.properties)中,稍后再来定义这个属性文件。
31行:为避免重复代码,使用静态代码块:只会在类加载的时候执行一次。
42行:定义一个获取数据库连接的方法
60行:关闭数据库连接
(2)接下来新建一个属性文件,new-->file,命名为:db-config.properties,代码如下:
jdbc.url=jdbc:mysql://localhost:3306/jdbcdb jdbc.username=root jdbc.password=smyh jdbc.driver=com.mysql.jdbc.Driver
以后如果需要修改配置信息,只需要在这里改就行了。注意在上面的DBUtils类中是怎么来调用这个配置信息的。
(3)紧接着新建文件,定义好Person类:
(4)然后开始编写主程序来测试一下:

1 package com.vae.jdbc;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7
8
9 public class Test {
10
11 public static void main(String[] args) {
12 Person p = new Person();
13 p = findById(1);
14 System.out.println(p);
15 }
16
17
18
19
20 /**
21 * 查询的方法
22 */
23 public static Person findById(int id){
24 Person p =null;
25 //通过工具类获取数据库连接
26 Connection conn = DBUtils.getConnection();
27 PreparedStatement ps = null;
28 ResultSet rs = null;
29 String sql = "select name,age,description from person where id=?";
30 try {
31 ps = conn.prepareStatement(sql);
32 //设置占位符对应的值
33 ps.setInt(1, id);
34 rs = ps.executeQuery();
35 if(rs.next()){
36 p = new Person();
37 p.setName(rs.getString(1));
38 p.setAge(rs.getInt(2));
39 p.setDescription(rs.getString(3));
40 }
41 } catch (SQLException e) {
42 e.printStackTrace();
43 }finally{
44 //通过工具类关闭数据库连接
45 DBUtils.close(rs, ps, conn);
46 }
47 return p;
48
49 }
50
51 }
MySQL JDBC事务处理、封装JDBC工具类的更多相关文章
- JDBC深度封装的工具类 (具有高度可重用性)
首先介绍一下Dbutils: Common Dbutils是操作数据库的组件,对传统操作数据库的类进行二次封装,可以把结果集转化成List. 补充一下,传统操作数据库的类指的是JDBC(java ...
- 一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入
一.JDBC的概述###<1>概念 JDBC:java database connection ,java数据库连接技术 是java内部提供的一套操作数据库的接口(面向接口编程),实现对数 ...
- JDBC封装的工具类
1. JDBC封装的工具类 public class JDBCUtil { private static Properties p = new Properties(); private static ...
- .NET3.5中JSON用法以及封装JsonUtils工具类
.NET3.5中JSON用法以及封装JsonUtils工具类 我们讲到JSON的简单使用,现在我们来研究如何进行封装微软提供的JSON基类,达到更加方便.简单.强大且重用性高的效果. 首先创建一个类 ...
- JAVA中封装JSONUtils工具类及使用
在JAVA中用json-lib-2.3-jdk15.jar包中提供了JSONObject和JSONArray基类,用于JSON的序列化和反序列化的操作.但是我们更习惯将其进一步封装,达到更好的重用. ...
- Workbook导出excel封装的工具类
在实际中导出excel非常常见,于是自己封装了一个导出数据到excel的工具类,先附上代码,最后会写出实例和解释.支持03和07两个版本的 excel. HSSF导出的是xls的excel,XSSF导 ...
- writeValueAsString封装成工具类
封装成工具类 <span style="font-family:Microsoft YaHei;">public static String toJsonByObjec ...
- 转:轻松把玩HttpClient之封装HttpClient工具类(一)(现有网上分享中的最强大的工具类)
搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用.调用关系不清楚,结构有点混乱.所以也就萌生了自己封装HttpClient工具类的想法.要做就 ...
- 打印 Logger 日志时,需不需要再封装一下工具类?
在开发过程中,打印日志是必不可少的,因为日志关乎于应用的问题排查.应用监控等.现在打印日志一般都是使用 slf4j,因为使用日志门面,有助于打印方式统一,即使后面更换日志框架,也非常方便.在 < ...
- 【JDBC】Java 连接 MySQL 基本过程以及封装数据库工具类
一. 常用的JDBC API 1. DriverManager类 : 数据库管理类,用于管理一组JDBC驱动程序的基本服务.应用程序和数据库之间可以通过此类建立连接.常用的静态方法如下 static ...
随机推荐
- 使用ssh远程执行命令批量导出数据库到本地(转)
前天正在跟前端的同事调试功能.服务器开好,模拟的玩家登录好,就在倒计时.这时突然运营的同事跑过来说要统计几个服务器玩家的一些情况,也就是需要从几个服的数据库导出部分玩家的数据.好吧,我看了一下时间,1 ...
- Xcode4.6 自制iOS可用的 Framework
First of all:新建一个空白project. File->New->Project 然后新建两个文件 File->New->File 如图 然后选择targets ...
- 公钥password学中的素数以及对称加密
password学.一向被人们觉得门槛非常高,特别高端...这也是实际,可是这决不意味着普通人无法了解它的精髓.对于喜欢画圆的人来讲,即便是理解了password技术背后的哪怕一点理论,也是激 ...
- EasyUI - DataGrid 组建 - [ 样式功能 ]
效果显示: 同上次博文效果. html代码: 同上次博文代码. js代码: align: 'center',//标题和内容居中 resizable: false,//不允许改变大小 //hidden: ...
- VC socket Connect 超时时间设置
设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...
- Kendo UI开发教程(21): Kendo MVVM 数据绑定(十) Source
Source绑定可以把ViewModel的值和由Kendo模板定义的目标元素绑定,如果ViewModel的值发生变化,被绑定的目标元素也随之发生变化.模板由属性data-template指定,它的值为 ...
- 自拉ADSL网线搭建站点server,解决动态IP、无公网IP、80port被封、HTTP被屏蔽的方法
自己的server搭建站点应用,提供站点服务,能够不用备案,但可能会面对网络限制问题,如动态公网IP.无公网IP.80port被封.HTTP被屏蔽,这些复杂网络情况. 依据本地网络环境,能够针对不同的 ...
- ASP.NET、WinForm - 判断整个页面文本框是否为空
foreach(Control ctrl in Page.Controls) { foreach(Control childc in ctrl.Controls) { switch(childc.Ge ...
- 【Demo 0003】Android 事件
本章学习要点: 1. 了解Android中资源用途: 2. 掌握资源使用通用规则: 3. 掌握具体资源使用方法;
- 综述-如何克服HTML5的“性工能”障碍
http://ask.dcloud.net.cn/docs HTML5自出现以来,几经风雨,虽看似很有前途,但实际使用问题太多,DCloud为此踩了无数坑.但我们从未放弃,我们加入了W3C,发起了 H ...