【声明】

欢迎转载,但请保留文章原始出处→_→

生命壹号:http://www.cnblogs.com/smyhvae/

文章来源:http://www.cnblogs.com/smyhvae/p/4055183.html

【正文】

首先需要回顾一下上一篇文章中的内容:MySQL数据库学习笔记(九)----JDBC的PreparedStatement接口重构增删改查

一、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插入数据并修改数据。正常情况下,代码应该这样写:

 package com.vae.jdbc;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class JDBCtest { //数据库连接地址
public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb";
//用户名
public final static String USERNAME = "root";
//密码
public final static String PASSWORD = "smyh";
//驱动类
public final static String DRIVER = "com.mysql.jdbc.Driver"; public static void main(String[] args) {
// TODO Auto-generated method stub
//insert(p);
//update(p);
//delete(3);
insertAndQuery();
} //方法:使用PreparedStatement插入数据、更新数据
public static void insertAndQuery(){
Connection conn = null;
try {
Class.forName(DRIVER);
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
String sql1 = "insert into user(name,pwd)values(?,?)";
String sql2 = "update user set pwd=? where name=?";
PreparedStatement ps = conn.prepareStatement(sql1);
ps.setString(1, "smyhvae");
ps.setString(2, "007");
ps.executeUpdate(); ps = conn.prepareStatement(sql2);
ps.setString(1, "008");
ps.setString(2, "smyh");
ps.executeUpdate(); ps.close();
conn.close(); } catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
} }

事务处理:

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

 //方法:使用PreparedStatement插入数据、更新数据
public static void insertAndQuery(){
Connection conn = null;
try {
Class.forName(DRIVER);
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
conn.setAutoCommit(false);//设置为手动提交事务
String sql1 = "insert into user(name,pwd)values(?,?)";
String sql2 = "update user set pwd=? where name=?";
PreparedStatement ps = conn.prepareStatement(sql1);
ps.setString(1, "smyhvae");
ps.setString(2, "007");
ps.executeUpdate(); ps = conn.prepareStatement(sql2);
ps.setString(1, "008");
ps.setString(2, "smyh");
ps.executeUpdate();
conn.commit(); //如果所有sql语句成功,则提交事务
ps.close();
conn.close(); } catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();//只要有一个sql语句出现错误,则将事务回滚
} catch (SQLException e1) {
e1.printStackTrace();
}
} }

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

二、封装JDBC工具类

之前的JDBC代码分析:

我们可以先回顾一下上一篇博文中的第五段:使用PreparedStatement重构增删改查。

通过分析可以发现有以下不足:有许多重复的代码、每次都要加载驱动、获取连接等。增删改查无非只是slq语句不一样而已。

封装工具类就是一个抽象的过程,我们可以把现在代码中非常公用的代码抽取出来,形成一个工具类。

  • 第一步:抽象公共的代码到工具类。
  • 第二步:为提高可以连接不同数据库的能力,将连接数据库的URL、用户名,密码等信息编写在一个属性文件(jdbc.properties)中,方便以后进行修改。 

我们先把之前的文章中,使用PreparedStatement查询数据库的代码贴出来,方便和后面的内容进行对比,省的翻来翻去麻烦。

使用PreparedStatement查询数据库:(重构前)

在这之前,请建好一个Person类,参考上一篇博文就行了。然后,JDBCtest.java的代码如下:

 package com.vae.jdbc;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class JDBCtest { //数据库连接地址
public final static String URL = "jdbc:mysql://localhost:3306/JDBCdb";
//用户名
public final static String USERNAME = "root";
//密码
public final static String PASSWORD = "smyh";
//驱动类
public final static String DRIVER = "com.mysql.jdbc.Driver"; public static void main(String[] args) {
// TODO Auto-generated method stub
Person p = new Person(); p = findById(2);
System.out.println(p);
} // 使用PreparedStatement查询数据
public static Person findById(int id){
Person p = null;
try {
Class.forName(DRIVER);
Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
String sql = "select name,age,description from person where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
//设置占位符对应的值
ps.setInt(1, id); ResultSet rs = ps.executeQuery();
if(rs.next()){
p = new Person();
p.setId(id);
p.setName(rs.getString(1));
p.setAge(rs.getInt(2));
p.setDescription(rs.getString(3)); }
rs.close();
ps.close();
conn.close(); } catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return p;
} }

接下来开始真正的工作了,从零开始。

封装工具类:

新建工程文件,结构如下:

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

 package com.vae.jdbc;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle; /**
* 数据库操作工具类
* @author lamp
*
*/
public class DBUtils { //数据库连接地址
public static String URL;
//用户名
public static String USERNAME;
//密码
public static String PASSWORD;
//mysql的驱动类
public static String DRIVER; private static ResourceBundle rb = ResourceBundle.getBundle("com.vae.jdbc.db-config"); private DBUtils(){} //使用静态块加载驱动程序
static{
URL = rb.getString("jdbc.url");
USERNAME = rb.getString("jdbc.username");
PASSWORD = rb.getString("jdbc.password");
DRIVER = rb.getString("jdbc.driver");
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//定义一个获取数据库连接的方法
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
System.out.println("获取连接失败");
}
return conn;
} /**
* 关闭数据库连接
* @param rs
* @param stat
* @param conn
*/
public static void close(ResultSet rs,Statement stat,Connection conn){
try {
if(rs!=null)rs.close();
if(stat!=null)stat.close();
if(conn!=null)conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
} }

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类:

 package com.vae.jdbc;

 public class Person {
private int id;
private String name;
private int age;
private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Person(int id, String name, int age, String description) {
super();
this.id = id;
this.name = name;
this.age = age;
this.description = description;
}
public Person(String name, int age, String description) {
super();
this.name = name;
this.age = age;
this.description = description;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age
+ ", description=" + description + "]";
} }

Person.java

(4)然后开始编写主程序来测试一下:

 package com.vae.jdbc;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class Test { public static void main(String[] args) {
Person p = new Person();
p = findById(1);
System.out.println(p);
} /**
* 查询的方法
*/
public static Person findById(int id){
Person p =null;
//通过工具类获取数据库连接
Connection conn = DBUtils.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select name,age,description from person where id=?";
try {
ps = conn.prepareStatement(sql);
//设置占位符对应的值
ps.setInt(1, id);
rs = ps.executeQuery();
if(rs.next()){
p = new Person();
p.setName(rs.getString(1));
p.setAge(rs.getInt(2));
p.setDescription(rs.getString(3));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
//通过工具类关闭数据库连接
DBUtils.close(rs, ps, conn);
}
return p; } }

测试程序是可以运行的。这样,我们的工具类就建好了。

MySQL数据库学习笔记(十)----JDBC事务处理、封装JDBC工具类的更多相关文章

  1. MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  2. MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  3. Mysql数据库学习笔记之数据库索引(index)

    什么是索引: SQL索引有两种,聚集索引和非聚集索引,索引主要目的是提高了SQL Server系统的性能,加快数据的查询速度与减少系统的响应时间. 聚集索引:该索引中键值的逻辑顺序决定了表中相应行的物 ...

  4. MYSQL数据库学习笔记1

      MYSQL数据库学习笔记1 数据库概念 关系数据库 常见数据库软件 SQL SQL的概念 SQL语言分类 数据库操作 创建数据库 查看数据库的定义 删除数据库 修改数据库 创建表 数据类型 约束 ...

  5. MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  6. MySQL数据库学习笔记(八)----JDBC入门及简单增删改数据库的操作

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  7. MySql数据库学习笔记(1)

    MySql数据库 下载地址 https://dev.mysql.com/downloads/mysql/5.1.html#downloads 连接到本机上的MYSQL mysql -u root -p ...

  8. MySQL数据库学习笔记<一>

    MySQL基本概念以及简单操作   一.MySQL   MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系 ...

  9. MYSQL进阶学习笔记十八:MySQL备份和还原!(视频序号:进阶_37)

    知识点十九:MySQL的备份的还原(38) 一.mysql的备份 1.通过使用mysqldump的命令备份 使用mysqldump命令备份,mysqldump命令将数据库中的数据备份成一个文本文件.表 ...

随机推荐

  1. SystemClock.sleep和Thread.sleep的区别(转)

    在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实 Android平台还提供了一个SystemClock.sleep方 ...

  2. [程序人生]前途无"亮‘’的大学

    转眼之间就到大四了,今天晚上很迷茫,很纠结,想了好多,好多,真的,长大之后,自从第一次失恋之后,第一次会想到这么的多.     嗯,先自我介绍哈吧,我是从云南的大山里走出来的孩子,什么样的大山,就是到 ...

  3. 改变mvc web api 支持android ,ios ,ajax等方式跨域调用

    公司一个移动后端的项目用到了 webapi 项目搭建到外网环境共app开发者调用测试接口时遇到了一个问题 接口不允许跨域调用 .查阅资料明白 同源策略原则根据请求报头值 Origin 与回应报头值 A ...

  4. ASP.NET MVC自定义AuthorizeAttribute篇知识点讲解—登录限制

    1.前言 a.微软对ASP.NET的开发从WebForm到MVC的转变,已经正式过去5,6个年头,现在WebForm和MVC也都越来越完善,小小算来我也已经工作了将近三年,从大学的时候学习ASP.NE ...

  5. javascript中apply()和call()方法的区别

    一.方法的定义 call方法: 语法:call(thisObj,Object)定义:调用一个对象的一个方法,以另一个对象替换当前对象.说明:call 方法可以用来代替另一个对象调用一个方法.call ...

  6. SharePoint 2013: Search Architecture in SPC202

    http://social.technet.microsoft.com/wiki/contents/articles/15989.sharepoint-2013-search-architecture ...

  7. 解决连接Oracle 11g报ORA-01034和ORA-27101的错误

    参考文献: http://10000001.blog.51cto.com/4600383/1248367 背景: 使用sqlplus连接oracle,提示ORA-01034和ORA-27101,具体内 ...

  8. vsphere vcenter server下安装ubuntu的vmwaretools

    0.参考文献 百度经验:这里面是以redhat桌面版为实例进行介绍的,我的环境是ubuntu-server,虽然不一样,也可以参考 http://jingyan.baidu.com/article/2 ...

  9. 在iOS 8中使用UIAlertController

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...

  10. OpenGL ES学习笔记(三)——纹理

    首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <OpenGL ES学习笔记( ...