一、未整合到SQLHelper之前
特别说明:
1、如果一个事务中,只有select那么事务控制可以忽略;
2、如果一个事务中,有多个dml语句(update,insert,delete)则需要考虑事务。
public class OracleDemo {
public static void main(String[] args) {
Connection ct = null;
try {
String sql0 = "insert into emp(empno,ename) values(121,'firePolice')";
String sql = "insert into emp(empno,ename) values(122,'Nurse')";
ct = SQLHelper.getConnection();
ct.setAutoCommit(false);
PreparedStatement ps = ct.prepareStatement(sql0);
PreparedStatement ps1 = ct.prepareStatement(sql);
ps.executeUpdate();
int a=12/0;
ps1.executeUpdate();
ct.commit();
} catch (Exception e) {
try {
ct.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally{
}
}
二、整合到SQLHelper
(executeUpdateUni)
package cn.wonders.oracle.utils;
import java.io.FileInputStream;
import java.lang.management.ManagementFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class SQLHelper {
// 定义三个变量
private static Connection ct = null;
private static PreparedStatement ps = null;
private static ResultSet rs = null;
// 连接数据库的用户名,密码,url,驱动
// 在实际开发中我们会把变量写到外部配置文件中
// 当程序启动时,我们读入这些配置信息,java.util.Properties
private static String username;
private static String password;
private static String driver;
private static String url;
// 使用静态代码块加载驱动(驱动只需要加一次)
static {
// 使用Properties类,来读取配置文件
Properties pp = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream("dbinfo.properties");
// 让pp与dbinfo.properties文件关联起来
pp.load(fis);
// 获取dbinfo.properties文件内信息
username = pp.getProperty("username");
password = pp.getProperty("password");
driver = pp.getProperty("driver");
url = pp.getProperty("url");
// 获得驱动
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
fis = null;
}
}
// 统一的curd操作
public static void executeUpdate(String sql, String[] parameters) {
try {
ct = DriverManager.getConnection(url, username, password);
ps = ct.prepareStatement(sql);
if (parameters != null) {
for (int i = 0; i < parameters.length; i++) {
ps.setString(i + 1, parameters[i]);
}
}
// 执行
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
} finally {
close(rs, ps, ct);
}
}
/**
* 统一的curd操作,作为一个事务进行控制
*/
public static void executeUpdateUni(String[] sqls, String[][] parameters) {
try {
ct = DriverManager.getConnection(url, username, password);
ct.setAutoCommit(false);
if (parameters != null) {
for (int i = 0; i < sqls.length; i++) {
ps = ct.prepareStatement(sqls[i]);
for (int j = 0; j < parameters[i].length; j++) {
ps.setString(j + 1, parameters[i][j]);
}
ps.executeUpdate();
}
} else {
for (int i = 0; i < sqls.length; i++) {
ps = ct.prepareStatement(sqls[i]);
ps.executeUpdate();
}
}
ct.commit();
} catch (Exception e) {
e.printStackTrace();
try {
ct.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
close(rs, ps, ct);
}
}
// 写一个方法进行查询操作
// sql表示要执行的sql语句
// sql select * from emp where ename=?
public static ResultSet executeQuery(String sql, String[] parameters) {
try {
// 根据实际情况我们对sql语句?赋值
// 得到连接
ct = DriverManager.getConnection(url, username, password);
// 创建ps对象,得到sql语句对象
ps = ct.prepareStatement(sql);
// 如果parameters不为null,才赋值
if (parameters != null) {
for (int i = 0; i < parameters.length; i++) {
ps.setString(i + 1, parameters[i]);
}
}
rs = ps.executeQuery();
} catch (Exception e) {
e.printStackTrace();
// 抛出运行异常
throw new RuntimeException(e.getMessage());
} finally {
// close(rs, ps, ct);
}
return rs;
}
// 写一个返回连接的方法
public static Connection getConnection() {
try {
ct = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return ct;
}
// 把关闭资源写成函数
public static void close(ResultSet rs, Statement ps, Connection ct) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
ps = null;
}
if (ct != null) {
try {
ct.close();
} catch (Exception e) {
e.printStackTrace();
}
ct = null;
}
}
public static Connection getCt() {
return ct;
}
public static PreparedStatement getPs() {
return ps;
}
}
三、Oracle中的事务
1.什么是事务?
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。
2.事务和锁
当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户改表表的结构,这里对我们用户来讲是非常重要的。
3.提交事务
当执使用commit语句可以提交事务,当执行了commit语句之后,会确认事务的变化、结束事务、删除保存点、释放锁,当使用commit语句结束事务后,其它会话将可以查看到事务变化后的新数据。
4.回退事务
在介绍回退事务前,我们先介绍一下保存点(savepoint)的概念和作用。保存点是事务中的一点,用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。
5.事务的几个重要操作
(1) 设置保存点
savepoint 保存点名;
(2) 取消部分事务
rollback to 保存点名;
(3) 取消全部事务
rollback;
6.oracle中事务处理–事务隔离级别
(1) 脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。
在oracle中没有脏读的问题。
(2) 不可重复读(nonrepeatable read):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时产生非重复读。
(3) 幻读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读。
oracle的read committed读已提交说明:
1、这里oracle缺省的事务隔离级别;
2、保证不会脏读,但可能出现非重复读和幻读。
oracle的serializable可串行化说明:
1、serializable就是使事务看起来象是一个接着一个地顺序地执行(从效果上可以这样理解);
2、仅仅能看见在本事务开始前由其它事务提交的更改和在本事务中所做的更改;
3、保证不会出现脏读、不可重复读和幻读;
4、serializable隔离级别提供了read-only事务所提供的读一致性(事务的读一致性),同时又允许DML(update/insert/delete)操作
oracle的read only读一致性说明:
1、遵从事务级的读一致性,仅仅能看见在本事务开始前由其它事务提交的更改;
2、不允许在本事务中进行DML(insert/update/delete)操作;
3、read only是serializable的子集。它们都避免了不可重复读和幻读。区别是在read only中是只读;而在serializable中可以进行DML操作。