第一次用jdbc的事务回滚,但是rollback为什么没反应?

上帝爱众生 发布于 2015/09/02 14:29
阅读 2K+
收藏 1

华为云11月刊推送:DIY微信问答机器人,高性能计算代码的20个技巧!>>>

代码:

加载中
0
张乐1024
张乐1024
//这里给你稍微改了改,这样就可以测试rollback了
    public void save() throws Exception{
    	//创建数据库连接
    	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db_dark", "root", "123456");
    	//加载驱动
    	Class.forName("com.mysql.jdbc.Driver");
    	//设置不自动提交
    	conn.setAutoCommit(false);
    	Statement stmt = conn.createStatement();
    	try{
    		String sSql = "insert into area (name) values ('hh')";
    		//执行插入操作
    		stmt.executeUpdate(sSql);
    		//这里故意让其抛出一个异常
    		String sNull = null;
    		//如果想正常执行commit提交更改,则注释下面这个判断
    		if (sNull.equals("")){
    			//上面这个判断会导致系统抛出一个空指针异常NullPointerException
    			//注意以后判断字符串是否为空的时候应该这样写
    			//if ("".equals(sNull))这样就不会报错空指针了
    		}
    
    		//如果语句执行到这里无异常,提交事物!
    		conn.commit();
    		//抛出一个运行时异常(现在抛出的异常其实不是这个新创建的,因为在上面已经抛出了空指针异常)
    		throw new RuntimeException();
    	}catch(Exception e){
    		//打印异常信息
    		e.printStackTrace();
    		//遇到异常回滚事物,不提交更改
    		conn.rollback();
    		//设置自动提交
    		conn.setAutoCommit(true);
    	}finally{
    		//非空的时候才关闭
    		if (stmt != null){
    		  stmt.close();
    		}
    		//先创建的最后关闭
    		if (conn != null){
    		  conn.close();
    		}
    	}
    }


张乐1024
张乐1024
回复 @来自爪哇岛的程序猿 : 其实rollback跟commit必须跟一个启动事物的方法,好久没写java了,你搜索一下Connection的事物处理吧,理解了事物的机制你就明白这是怎么回事儿了!
上帝爱众生
上帝爱众生
如果不设置自动提交的话就是rollback没有什么用,如果设置了自动提交,rollback就有价值了,那我不用rollback,直接不写自动提交那句代码不就行了吗?
上帝爱众生
上帝爱众生
有一点我不明白,如果按照你这种写法的话,即便是不rollback也没关系啊,因为抛异常的话就代表commit不执行,commit不执行本身就不会提交事务啊,何来回滚之说呢?
0
风象南
风象南

亲,你的异常在commit 之后抛出的,当然回滚不了了。


0
小小志
小小志
commit放在异常之后
0
如比如比
如比如比
也可以在 Commit后再执行一个数据库更新操作。
0
番茄酱汁
番茄酱汁
写代码好蛋疼啊
0
番茄酱汁
番茄酱汁
这代码太他妈奇葩了
0
bigtk
bigtk
事务都被你commit了,再抛异常就没效果了吧
0
张乐1024
张乐1024

引用来自“张乐1024”的评论

//这里给你稍微改了改,这样就可以测试rollback了
    public void save() throws Exception{
    	//创建数据库连接
    	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db_dark", "root", "123456");
    	//加载驱动
    	Class.forName("com.mysql.jdbc.Driver");
    	//设置不自动提交
    	conn.setAutoCommit(false);
    	Statement stmt = conn.createStatement();
    	try{
    		String sSql = "insert into area (name) values ('hh')";
    		//执行插入操作
    		stmt.executeUpdate(sSql);
    		//这里故意让其抛出一个异常
    		String sNull = null;
    		//如果想正常执行commit提交更改,则注释下面这个判断
    		if (sNull.equals("")){
    			//上面这个判断会导致系统抛出一个空指针异常NullPointerException
    			//注意以后判断字符串是否为空的时候应该这样写
    			//if ("".equals(sNull))这样就不会报错空指针了
    		}
    
    		//如果语句执行到这里无异常,提交事物!
    		conn.commit();
    		//抛出一个运行时异常(现在抛出的异常其实不是这个新创建的,因为在上面已经抛出了空指针异常)
    		throw new RuntimeException();
    	}catch(Exception e){
    		//打印异常信息
    		e.printStackTrace();
    		//遇到异常回滚事物,不提交更改
    		conn.rollback();
    		//设置自动提交
    		conn.setAutoCommit(true);
    	}finally{
    		//非空的时候才关闭
    		if (stmt != null){
    		  stmt.close();
    		}
    		//先创建的最后关闭
    		if (conn != null){
    		  conn.close();
    		}
    	}
    }


回复 @来自爪哇岛的程序猿 : 当你执行事物启动以后,会导致你insert的area表处于锁定状态,这时候必须有个配对的rollback或commit,这个锁才会释放。在这个锁没有释放以前,对这个表的其他更新就处于等待状态,甚至连查询也处于等待状态。如果你起了一个事物,迟迟没有提交或回滚,这时候正好其他地方也要操作area表,那么就会导致其他所有地方都处于等待状态,逻辑不对的话,可能会导致循环锁,也就是死锁!!!
返回顶部
顶部