事务及数据库的隔离级别

package com.java;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

public class TransactionTest {

    /**
     * 测试事务的隔离级别 在 JDBC 中,可以用 Connection 的 setTransactionIsolation()
     * 方法来设置事务的隔离级别
     */
    @Test
    public void testTransactionIsolationUpdate() {
        Dao dao = new Dao();
        Connection connection = null;
        try {
            connection = JDBCTools.getConnection();
            // 设置不自动提交
            connection.setAutoCommit(false);
            
            String sql = "UPDATE user SET balance = balance - 500 WHERE id = 1";
            dao.update(connection, sql);
            
            connection.commit();//加一个断点,使程序到这儿暂停,测试其他线程读取到的是否是未提交的数据
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
    
    @Test
    public void testTransactionIsolationRead() {
        String sql = "SELECT balance FROM user WHERE id = 1";
        
        Integer balance = getForValue(sql);
        
        System.out.println(balance);
    }

    // 返回某条记录的某一个字段的值 或 一个统计的值(一共有多少条记录等.)
    public <E> E getForValue(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 1.得到结果集
            connection = JDBCTools.getConnection();
            /*
             * 可以在 cmd 中设置mySql的隔离级别
             * ① mysql -uroot -p123456
             * 查看当前 mySql 的隔离级别
             * ② SELECT @@tx_isolation;
             * 设置当前 mySql 的隔离级别
             * ③ set transaction isolation level read committed;
             * 设置数据库系统全局的隔离级别
             * ④ set global transaction isolation level read committed;
             */
            // 查看mySql 默认的隔离级别
            System.out.println(connection.getTransactionIsolation());
            
            // 读取未提交的数据
//            connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
            // 读取已提交的数据
            connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
            
            
            preparedStatement = connection.prepareStatement(sql);

            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i + 1, args[i]);
            }

            resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                return (E) resultSet.getObject(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Tom 给 Jerry 汇款500 元。
     * 
     * 关于事务: 1. 如果多个操作,每个操作使用的是单独的链接,则无法保证事务. 2. 具体步骤: 1). 事务操作开始前,开始事务: 取消
     * Connection 的默认提交行为. connection.setAutoCommit(false); 2).
     * 如果事务的操作都成功,则提交事务: connection.commit(); 3). 回滚事务: 若出现异常,则在 catch 块中回滚事务
     * connection.roolback();
     */
    @Test
    public void testTransaction() {

        Dao dao = new Dao();
        Connection connection = null;

        try {
            connection = JDBCTools.getConnection();
            // 开始事务: 取消默认提交
            connection.setAutoCommit(false);

            String sql = "UPDATE user SET balance = balance - 500 WHERE id = 1";

            dao.update(connection, sql);

            // 增加一个异常,看事务是否回滚
            int i = 10 / 0;
            System.out.println(i);

            sql = "UPDATE user SET balance = balance + 500 WHERE id = 2";

            dao.update(connection, sql);

            // 提交事务
            connection.commit();

        } catch (Exception e) {
            e.printStackTrace();

            try {
                // 回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }

        } finally {
            JDBCTools.release(null, null, connection);
        }
    }

}

 

posted @ 2016-10-10 19:41  删库到跑路  阅读(279)  评论(0编辑  收藏  举报