`

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

    博客分类:
  • 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

 

 

  • 大小: 101.2 KB
0
0
分享到:
评论

相关推荐

    详细标准的jdbc学习资料

    一、JDBC基础 1. JDBC驱动:JDBC驱动是连接Java应用程序和数据库之间的桥梁。有四种类型的JDBC驱动,分别是:JDBC-ODBC桥接驱动、网络协议驱动、部分Java驱动和完全Java驱动(类型4)。 2. 连接数据库:使用`Class...

    JSP JDBC 学习笔记(基础)

    ### JDBC基础 1. **JDBC简介**:JDBC是Java API,用于与各种数据库进行连接,执行SQL语句并处理结果。它提供了一套统一的接口,使得开发者无需关心底层数据库的细节。 2. **JDBC驱动**:根据不同的数据库系统,...

    java(jdbc)学习

    JDBC提供了对事务的全面支持,包括手动控制事务的开始、提交和回滚。事务管理对于保持数据一致性至关重要。 #### 八、PreparedStatement 接口 PreparedStatement是Statement的子类,支持预编译SQL语句,提高了SQL...

    非常好的JDBC学习文档

    总的来说,这个"非常好的JDBC学习文档"将涵盖从基础到进阶的JDBC知识,包括驱动管理、连接创建、SQL执行、事务处理、异常控制、批处理以及连接池的使用。通过学习,你不仅可以掌握数据库操作,还能理解如何在实际...

    达内jdbc学习笔记

    总的来说,"达内jdbc学习笔记"涵盖了JDBC基础、数据库连接、SQL执行、结果集处理、事务管理和性能优化等多个关键知识点,对Java开发者来说是宝贵的参考资料。通过深入学习和实践,可以熟练地使用Java进行数据库操作...

    jdbc学习手册

    6. **事务管理**:JDBC支持事务的概念,可以使用`Connection`对象的`setAutoCommit(false)`关闭自动提交,然后通过`commit()`和`rollback()`控制事务边界。 7. **批处理**:批量执行SQL语句可以提高性能,通过`...

    JDBC学习资料

    这份“JDBC学习资料”将带你走进这个领域,通过PPT文件,你可以系统地学习到如何使用JDBC进行数据库连接、SQL语句执行、结果集处理以及事务管理等核心概念,为你的Java数据库编程打下坚实基础。

    JDBC笔记_JDBC学习笔记_

    一、JDBC基础 1. JDBC驱动程序:JDBC驱动是连接Java应用程序和数据库之间的桥梁。根据实现方式,JDBC驱动分为四种类型:类型1(JDBC-ODBC桥接),类型2(部分Java,部分Native),类型3(纯Java网络协议驱动),...

    jdbc学习文件

    1. **JDBC基础**:从"day01"到"day05"的文件可能涵盖了JDBC的基本概念和用法,包括JDBC驱动的分类(如Type 1、Type 2、Type 3、Type 4及JDBC-ODBC桥),以及JDBC API的核心类和接口,如`DriverManager`、`Connection...

    JDBC个人学习笔记

    【JDBC学习笔记】 JDBC,全称Java Database Connectivity,是Java编程语言中用来规范客户端程序如何访问数据库的应用程序接口,由Sun Microsystems公司提出。它为程序员提供了标准的API,使得开发者可以使用Java...

    JDBC基础.doc

    在学习JDBC基础时,主要涉及以下几个关键知识点: 1. **快速入门**: - 安装Java和JDBC:确保你拥有与JDBC兼容的JDK版本,通常JDBC会随JDK一起安装。 - 安装驱动程序:根据选择的数据库,安装相应的JDBC驱动,如...

    JDBC基础培训课件ppt

    **JDBC基础培训课件** Java Database Connectivity (JDBC) 是Java编程语言中用于与数据库交互的一组接口和类。它是Java平台的标准部分,由Java SE的Java Database Connectivity API提供,使得开发者能够编写数据库...

    Java Dao JDBC 基础练习代码

    4. 事务管理:对于涉及多条SQL语句的操作,如下单过程,可能需要使用JDBC的`Connection`对象进行事务控制,确保数据的一致性。例如,`Connection.setAutoCommit(false)`开启手动事务,然后在所有操作成功后调用`...

    发个基础jdbc

    6. **事务管理**: JDBC支持事务处理,可以通过`Connection`对象的`setAutoCommit(false)`关闭自动提交,并使用`commit()`和`rollback()`控制事务边界。 7. **预编译SQL**: 对于频繁执行的SQL语句,可以使用`...

    oracle 基础教程 jdbc 以及样式demo 各种数据库的连接方法

    一、JDBC基础 1. JDBC驱动管理:在Java程序中,我们需要加载对应的JDBC驱动来建立与Oracle数据库的连接。Oracle提供了四种类型的JDBC驱动,从早期的JDBC-ODBC桥接驱动到现代的 thin 驱动,每种都有其特定的应用场景...

    JDBC 实战教程-尚硅谷学习笔记 ,2022版

    JDBC基础** - **JDBC驱动类型**:JDBC驱动分为四种类型,分别是JDBC-ODBC桥接驱动、本地API驱动、网络纯Java驱动和Java数据库连接(JDBC-4.0)驱动。每种驱动有其适用场景和优缺点。 - **数据库连接**:使用`...

    JDBC入门基础讲座

    JDBC支持事务控制,包括提交(commit)、回滚(rollback)和保存点(savepoint)。事务的ACID特性(原子性、一致性、隔离性和持久性)确保了数据的完整性和一致性。 ### 错误处理和异常处理 在JDBC编程中,应捕获...

    JDBC学习手册 共两套

    一、JDBC基础 1. JDBC驱动:JDBC驱动分为四种类型,从1型到4型,4型驱动(Java数据库连接)是最新的,完全基于纯Java,无需依赖数据库厂商提供的本地库。驱动管理器负责加载合适的驱动并建立与数据库的连接。 2. ...

Global site tag (gtag.js) - Google Analytics