java演示数据库并发,设置数据库的隔离级别

数据库的并发问题

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种 并发问题:

脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段。之后, 若 T2 回滚, T1读取的 内容就是临时且无效的。

不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段。之后, T1再次读取同一个字 段, 值就不同了。

幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行。之后, 如 果 T1 再次读取同一个表, 就会多出几行。

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问 题。 一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰 程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。

数据库的四种隔离级别:

以user_table表为例,表的结构如下:

 

 

下面代码演示读未提交数据和读已提交数据 :


import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

import org.junit.Test;

import com1jdbcConnection.jdbcConnection;

public class TransactionTest {
    //修改操作
	public void update(Connection conn,String sql,Object ...args){//sql中占位符的个数与可变形参的长度一致
		//1、编译sql语句
		PreparedStatement ps=null;
		try {
			ps = conn.prepareStatement(sql);
			//2、填充占位符
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1, args[i]);
			}
			//3、执行
			ps.execute();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//4、关闭资源
			jdbcConnection.CloseResource(null, ps);
		}
	}
	//查询操作
	@Test
	public void testTransactionSelect() throws Exception{
		Connection conn=jdbcConnection.connection();
		conn.setAutoCommit(false);
		//设置数据库的隔离级别
		/*TRANSACTION_READ_UNCOMMITTED:未解决脏读问题
		 *TRANSACTION_READ_COMMITTED:解决了脏读问题
		 */
		conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//当前是读已提交数据
		//查看当前的隔离级别
		System.out.println("隔离级别:"+conn.getTransactionIsolation());
		String sql="select user,password,balance from user_table where user=?";
		User user=update(conn,User.class,sql,"CC");
		System.out.println(user.toString());
		conn.commit();
		conn.setAutoCommit(true);
		jdbcConnection.CloseResource(conn, null);
		
	}
	//修改操作
	@Test
	public void testTransactionUpdata() throws Exception{
		Connection conn=jdbcConnection.connection();
		conn.setAutoCommit(false);
		
		String sql="update user_table set balance=? where user=?";
		update(conn,sql,5000,"CC");

		Thread.sleep(5000);
		System.out.println("修改结束!");
		jdbcConnection.CloseResource(conn, null);
	}
	//通用查询操作,返回一条数据
	public <T> T update(Connection conn,Class<T> clazz,String sql,Object ...args){
		
		//1、实例化PreparedStatement对象
		PreparedStatement ps=null;
		
		ResultSet rs=null;
		try {
			ps = conn.prepareStatement(sql);
			//2、填充占位符
			for(int i=0;i<args.length;i++){
				ps.setObject(i+1, args[i]);
			}
			//3、执行,获取结果集
			rs = ps.executeQuery();
			//4、获取元数据
			ResultSetMetaData rsmd=rs.getMetaData();
			//5、获取列数
			int columnValue=rsmd.getColumnCount();
			if(rs.next()){
				T t=clazz.newInstance();
				for(int i=0;i<columnValue;i++){
					//6、获取列名
					String columnName=rsmd.getColumnLabel(i+1);
					//7、获取当前列的值
					Object value=rs.getObject(i+1);
					//8、给t对象指定的columnName属性,赋值为columnValue:通过反射
					Field field=clazz.getDeclaredField(columnName);
					field.setAccessible(true);
					field.set(t, value);
				}
				return t;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//9、关闭资源
			jdbcConnection.CloseResource(null, ps,rs);
		}
		return null;
		
	}
}

代码中User类如下:

 


public class User {
	private String user;
	private String password;
	private int balance;
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	@Override
	public String toString() {
		return "User [user=" + user + ", password=" + password + ", balance=" + balance + "]";
	}
}

  代码中jdbcConnection类的构造查看:封装数据库的连接关闭操作_qq_46053741的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值