zoukankan      html  css  js  c++  java
  • MySQL数据库学习笔记(十)----JDBC事务处理、封装JDBC工具类

     【声明】 

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

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

     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 }

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

    封装工具类:

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

    37ba68f4-fa7f-49fc-bfb5-1d6b4acc4c66

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

     1 package com.vae.jdbc;
     2 
     3 public class Person {
     4     private int id;
     5     private String name;
     6     private int age;
     7     private String description;
     8     public int getId() {
     9         return id;
    10     }
    11     public void setId(int id) {
    12         this.id = id;
    13     }
    14     public String getName() {
    15         return name;
    16     }
    17     public void setName(String name) {
    18         this.name = name;
    19     }
    20     public int getAge() {
    21         return age;
    22     }
    23     public void setAge(int age) {
    24         this.age = age;
    25     }
    26     public String getDescription() {
    27         return description;
    28     }
    29     public void setDescription(String description) {
    30         this.description = description;
    31     }
    32     public Person(int id, String name, int age, String description) {
    33         super();
    34         this.id = id;
    35         this.name = name;
    36         this.age = age;
    37         this.description = description;
    38     }
    39     public Person(String name, int age, String description) {
    40         super();
    41         this.name = name;
    42         this.age = age;
    43         this.description = description;
    44     }
    45     public Person() {
    46         super();
    47         // TODO Auto-generated constructor stub
    48     }
    49     @Override
    50     public String toString() {
    51         return "Person [id=" + id + ", name=" + name + ", age=" + age
    52                 + ", description=" + description + "]";
    53     }
    54     
    55     
    56 }
    Person.java

    (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 }

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

  • 相关阅读:
    Java Swing3-MyDialog的基本实现
    Java IO4 实现凯撒密码加密解密文本文件
    POJ 3869 条件概率
    2017年校招全国统一模拟笔试(第三场)编程题集合
    POJ 2800 Joseph’s Problem 数论找规律
    数据结构期末考试再复习
    Java Swing2 基本登录框
    Java Swing1 基本框架
    Java 多线程1 烧水开水喝茶案例
    Java IO3 把一个图片写进txt,再写出还原图片
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4055183.html
Copyright © 2011-2022 走看看