事务与连接池

什么是事务?

事务就是一系列必须同步完成的操作,必须所有操作都成功才能能成功,否则一个失败全部失败,事务是一个整体操作

为什么需要事务?

银行案例:
		如果在转账的时候发生不可避免的异常(比如断电),此时转账操作已经进行一半,这是数据库中的数据更改了一半,一个人账户余额减少,但另一个账户余额没有增加,会出现金钱纠纷

分割线-----------------------------------------------------

			事务模板:
			//设置手动提交事务,否则默认自动
			conn.setAutoCommit(false);
				try{
					查询余额
					转帐方扣钱
					接收方加钱
					...
					conn.commit();
				}catch(Exception e){
				//回滚-->释放事务锁
				conn.rollBack();
				}
		
		/*
		 * 只有在调用了commit方法之后,数据库才会真正的发生变化.全部成功,调用commit方法.
		 * 如果失败了一定要调用rollback方法. 原因:
		 * 在开启事务的时候,就有一个事务锁的存在.必须要调用commit或者rollback才可以释放.
		 * 
		 * 事务锁锁数据库表,不释放锁的话会造成数据库崩溃
		 */
		事务的ACID属性:
  1. 原子性(Atomicity):原子在化学中,是最小单位,不可以再分割了.
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  2. 一致性(Consistency):保证数据的完整性.
    事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
  3. 隔离性(Isolation):
    事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  4. 持久性(Durability):
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

事务相关的细节:
1):默认情况下,事务在执行完DML操作就自动提交.
2):查询操作,其实是不需要事务的.但是,一般的,我们在开发中都把查询放入事务中.
3):开发中,代码完全正确,没有异常,但是就是数据库中数据不变.
意识:可能没有提交事务.

获取自动生成的主键

快速注册:
只使用账号密码等信息
此时立马完善资料的话需要拿到刚刚注册时的id
此时就需要获取自动生成id
        如何获取:
       conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                    设置要获取自动生成主键的标记.
                    ps对象去获取自动生成的主键.getLong(1);

连接池:

为什么要使用连接池(复用)
获取数据库连接对象是一个比较消耗资源,耗时的操作,而我们只是用了一下就断开了,使用连接池可以将连接对象存放在连接池中,起到一个缓存的作用
DBCP/Druid:
DataSource ds=null;
ds=DBCP/DruidDataSourceFactory.createDataSource(ps);
此处约定优于配置
driverClassName
url
username
password
------------------------------------------
public class JdbcUtil {

	private JdbcUtil() {
	}

	private static Properties ps = new Properties();
	// 连接池
	private static DataSource ds = null;

	static {
		try {
			ps.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
			// 约定优于配置
			ds = DruidDataSourceFactory.createDataSource(ps);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static Connection getConnection() {
		try {
			//使用连接池来获取数据库连接对象
			return ds.getConnection();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		throw new RuntimeException("连接异常");
	}
}

事务-主键:

public class IEmployeeDAOImplTest {
	private IEmployeeDAO dao = new EmployeeDAOImpl();

	@Test
	public void testTansaction() throws Exception {
		ResultSet rs = null;
		Connection conn = null;
		PreparedStatement ps = null;
		try {// 先查询xx账户中是否有足够的余额
			String sql = "SELECT * FROM employee WHERE name=? and salary>=?";
			conn = JdbcUtil.getConnection();
			// 设置事务手动提交,如果不设置则默认为自动提交
			conn.setAutoCommit(false);
			ps = conn.prepareStatement(sql);
			ps.setString(1, "张三");
			ps.setBigDecimal(2, new BigDecimal(10000));
			rs = ps.executeQuery();
			// ps对象使用完后需关闭,否则下方创建新的ps对象会报黄色警告--->ps未关闭
			ps.close();
			// 如果没有则提示余额不足
			if (!rs.next()) {
				System.out.println("余额不足");
				return;
			} else {
				// System.out.println(1 / 0);
				// 执行扣钱操作,从xx账户中减去 xx元
				sql = "UPDATE employee SET salary=salary-? WHERE name=?";
				ps = conn.prepareStatement(sql);
				ps.setBigDecimal(1, new BigDecimal(100));
				ps.setString(2, "张三");
				ps.executeUpdate();
				ps.close();
				// 再给xxx账户中加上xxx元
				sql = "UPDATE employee SET salary=salary+? WHERE name=?";
				ps = conn.prepareStatement(sql);
				ps.setBigDecimal(1, new BigDecimal(100));
				ps.setString(2, "李四");
				ps.executeUpdate();
				// 如果全部成功则提交事务
				conn.commit();
			}

		} catch (Exception e) {
			e.printStackTrace();
			/*
			 * 只有在调用了commit方法之后,数据库才会真正的发生变化.全部成功,调用commit方法.
			 * 如果失败了一定要调用rollback方法. 原因:
			 * 在开启事务的时候,就有一个事务锁的存在.必须要调用commit或者rollback才可以释放.
			 * 
			 * 事务锁锁数据库表,不释放锁的话会造成数据库崩溃
			 */
			// 出现异常则回滚
			try {
				if (conn != null) {
					conn.rollback();
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		} finally {
			JdbcUtil.closeResource(conn, ps, rs);
		}
	}

	@Test
	public void testAutoKey() throws Exception {
		Connection conn = null;
		PreparedStatement ps = null;
		String sql = "INSERT INTO employee (name,salary)VALUES(?,?)";
		conn = JdbcUtil.getConnection();
		// 自动获取主键
		ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
		ps.setString(1, "王昭君");
		ps.setBigDecimal(2, new BigDecimal(8000));
		ps.executeUpdate();
		//获取主键
		ResultSet gk = ps.getGeneratedKeys();
		while(gk.next()){
			Object obj=gk.getObject(1);
			System.out.println(obj);
			
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值