【JavaEE学习笔记】JDBC_02_抽取jdbc工具类,事物,调用存储过程
2017-10-07 14:40
721 查看
JDBC_02
A.抽取jdbc工具类
1.概述
在我Java链接数据库中,需要一系列的步骤
但在开发中,不可能每次都要写这么长的步骤
所以,我们可以将这些步骤抽取到一个工具类中
这样在链接数据库时,直接调用即可,减少代码的复用性
2.工具类
工具类一旦写好,尽量避免改动
但我们每次链接的数据库不同,帐号密码也不同
因此我们需要建立一个配置文件,存放这些参数
只需要通过集合properties.load()方法
或者ResourceBundle工具(代码中解释)从文本中读取配置信息即可
当我们需要更改数据库配置信息,只需要更改配置文件即可
在src文件下创建一个配置文件jdbc.properties
B.事物
1.模拟银行转账
现在数据库中创建一个表
现在制造一个异常来模拟:当张三将钱转出去,服务器发生异常,强制终止
给执行语句中间加一个异常
会发现张三账户扣了钱,但李四没到帐
这种情况在银行是不允许的,因此引入事物概念
2.概述
a.概念
事务指一组最小逻辑操作单元,里面由多个操作组成
组成事务的每一部分必须要同时提交成功
如果有一个操作失败,整个操作就回滚
b.特性
1)原子性:是一个最小逻辑操作单元
指事务是一个不可分割的工作单位
事务中的操作要么都发生,要么都不发生
2)一致性:事务过程中,数据处于一致状态
事务必须使数据库从一个一致性状态变换到另外一个一致性状态
3)隔离性:事务与事务之间是隔离的
多个用户并发访问数据库时,数据库为每一个用户开启的事务
不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
4)持久性:事务一旦提交成功,对数据的更改会反映到数据库中
事务一旦被提交,它对数据库中数据的改变就是永久性的
接下来即使数据库发生故障也不应该对其有任何影响
3.事务回滚
针对上述银行账户问题,就要使用回滚来解决
Connection SetAutoCommit(boolean b):开启事物,默认为true,b=false则开启事物
Connection rollback():回滚事物到初始状态(当程序运行异常,张三李四账户余额不变)
Connection commit():提交事物
4.事物回滚点
当程序中执行两次转账,第一次成功,第二次失败,回滚到初始状态
但我想第一转账成功保留,只会滚到第二次转账前的状态,怎么办?
需要设置一个回滚点
Connection setSavepoint():在两次之间设置一个回滚点
Connection rollback(Connection setSavepoint()):回滚到回滚点上
第一次转账成功,第二次发生异常
在两次之间设置了一个回滚点,使得正确执行的部分得以保留
C.调用存储过程
1.概述
有时为了提高效率,需要执行存储过程语句
2.调用存储过程
Connection prepareCall(sql):创建存储过程对象
建立一个存储过程
A.抽取jdbc工具类
1.概述
在我Java链接数据库中,需要一系列的步骤
但在开发中,不可能每次都要写这么长的步骤
所以,我们可以将这些步骤抽取到一个工具类中
这样在链接数据库时,直接调用即可,减少代码的复用性
2.工具类
工具类一旦写好,尽量避免改动
但我们每次链接的数据库不同,帐号密码也不同
因此我们需要建立一个配置文件,存放这些参数
只需要通过集合properties.load()方法
或者ResourceBundle工具(代码中解释)从文本中读取配置信息即可
当我们需要更改数据库配置信息,只需要更改配置文件即可
在src文件下创建一个配置文件jdbc.properties
url=jdbc:mysql://localhost:3306/mydb_01 user=root password=root driverClass=com.mysql.jdbc.Driver工具类
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ResourceBundle; // 工具类 public class JDBCUtil { private static String url; private static String user; private static String password; private static String driverClass; // 静态代码块,随着类的加载而执行 // 读取配置信息并加载驱动,只要调用类,就加载 static { try { // 方式1 properties // 创建集合 // Properties prop = new Properties(); // 读取配置信息 // prop.load(new FileInputStream("src//jdbc.properties")); // url = prop.getProperty("url"); // user = prop.getProperty("user"); // password = prop.getProperty("password"); // 加载驱动 // Class.forName(prop.getProperty("driverClass")); // 方式2 ResourceBundle工具 // 如果一个文件在src目录下 而且键值对数据是以"="连接 并且文件后缀名是.properties // 1)获取对象 ResourceBundle bundle = ResourceBundle.getBundle("jdbc"); // 不带后缀名 url = bundle.getString("url"); user = bundle.getString("user"); password = bundle.getString("password"); driverClass = bundle.getString("driverClass"); // 加载驱动 Class.forName(driverClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 不让外界创建对象,私有构造 private JDBCUtil() { super(); } // 获取连接 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } // 释放资源 public static void close(Connection conn, Statement statement, ResultSet resultSet) throws SQLException { // 非空判断 if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (conn != null) { conn.close(); } } // 如果没有返回结果集,方法重载 public static void close(Connection conn, Statement statement) throws SQLException { // 非空判断 if (statement != null) { statement.close(); } if (conn != null) { conn.close(); } } }测试类
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.xxxx.jdbc.utils.JDBCUtil; // 测试类 public class JDBCDemo01 { public static void main(String[] args) throws SQLException { // 拷jar包 // 获取链接对象 Connection conn = JDBCUtil.getConnection(); // 定义sql语句 String sql = "select * from user where username=?"; // 获取预编译对象 PreparedStatement statement = conn.prepareStatement(sql); // 给占位符赋值 statement.setString(1, "张三"); // 执行语句 ResultSet resultSet = statement.executeQuery(); // 处理结果 while (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); System.out.println(id + "---" + username); } // 释放资源 JDBCUtil.close(conn, statement, resultSet); } }
B.事物
1.模拟银行转账
现在数据库中创建一个表
CREATE TABLE bank( username VARCHAR(50), money INT ); INSERT INTO bank VALUES('张三', 5000); INSERT INTO bank VALUES('李四', 100); SELECT * FROM bank;现在需求是张三给李四转账1000
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.xxxx.jdbc.utils.JDBCUtil; public class Demo01 { public static void main(String[] args) { // 拷jar包 Connection conn = null; PreparedStatement statement1 = null; PreparedStatement statement2 = null; try { // 建立连接 conn = JDBCUtil.getConnection(); // 定义sql语句 String sql1 = "update bank set money=money-1000 where username=?"; // 账户转出 String sql2 = "update bank set money=money+1000 where username=?"; // 账户转入 // 获取预编译对象 statement1 = conn.prepareStatement(sql1); statement2 = conn.prepareStatement(sql2); // 给?赋值 statement1.setString(1, "张三"); statement2.setString(1, "李四"); // 执行语句 statement1.executeUpdate(); statement2.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { // 释放资源 try { JDBCUtil.close(null, statement2); JDBCUtil.close(conn, statement1); } catch (SQLException e) { e.printStackTrace(); } } } }查看结果
现在制造一个异常来模拟:当张三将钱转出去,服务器发生异常,强制终止
给执行语句中间加一个异常
// 执行语句 statement1.executeUpdate(); // 加一个异常 System.out.println(1 / 0); statement2.executeUpdate();
会发现张三账户扣了钱,但李四没到帐
这种情况在银行是不允许的,因此引入事物概念
2.概述
a.概念
事务指一组最小逻辑操作单元,里面由多个操作组成
组成事务的每一部分必须要同时提交成功
如果有一个操作失败,整个操作就回滚
b.特性
1)原子性:是一个最小逻辑操作单元
指事务是一个不可分割的工作单位
事务中的操作要么都发生,要么都不发生
2)一致性:事务过程中,数据处于一致状态
事务必须使数据库从一个一致性状态变换到另外一个一致性状态
3)隔离性:事务与事务之间是隔离的
多个用户并发访问数据库时,数据库为每一个用户开启的事务
不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
4)持久性:事务一旦提交成功,对数据的更改会反映到数据库中
事务一旦被提交,它对数据库中数据的改变就是永久性的
接下来即使数据库发生故障也不应该对其有任何影响
3.事务回滚
针对上述银行账户问题,就要使用回滚来解决
Connection SetAutoCommit(boolean b):开启事物,默认为true,b=false则开启事物
Connection rollback():回滚事物到初始状态(当程序运行异常,张三李四账户余额不变)
Connection commit():提交事物
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.xxxx.jdbc.utils.JDBCUtil; public class Demo01 { public static void main(String[] args) { // 拷jar包 Connection conn = null; PreparedStatement statement1 = null; PreparedStatement statement2 = null; try { // 建立连接 conn = JDBCUtil.getConnection(); // 开启事物 conn.setAutoCommit(false); // 定义sql语句 String sql1 = "update bank set money=money-1000 where username=?"; // 账户转出 String sql2 = "update bank set money=money+1000 where username=?"; // 账户转入 // 获取预编译对象 statement1 = conn.prepareStatement(sql1); statement2 = conn.prepareStatement(sql2); // 给?赋值 statement1.setString(1, "张三"); statement2.setString(1, "李四"); // 执行语句 statement1.executeUpdate(); // 加一个异常 System.out.println(1 / 0); statement2.executeUpdate(); } catch (Exception e) { // 一旦发生异常,回滚到最初状态 try { conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { // 提交事物 try { conn.commit(); } catch (SQLException e1) { e1.printStackTrace(); } // 释放资源 try { JDBCUtil.close(null, statement2); JDBCUtil.close(conn, statement1); } catch (SQLException e) { e.printStackTrace(); } } } }当程序发生异常,数据回滚到最初状态
4.事物回滚点
当程序中执行两次转账,第一次成功,第二次失败,回滚到初始状态
但我想第一转账成功保留,只会滚到第二次转账前的状态,怎么办?
需要设置一个回滚点
Connection setSavepoint():在两次之间设置一个回滚点
Connection rollback(Connection setSavepoint()):回滚到回滚点上
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Savepoint; import org.xxxx.jdbc.utils.JDBCUtil; public class Demo01 { public static void main(String[] args) { // 拷jar包 Connection conn = null; PreparedStatement statement1 = null; PreparedStatement statement2 = null; Savepoint savepoint = null; try { // 建立连接 conn = JDBCUtil.getConnection(); // 开启事物 conn.setAutoCommit(false); // 定义sql语句 String sql1 = "update bank set money=money-1000 where username=?"; // 账户转出 String sql2 = "update bank set money=money+1000 where username=?"; // 账户转入 // 第一次转账 // 获取预编译对象 statement1 = conn.prepareStatement(sql1); statement2 = conn.prepareStatement(sql2); // 给?赋值 statement1.setString(1, "张三"); statement2.setString(1, "李四"); // 执行语句 statement1.executeUpdate(); statement2.executeUpdate(); // 设置回滚点 savepoint = conn.setSavepoint(); // 第二次转账 // 执行语句 statement1.executeUpdate(); // 加一个异常 System.out.println(1 / 0); statement2.executeUpdate(); } catch (Exception e) { // 一旦发生异常,回滚到最初状态 try { conn.rollback(savepoint); // 回滚到指定回滚点 } catch (SQLException e1) { e1.printStackTrace(); } } finally { // 提交事物 try { conn.commit(); } catch (SQLException e1) { e1.printStackTrace(); } // 释放资源 try { JDBCUtil.close(null, statement2); JDBCUtil.close(conn, statement1); } catch (SQLException e) { e.printStackTrace(); } } } }
第一次转账成功,第二次发生异常
在两次之间设置了一个回滚点,使得正确执行的部分得以保留
C.调用存储过程
1.概述
有时为了提高效率,需要执行存储过程语句
2.调用存储过程
Connection prepareCall(sql):创建存储过程对象
建立一个存储过程
DELIMITER $ CREATE PROCEDURE pro_bank() BEGIN SELECT * FROM bank; END $调用存储过程
import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import org.xxxx.jdbc.utils.JDBCUtil; public class Demo01 { public static void main(String[] args) { // 拷jar包 Connection conn = null; CallableStatement prepareCall = null; ResultSet resultSet = null; try { // 创建连接 conn = JDBCUtil.getConnection(); // 定义sql语句 String sql = "call pro_bank"; // 创建存储过程对象 prepareCall = conn.prepareCall(sql); // 执行sql语句 resultSet = prepareCall.executeQuery(); // 查看结果 while (resultSet.next()) { String username = resultSet.getString("username"); int money = resultSet.getInt("money"); System.out.println(username + "---" + money); } } catch (SQLException e) { e.printStackTrace(); } finally { // 释放资源 try { JDBCUtil.close(conn, prepareCall, resultSet); } catch (SQLException e) { e.printStackTrace(); } } } }
相关文章推荐
- JDBC基础学习笔记_02JDBC编程的mysql数据准备并编写程序
- 【JavaEE学习笔记】Servlet_02_创建Servlet方法,获取文件,响应对象
- 【JavaEE学习笔记】Hibernate_02_连接池,HQL
- MVC学习笔记四:利用Entity Framework调用存储过程
- 搬运自己的mysql学习笔记1.工具类的抽取
- 强大的DataGrid组件[6]_调用存储过程服务端分页——Silverlight学习笔记[14]
- MVC学习笔记四:利用Entity Framework调用存储过程
- 黑马程序员之C#学习笔记:后台C#调用存储过程
- 【JavaEE学习笔记】JDBC_03_批处理,获取自增长键值,DBCP,C3P0,DBUtils
- javaEE学习笔记【02】JDK新特性
- (原创)c#学习笔记10--定义类成员02--类成员的其他议题02--调用重写或隐藏的基类方法
- 【数据库学习笔记】Oracle_02_序列,分页,常用函数,jdbc,PL/SQL
- [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作
- java-oop 连接sql数据库的方法和如何调用存储过程以及jdbc事物
- 【JavaEE学习笔记】Spring_02_IoC/DI依赖注入,集合对象属性注入,自动装配,代理模式
- 【JavaEE学习笔记】Spring_04_SpringJDBC,模板模式
- JDBC学习中存储过程的调用
- 【JavaEE学习笔记】Hibernate_01_配置,核心,Session,事物,Jboss Tools
- 【JavaEE学习笔记】JDBC_01_Java链接数据库,封装数据,sql注入
- MyBatis学习笔记(六)——调用存储过程