Mysql事务 &数据库连接池 &DBUtiles
事务
Transaction事物指逻辑上的一组操作,组成这组操作的各个单元,要么全成功,要么全不成功。
mysql是默认自动提交事物的,每条语句都在单独的事物中
- 手动控制事物
1.开启事物:start trannsaction begin
2.提交事物:commit
3.回滚事务:rollback
- 事物的特点:
原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。
隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性::指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
- 事物的隔离级别
- 脏读:指一个事物读取另一个事物未提交的数据,
- 不可重复读:在一个事物内读取了表中的某一行数据,一个事物读取到另一个事务提交后的结果(多线程)
- 虚度:是指一个事物内读取到了别的事物插入的数据,导致前后读取不一致。
数据库通过设置事务的隔离级别防止以上的情况的发生
1.READ UNCOMMITTED :脏读、不可重复读、虚度都有可能发生
2.READ COMMITTED:避免脏读。不可重复读、虚读都有可能发生(oracle)
3.repeatable read:避免脏读、不可重复读、虚读
4.serializabale:避免脏读、不可重复读、虚读
- 使用代码来实现
1.通过conn.setAutoCommit(false )来关闭自动提交的设置。
2.提交事务 conn.commit();
3.回滚事务 conn.rollback();
@Test
public void testTransaction(){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtil.getConn();
//连接,事务默认就是自动提交的。 关闭自动提交。
conn.setAutoCommit(false);
String sql = "update account set money = money - ? where id = ?";
ps = conn.prepareStatement(sql);
//扣钱, 扣ID为1 的100块钱
ps.setInt(1, 100);
ps.setInt(2, 1);
ps.executeUpdate();
int a = 10 /0 ;
//加钱, 给ID为2 加100块钱
ps.setInt(1, -100);
ps.setInt(2, 2);
ps.executeUpdate();
//成功: 提交事务。
conn.commit();
} catch (SQLException e) {
try {
//事变: 回滚事务
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps, rs);
}
}
连接池
数据库的连接对象创建工作,比较消耗性能。
一开始现在内存中开辟一块空间(集合) , 一开先往池子里面放置 多个连接对象。 后面需要连接的话,直接从池子里面去。不要去自己创建连接了。 使用完毕, 要记得归还连接。确保连接对象能循环利用。
作用:创建连接池可以控制对服务器访问的个数。
通过装饰设计模式,重写连接,与连接池配合使用
常用的数据源配置:
1.创建池子(数据源)---创建了数据源之后,系统会自动添加连接
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
2.获取连接:dataSource.getConnection();
3.使用DBUtil查询:QueryRummer runner = new QueryRummer(getDataSource());
4.runner.query(sql,new BeanListHandler<Product>(Procduct.class),参数)
DBCP
1.导包jar
2.使用配置文件:
Connection conn = null;
PreparedStatement ps = null;
try {
BasicDataSourceFactory factory = new BasicDataSourceFactory();
Properties properties = new Properties();
InputStream is = new FileInputStream("src//dbcpconfig.properties");
properties.load(is);
DataSource dataSource = factory.createDataSource(properties);
//2. 得到连接对象
conn = dataSource.getConnection();
String sql = "insert into account values(null , ? , ?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "liangchaowei");
ps.setInt(2, 100);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
C3po
拷贝jar文件 到 lib目录
//默认会找 xml 中的 default-config 分支。
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2. 设置连接数据的信息
dataSource.setDriverClass("com.mysql.jdbc.Driver");
//忘记了---> 去以前的代码 ---> jdbc的文档
dataSource.setJdbcUrl("jdbc:mysql://localhost/bank");
dataSource.setUser("root");
dataSource.setPassword("root");
//2. 得到连接对象
conn = dataSource.getConnection();
String sql = "insert into account values(null , ? , ?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "admi234n");
ps.setInt(2, 103200);
C3PO与DBCP区别:DBCP配置文件可以自己创建,文件名随便修改,C3PO不行
WebRoot:在项目里面使用的资源,src文件不在
webxml:配置文件信息 类似外部工程的main方法。
DBUtils
封装了对应的框架 对数据表的增删改查的操作,
1 增删改
//dbutils 只是帮我们简化了CRUD 的代码, 但是连接的创建以及获取工作。 不在他的考虑范围
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
//增加
//queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000);
//删除
//queryRunner.update("delete from account where id = ?", 5);
//更新
//queryRunner.update("update account set money = ? where id = ?", 10000000 , 6);
-
直接使用框架已经写好的实现类。
-
查询单个对象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
//查询单个对象
Account account = queryRunner.query(“select * from account where id = ?”,
new BeanHandler(Account.class), 8); -
查询多个对象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource());
List list = queryRunner.query("select * from account ",
new BeanListHandler(Account.class));
-
ResultSetHandler 常用的实现类
以下两个是使用频率最高的
BeanHandler, 查询到的单个数据封装成一个对象
BeanListHandler, 查询到的多个数据封装 成一个List<对象>
ArrayHandler, 查询到的单个数据封装成一个数组
ArrayListHandler, 查询到的多个数据封装成一个集合 ,集合里面的元素是数组。
MapHandler, 查询到的单个数据封装成一个map
MapListHandler,查询到的多个数据封装成一个集合 ,集合里面的元素是map。