JDBC技术(二)事务初识 数据库连接池

接上篇JDBC技术(一)JDBC基础入门封装了JdbcUtils工具:

public class JdbcUtils {
	private static String driverClass = null;
	private static String url = null;
	private static String userName = null;
	private static String password = null;
	
	public static void scanf(String filePath) throws IOException {
		Properties pp = new Properties();
		InputStream inStream = JdbcUtils.class.getResourceAsStream(filePath);
		pp.load(inStream);
		driverClass = pp.getProperty("driverClass");
		url = pp.getProperty("url");
		userName = pp.getProperty("userName");
		password = pp.getProperty("password");
	}
	
	public static void load() throws ClassNotFoundException {
		Class.forName(driverClass);
	}
	
	public static Connection getConnection() throws SQLException {
		return DriverManager.getConnection(url, userName, password);
	}
	
	public static void close(Connection conn, PreparedStatement state, ResultSet rs) {
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(state != null) {
			try {
				state.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

接着又整理了事务的相关基本内容:

 数据库事务:

在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。组成各个数据的执行的单元,要么都成功,要么都不成功。
一个最经典的转账的例子  : A给B转100元钱。

  1. 先给A扣除掉100元 (执行单元)
  2. 再给B加上100元            (执行单元)    

这个过程就需要看成一个事务。 
在这个过程中,如果A的钱扣除之后,出现网络异常等问题,就需要回滚事务(回到二者的起始状态)
如果没有出问题那就提交这个事务。 (事务一旦提交就不可回滚)

需要注意的是

MySQL数据库的事务是默认自动提交的。

JDBC处理事务:

当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,
而不能回滚,为了让多个 SQL 语句作为一个事务执行:

  1. 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
  2. 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
  3. 在出现异常时,调用 rollback(); 方法回滚事务
  4. 若此时 Connection 没有被关闭, 则需要恢复其自动提交状态

转账问题演示,不控制事务情况下模拟异常:

public class Test4 {

    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement state = null;
	    try {
	        JdbcUtils.scanf("/db.properties");
		JdbcUtils.load();
		conn = JdbcUtils.getConnection();
                //开启事务  设置事务不自动提交只能手动提交
		//conn.setAutoCommit(false);
			
		String sql = "update t_user set money = money + ? where username=?";
		state = conn.prepareStatement(sql);
		state.setDouble(1, -100.0);
		state.setString(2, "zhang");
		state.executeUpdate();					
		
                //模拟异常	
		int i = 1 / 0;
			
		state.setDouble(1, 100.0);
		state.setString(2, "san");
		state.executeUpdate();	
			
		//能顺利执行结束  提交事务
		//conn.commit();
	    } catch (Exception e) {
		//回滚事务
//		try {
//		    conn.rollback();
//		} catch (SQLException e1) {
//		    e1.printStackTrace();
//		}
		e.printStackTrace();
	    }finally {
		JdbcUtils.close(conn, state, null);
	    }
    }

}

执行结果:

解决上述问题,需要将两个执行单元放在同一个事务当中。若带上事务在执行一次结果显示如下:

可以说显示的已经很明显了。 

事务的特性:

原子性 ---强调的是事务的不可分割的特性。    一个事务已经是最小单元了。你不能说在一个事务中再分出几个子事务。
一致性 -‐‐强调的是事务执行前后数据需要保证一致。就像上面的转账事务,无论成功与否,他两的总金额是不变的。
隔离性 ‐‐-强调的是多个事务同时操作一条记录,事务之间不能互相干扰。比如A开一个事务,B也开一个事务,但AB之间互相不能干扰。
持久性 ‐‐-强调的是事务一旦结束了,数据将永久的保存到数据库中。

不考虑事务的隔离性会引发的问题
脏读: 对于两个事务 T1,T2。T1 读取了已经被 T2 更新但还没有被提交的字段。之后,若 T2 回滚,T1读取的内容就是临时且无效的。
不可重复读: 对于两个事务 T1, T2。 T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.强调的是update,修改记录的数据。
幻读: 对于两个事务 T1,T2。 T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行之后, 如果 T1 再次读取同一个表, 就会多出几行。强调是insert,向表中添加一条数据。

事务的隔离级别(设置数据库的隔离级别,根据级别的不同,解决上述的读的问题)
读未提交(Read uncommitted) ‐‐ 什么读都解决不了  
读已提交(Read committed) ‐‐ 避免脏读,但是不可重复读和幻读有可能产生  
可重复读(Repeatable read) ‐‐ 避免脏读和不可重复读,但幻读有可能产生的  
可串行化(Serializable) ‐‐ 避免各种读 

数据库都有自己默认的隔离级别 MySQL的数据库,默认的隔离级别是Repeatable read,避免脏读和不可重复读。

数据库连接池的配置使用:

DataSource接口,SUN公司提供的接口,任何的连接池(开源的,自定义的)必须要实现该接口。我们可以通过该接口的getConnection()方法就能从连接池中获取到连接


4个核心参数的设置:任何的开源的连接池,4大参数都需要自己来设置(驱动名称,数据库连接,用户名,密码)。

以Druid为例,方式一(修改JdbcUtils中相关内容):

private static DruidDataSource dataSource = null;
	
public static void initDataSource(){
    dataSource = new DruidDataSource();
    dataSource.setDriverClassName(driverClass);
    dataSource.setUrl(url);
    dataSource.setUsername(userName);
    dataSource.setPassword(password);
    //初始化连接数
    dataSource.setInitialSize(5);
    //最大连接数
    dataSource.setMaxActive(10);
    //最大等待时长 毫秒
    dataSource.setMaxWait(2000);
}

方式二:配置文件方式properties文件中可进行如下基本配置: 

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///jdbcdemo
username=root
password=root
initialSize=5
maxActive=10
maxWait=2000
public class JdbcUtils {
	private static DataSource dataSource = null;
	
	static {
		Properties pp = new Properties();
		InputStream inStream = JdbcUtils.class.getResourceAsStream("/druid.properties");
		try {
			pp.load(inStream);
			dataSource = DruidDataSourceFactory.createDataSource(pp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() throws SQLException{
		return dataSource.getConnection();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ShardingSphere:SpringBoot2+MybatisPlus+读写分离+分库分表课程目标快速的掌握读写分离+分表的实战,即插即用适用人群IT从业人员,开发人员,Java从业者,互联网从业者,性能调优人群课程简介ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈。它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成,shardingSphere定位为关系型数据库中间件。 Sharding-JDBCSharding-JDBC是Sharding-Sphere的第一个产品,也是Sharding-Sphere的前身,是当当网开源的一个产品。定位为轻量级的Java框架,在Java的JDBC层提供额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。他们均提供标准化的数据分片、读写分离、柔性事务和数据治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。Sharding-JDBC可以通过Java,YAML,Spring命名空间和Spring Boot Starter四种方式配置,开发者可根据场景选择适合的配置方式。课程特色 本章节以尽量短的时间,为使用者提供最简单的ShardingSphere的快速入门。课程说明该课程属于系列课程,分为读写分离,分库不分表,不分库分表,分库分表,读写分离+分库分表共5个回合。本课程属于其中一个回合,请各位小哥哥们注意,课程的标题哦~

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值