MyException - 我的异常网
当前位置:我的异常网» 数据库 » JDBC基础学习之事务控制(4)

JDBC基础学习之事务控制(4)

www.MyException.Cn  网友分享于:2013-03-06  浏览:0次
JDBC基础学习之事务控制(四)

一、现象

写道
上图中机构表与人员信息表是1:n关系,人员信息表与用户登录信息是1:1关系
场景,删除人员信息的时候要把对应的用户登录信息删除,在这个过程中可能会出现以下几种情况,1)人员信息删除了但对应的用户登录信息没有删除 2)人员信息没删除但对应的用户登录信息删除了 3)人员信息与对应的用户登录信息都删除了,在这个过程中应该要不全部删除,要不都不删除,这两个过程中是同一个过程不能被分割。

 二、事务的概念

写道
数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

三、事务特征

写道
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响

 四、事务的类型

写道
(1)手动事务
手动事务允许显式处理若干过程,这些过程包括:开始事务、控制事务边界内的每个连接和资源登记、确定事务结果(提交或中止)以及结束事务。尽管此模型提供了对事务的标准控制,但它缺少一些内置于自动事务模型的简化操作。例如,在手动事务中数据存储区之间没有自动登记和协调。此外,与自动事务不同,手动事务中事务不在对象间流动。
如果选择手动控制分布式事务,则必须管理恢复、并发、安全性和完整性。也就是说,必须应用维护与事务处理关联的 ACID 属性所需的所有编程方法。
(2)自动事务
.NET 页、XML Web services方法或 .NET Framework 类一旦被标记为参与事务,它们将自动在事务范围内执行。您可以通过在页、XML Web services 方法或类中设置一个事务属性值来控制对象的事务行为。特性值反过来确定实例化对象的事务性行为。因此,根据声明特性值的不同,对象将自动参与现有事务或正在进行的事务,成为新事务的根或者根本不参与事务。声明事务属性的语法在 .NET Framework 类、.NET 页和 XML Web services 方法中稍有不同。
声明性事务特性指定对象如何参与事务,如何以编程方式被配置。尽管此声明性级别表示事务的逻辑,但它是一个已从物理事务中移除的步骤。物理事务在事务性对象访问数据库或消息队列这样的数据资源时发生。与对象关联的事务自动流向合适的资源管理器,诸如 OLE DB、开放式数据库连接 (ODBC) 或 ActiveX 数据对象 (ADO) 的关联驱动程序在对象的上下文中查找事务,并通过分布式事务处理协调器 (DTC) 在此事务中登记。整个物理事务自动发生。

五、示例

       5.1情况1:正常删除人员信息,删除用户信息是有异常,虽然将事务设置为手动提交,但仍然不能控制一致性,原因是他们进行操作时是两个Connection.

 

package com.zlt.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.zlt.jdbc.util.DBUtil;

public class Test5 {

	public static void main(String[] args) {

		deletePersonById(1);
		deleteUserByPid(1);
	}
	
	
	/**
	 * 根据人员ID删除人员信息
	 * @param id
	 * @return reuslt :-1,删除失败;非-1,删除成功
	 */
	public static int deletePersonById(int id){
		int result = 0;
		Connection conn = null;
		PreparedStatement pstmt = null;
		
		try {
			conn  = DBUtil.getConnection();
			conn.setAutoCommit(false);//将事务设为手动提交
			String sql = "delete from t_person where id = ?" ;
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, id);
			result = pstmt.executeUpdate();
			conn.commit();//提交事务
		} catch (SQLException e) {
			e.printStackTrace();
			result = -1;
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}//事务回滚
		}finally{
			DBUtil.close(pstmt);
			DBUtil.close(conn);
		}
		return result;
	}
	
	
	
	/**
	 * 根据人员ID删除用户信息
	 * @param pid 人员ID
	 * @return 
	 */
	public static int deleteUserByPid(int pid){
		Connection conn = null;
		PreparedStatement pstmt = null;
		int result = 0;
		try {
			conn  = DBUtil.getConnection();
			conn.setAutoCommit(false);
			String sql = "delete from user where pid = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, pid);
			Integer.parseInt("123a");
			result = pstmt.executeUpdate();
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
			result = -1;
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			DBUtil.close(pstmt);
			DBUtil.close(conn);
		}
		return result;
	}

}

   5.2改进事务控制,将两个方法的Connection控制在一个Connection

 

 

package com.zlt.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.zlt.jdbc.util.DBUtil;

public class Test5 {

	public static void main(String[] args) {
		
		Connection conn = null;
		try{
			conn = DBUtil.getConnection();
			conn.setAutoCommit(false);//将事务设为手动提交
			deletePersonById(conn,1);
			deleteUserByPid(conn,1);
			conn.commit();//提交事务
		}catch(Exception e){
			try {
				conn.rollback();//事务回滚
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			DBUtil.close(conn);
		}
	}
	
	
	/**
	 * 根据人员ID删除人员信息
	 * @param id
	 * @return reuslt :-1,删除失败;非-1,删除成功
	 */
	public static int deletePersonById(Connection conn,int id){
		int result = 0;
		PreparedStatement pstmt = null;
		
		try {
			String sql = "delete from t_person where id = ?" ;
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, id);
			result = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			result = -1;
		}
		return result;
	}
	
	
	
	/**
	 * 根据人员ID删除用户信息
	 * @param pid 人员ID
	 * @return 
	 */
	public static int deleteUserByPid(Connection conn,int pid){
		PreparedStatement pstmt = null;
		int result = 0;
		try {
			String sql = "delete from user where pid = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, pid);
			Integer.parseInt("123a");
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			result = -1;
		}
		return result;
	}
}

 

    以上示例代码虽然进行的改进但是事务还是没有控制住,只有一张表中的数据被删除了,由于在deleteUserByPid方法中出现了异常没有往上抛,被底下把异常Catch了,当然一般持久化异常都是SQLException,此处我们为了做实验才catch Exception异常

    5.3小结

写道
进行事务控制的两个条件:
1)同一个Connection 2)在被调用的方法中不能把异常给处理掉要往上面抛

 最后的代码:方法deleteUserByPid虽然有异常,但方法deletePersonById中也未删除数据,说明进行了事务回滚

 

package com.zlt.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.zlt.jdbc.util.DBUtil;

public class Test5 {

	public static void main(String[] args) {
		
		Connection conn = null;
		try{
			conn = DBUtil.getConnection();
			conn.setAutoCommit(false);//将事务设为手动提交
			deletePersonById(conn,1);
			deleteUserByPid(conn,1);
			conn.commit();//提交事务
		}catch(Exception e){
			try {
				conn.rollback();//事务回滚
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}finally{
			DBUtil.close(conn);
		}
	}
	
	
	/**
	 * 根据人员ID删除人员信息
	 * @param id
	 * @return reuslt :-1,删除失败;非-1,删除成功
	 */
	public static int deletePersonById(Connection conn,int id) throws SQLException{
		int result = 0;
		PreparedStatement pstmt = null;
		
		try {
			String sql = "delete from t_person where id = ?" ;
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, id);
			result = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			result = -1;
			throw new SQLException();
		}
		return result;
	}
	
	
	
	/**
	 * 根据人员ID删除用户信息
	 * @param pid 人员ID
	 * @return 
	 */
	public static int deleteUserByPid(Connection conn,int pid) throws SQLException{
		PreparedStatement pstmt = null;
		int result = 0;
		try {
			String sql = "delete from user where pid = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, pid);
			Integer.parseInt("123a");
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
			result = -1;
			throw new SQLException();
		}
		return result;
	}

}

    5.4 遗留的问题

         1)JDBC有大量重复的地方
         2)随着功能模块的增加维护越来越不方面,因此将数据库操作的那层抽象出来,DAO层
         3)流行的持久层开源框架:Mybatis与Hibernate

 

 

文章评论

老程序员的下场
老程序员的下场
鲜为人知的编程真相
鲜为人知的编程真相
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
编程语言是女人
编程语言是女人
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
 程序员的样子
程序员的样子
程序员应该关注的一些事儿
程序员应该关注的一些事儿
一个程序员的时间管理
一个程序员的时间管理
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Java程序员必看电影
Java程序员必看电影
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
为什么程序员都是夜猫子
为什么程序员都是夜猫子
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员的鄙视链
程序员的鄙视链
程序员和编码员之间的区别
程序员和编码员之间的区别
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员都该阅读的书
程序员都该阅读的书
10个调试和排错的小建议
10个调试和排错的小建议
每天工作4小时的程序员
每天工作4小时的程序员
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
那些争议最大的编程观点
那些争议最大的编程观点
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
漫画:程序员的工作
漫画:程序员的工作
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
总结2014中国互联网十大段子
总结2014中国互联网十大段子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
我是如何打败拖延症的
我是如何打败拖延症的
我的丈夫是个程序员
我的丈夫是个程序员
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
中美印日四国程序员比较
中美印日四国程序员比较
如何成为一名黑客
如何成为一名黑客
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有