关于jdbc批处理&事务概念与性质

提纲:
1. JDBC使用快速回顾
2. 批处理
3. 事务

####复习

  1. 怎样注册驱动
                Class.forName("com.sql.jdbc.Driver");

2.怎样获取连接对象

             DriverManager.getConnection(url,name,password);
            url作用:通过url可以知道具体加载哪一个驱动
            
            mysql的url可以简写:jdbc:myql:///mydb
  1. 怎样获取可以操作sql语句的对象
                Statement st=conn.createStatement();      
                
                st.executeQuery();
                st.executeUpdate();                
                st.execute();
                
                PreparedStatement pst=conn.prepareStatement(sql);   //占位符是?
                setXXX()
                
                executeQuery();
                pst.executeUpdate();

4.执行查询语句后,可以得到ResultSet

                ResultSet  rs=st.executeQuery(sql);
                
                rs.next();
                
                getObject()
                getInt();

5.关闭资源

                rs.close();
                st.close();
                conn.close();     

##关于多数据处理.
###批处理
批处理应用:一次可以执行多条sql语句

    批处理有两种方式
            1.Statement
                         addBatch(String sql)  //将多条sql语句回到批处理中
                         cleaarBatch();        //清空所有的sql
                         executetBatch();      //执行一批sql     
            2.PreparedStatement
                         addBatch();           //添加SQL语句回到批处理
                         executeBaatch();      //批量执行sql

####Statement与PreparedStatement区别
1.Statement适合执行不同的sql语句 PreparedStatement适合执行相同的sql语句
2.Statement在执行时比PreParedStatement的效率低1
####看两个demo吧
我先把jdbc封装到一个utils里面

package cn.lawfree.JDBC.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;

public class JdbcUtil {

	private static String DRIVER;
	private static String URL;
	private static String USERNAME;
	private static String PASSWORD;

	// private static final ThreadLocal tl = new
	// ThreadLocal();

	static {
		// 获取连接数据
		ResourceBundle bundle = ResourceBundle.getBundle("db");
		DRIVER = bundle.getString("driver");
		URL = bundle.getString("url");
		USERNAME = bundle.getString("username");
		PASSWORD = bundle.getString("pwd");

	}
	static {
		try {
			Class.forName(DRIVER);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("加载驱动加载驱动");
		}
	}


	// 创建一个可以去Connection对象的方法
	public static Connection getConnection() {
		Connection conn = null;

		try {
			conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

		} catch (SQLException e) {
			// throw new RuntimeException("获取连接失败");
			e.printStackTrace();
		}
		return conn;
	}

	// 关闭方法Connection方法
	public static void closeConnection(Connection conn) throws SQLException {
		if (conn != null) {
			conn.close();
		}
	}

	// 关闭Statement方法
	public static void closeStatement(Statement st) throws SQLException {
		if (st != null) {
			st.close();
		}
	}

	// 关闭ResultSet方法
	public static void closeResultSet(ResultSet rs) throws SQLException {
		if (rs != null) {
			rs.close();
		}
	}
}

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import cn.lawfree.JDBC.util.JdbcUtil;

//statement的批处理
public class Demo1 {
	public static void main(String[] args) throws SQLException {

		String sql0 = "use t_testpatch";
		String sql1 = "create table user(id int,name varchar(20),sex varchar(10),age int  )";
		String sql2 = "insert into user values(1,'tom','male','20')";
		String sql3 = "insert into user values(2,'fox','male','30')";
		String sql4 = "update user set age=40 where id=1";

		// 1.获取Connection对象
		Connection conn = JdbcUtil.getConnection();
		// 2.获取Statement对象
		Statement st = conn.createStatement();

		// 3.将sql语句添加到st中
		st.addBatch(sql0);
		st.addBatch(sql1);
		st.addBatch(sql2);
		st.addBatch(sql3);
		st.addBatch(sql4);

		// 4.批处理
		st.executeBatch();

		// 5.关闭资源
		st.close();
		conn.close();
	}
}
package cn.lawfree.JDBC.batch;

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

import cn.lawfree.JDBC.util.JdbcUtil;

//PreparedStatement执行批处理 
public class demo2 {
	public static void main(String[] args) throws SQLException {
		Connection conn = JdbcUtil.getConnection();
		String sql = "insert into user values(?,?,?,?)";
		PreparedStatement pst = conn.prepareStatement(sql);

		for (int i = 1; i < 10; i++) {
			pst.setInt(1, i);
			pst.setString(2, "name" + i);
			pst.setString(3, "male");
			pst.setInt(4, 20 + (int) (Math.random() * 10));

			// 添加到批处理
			pst.addBatch();

		}

		// 执行
		pst.executeBatch();

		pst.close();
		conn.close();
		conn.close();
	}
}

##事务
通俗地讲:事务是指一组操作,组成这组操作的功能,要不全部成功,要不全部不成功
关于事务
1.数据库本意识提供事务.
2.jdbc提供对事务的处理.

###1.数据库中事务处理
mysql事务是自动提交的.------默认情况,事务自动提交,一条sql语句是一个单独事务
oracle事务是手动提交. commit

            start transaction ------开启事务
            rollback          ------回滚
            commit            ------提交事务      

mysql可以设置提交方式吗?
show variables like ‘%commit’; 查看提交方式
set autocomit=off/on; 关闭自动提交

演示 start transaction rollback commit使用

                 create table acount(
                      id int,
                      name varchar(10),
                      money int
                 )       
                 
                 insert into account values(1,'aaa',1000);      
                 insert into account values(2,'bbb',1000);          
                 insert into account values(3,'ccc',1000);           
                 
                 aaa--汇款给-->bbb  500元
                 update acount set money=money-500 where name='aaa';  从aaa前去500.
                 update acount set money=money+500 where name='bbb';  给bbb加上500.

事务处理操作
1.start transcation.
2.

                 update acount set money=money-500 where name='aaa';  从aaa前去500.
                 update acount set money=money+500 where name='bbbb';  给bbb加上500.

3.发现数据有问题–>rollback;
4. commit

###2.jdbc事务处理

在Connection中提供

                             setAutoCommit(boolean f);  //-----设置事务的提交方式
                             rollback();                //-----事务回滚 
                             commit();                  //-----事务提交

这三个方法是jdbc中事务的三个方法
Savepoint 回滚点
con.setSavepoint(); 获取(设置回滚点)

                             rollback(Savepoint) ;//这样使用 

还是来看一个demo

package cn.lawfree.JDBC.transaction;

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

//这是转账操作的底层实现
//包含两个方法,存钱和取钱方法
public class AccountDao {

	// 存储
	public void save(double money, String name, Connection conn)
			throws SQLException {
		String sql = "update account set money=money+? where name=? ";

		PreparedStatement pst = conn.prepareStatement(sql);

		pst.setDouble(1, money);
		pst.setString(2, name);

		int row = pst.executeUpdate();
		if (row == 0) {
			throw new RuntimeException("存款失败");
		}

		pst.close();

	}

	// 取钱
	public void get(double money, String name, Connection conn)
			throws SQLException {
		String sql = "update account set money=money-? where name=?";

		PreparedStatement pst = conn.prepareStatement(sql);

		pst.setDouble(1, money);
		pst.setString(2, name);

		int row = pst.executeUpdate();
		if (row == 0) {
			throw new RuntimeException("存款失败");
		}
		pst.close();

	}
}

package cn.lawfree.JDBC.transaction;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;

import cn.itcast.lawfree.util.JdbcUtil;

//这是转账支付的service操作,主要用于实现事务逻辑
//我们给它添加一个回滚的逻辑
public class AccountService {
	public void hk() {

		AccountDao dao = new AccountDao();
		Connection conn = JdbcUtil.getConnection();
		// 开启事务 ------setAutoCommit(false);

		Savepoint point = null;

		try {
			conn.setAutoCommit(false);
			// 1.从a账户取钱500

			dao.get(500, "aaa", conn);

			// 设置一个回滚点
			point = conn.setSavepoint();

			// 2.向账户存500;
			dao.save(500, "bbb", conn);
		} catch (SQLException e) {
			// 回滚
			// rollback
			try {
				conn.rollback(point);
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {

			try {
				// commit
				conn.commit();
				// 关闭conn
				JdbcUtil.closeConnection(conn);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}
}

###事务的特性(ACID)
1.原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
2.一致性(Consistency)
事务前后数据的完整性必须一致
3.隔离性(Isolation)
事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间的数据要相互隔离
4.持久性(Durability)
持久性是指一个事务一旦被提交.它对数据库中数据的改变是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

重点介绍事务的隔离性
如果不考虑事务的隔离性会引发的问题

  1. 脏读 一个事务读取到另一个事务的未提交数据

                             A 转账给B 100,未提交
                             B 查询账户多了100
                             A 回滚
                             B 查询账户那100不见了
    

2.不可重复读 两次读取的数据不一致(强调的是update操作,数据的总条数不变

                            将隔离级别设置成  Read committed.查看是否可以解决脏读问题

演示不可重复读:

                            A 转账 给B 100,未提交
                            B 查询 金额没变(级别是: Read committed  避免了脏读)
                            A 查询,发现金额多了100
                            
                            两次读取到的数据不一致,出现了不可重复读.
  1. 虚读(幻读) 两次读取的数据不一致(强调的是insert操作,数据的总条数变化)

###事务的隔离级别
数据库中一共有四种隔离级别
1.Serializable:可避免脏读 不可重复读 虚读情况的发生.(串行化)
2.Repeatable read:可避免脏读 不可重复读情况发生(输入一个commit即可得到最新数据) .(可重复读)不可避免虚读
3.Read committed:可避免脏读情况发生(读已提交)
4.Read uncommitted:最低级别,以上情况均无法保证(读未提交)

####mysql默认的隔离级别是什么?怎么设置隔离级别?

mysql默认隔离级别是Repeatable read 级别

                    select @@tx_isolation   查询当起事务隔离级别 
                    
                    set session transaction isolation level  设置事务隔离级别
                              
                    set session transaction isolation level Read uncommitted;
                    
                    serializable会出现锁表情况      
                    
                    安全性越高的,性能越低    

下面我们用mysql具体来看看不同的事务隔离级别会发生什么.

  1. 准备一个表account,用两个Mysql打开打开,就像这样:
  2. 我们已经知道Mysql默认事务隔离级别是Repeatable read,我们先来看看能不能避免脏读和不可重复读:
  3. 由于csdn传图片卡到爆?以后有空再弄…

###JDBC设置事务的隔离级别

        在connection接口中提供
        setTransactionIsolation(int level)用来设置事务的隔离级别
        
        四个级别字段          

小结:
1.Statementment与PreparedStatement执行批处理的特点
Statement适合执行多条不同的sql
PreparedStatement适合执行相同的sql
2.事务
一组操作,要么全部成功,要么全不成功
3.mysql中的事务管理
1.start transcation rollback commit.
2.mysql中的事务默认是
autocommit=on 可手动修改
autocommit=off
oracle数据库它的事务必须手动提交
4.jdbc管理事务

                     Connection下的
                              1.setAutoCommit(boolean flag)
                              2.rollback
                              3.commit
                              4.Savepoint回滚点

5.事务特性 (重点)

                      ACID
                      原子性    一致性    gelixing    持久性                                                                                      

6.隔离性
不考虑隔离性会发生什么问题?

                              1.脏读     2.不可重复读    3虚读(幻读)

7.隔离级别

                      1.Serializable:可避免脏读 不可重复读 虚读情况的发生.(串行化)
                      2.Repeatable read:可避免脏读 不可重复读情况发生(输入一个commit即可得到最新数据) .(可重复读)不可避免虚读    
                      3.Read committed:可避免脏读情况发生(读已提交)
                      4.Read uncommitted:最低级别,以上情况均无法保证(读未提交)    

8.jdbc怎样设置事务的隔离级别

                      setTranscationIsolation(int level)     

你可能感兴趣的:(Java基础)