一:概念
数据库事务:
一组逻辑操作单元,使数据从一种状态变换到另一种状态
事务处理:
一个事务执行多个操作时,要么所有事物都被提交,那么这些修改永久保存;要么放弃所有修改,事务回滚到最初状态
自动提交:
? ? ? ? ? ? ? ? DDL操作执行,自动提交
? ? ? ? ? ? ? ? DML:通过set autocommit=false 取消自动提交
事务ACID属性
数据库并发问题
脏读:T2更新字段但没提交,T1读取了,T2回滚,T1读取的是无效的
不可重复读:T1读取字段,T2更新字段,T1再读值就变化了
幻读:T1读取字段,T2在表中插入新行,T1再读就多出几行
事务隔离级别
?考虑事务的增删改查
Connection设为形参,在调用方法时用一个Connection串起所有操作,关闭连接时不能将Connection关闭
public class test {
@Test
public void testUpdateWithTransaction() {
Connection connection = null;
try {
connection = JDBCutils.getConnection();
//1.取消数据自动提交
connection.setAutoCommit(false);
String sql1 = "update user_table set balance =balance-100 where user=?";
update(connection, sql1, "AA");
String sql2 = "update user_table set balance =balance+100 where user=?";
update(connection, sql2, "BB");
System.out.println("转账成功");
//2.提交数据
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
//3.若发生异常会被catch,需要回滚数据
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} finally {
//关闭连接,若不关闭需要将自动提交改为true
JDBCutils.closeResource(connection, null);
}
}
//通用的增删改(version2.0 考虑事务)
public void update(Connection connection, String sql, Object... args) {
PreparedStatement ps = null;
try {
//1.预编译sql语句
ps = connection.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.执行
jdbc.util.JDBCutils.closeResource(null, ps);//外部传入的connection在外部关闭
}
}
//通用的查询操作,用以返回数据表中一条数据(version2.0 考虑事务)
public <T> T QueryCommon(Connection connection,Class<T> clazz, String sql, Object... args) throws Exception {
//1.预编译sql语句
PreparedStatement ps = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
//2.执行并返回结果集
ResultSet resultSet = ps.executeQuery();
ResultSetMetaData rsmd = resultSet.getMetaData();//元数据
int columnCount = rsmd.getColumnCount();//列数
//3.处理结果集
if (resultSet.next()) {
T t = clazz.getConstructor().newInstance();
for (int i = 0; i < columnCount; i++) {
Object columnValue = resultSet.getObject(i + 1);//将columnValue赋值给columnName
String columnLabel = rsmd.getColumnLabel(i + 1);//获取列的别名
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnValue);
}
return t;
}
//关闭流
JDBCutils.closeResource(connection,ps,resultSet);
return null;
}
@Test
public void testTransactionSelect() throws Exception {
Connection connection = JDBCutils.getConnection();
//获取当前的隔离级别
System.out.println(connection.getTransactionIsolation());
//设置当前隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
//取消自动提交
connection.setAutoCommit(false);
String sql="select user,password,balance from user_table where user=?";
User user = QueryCommon(connection, User.class, sql, "CC");
System.out.println(user);
}
}
|