17.12.05,web学习第十九天,还有一年,努力吧青年事务mysql

2017-12-05 19:37:47来源:CSDN作者:qq_39630225人点击

分享

事务

1. 一条sql语句就是一个默认的事物 affairs:事务

手动事务:

显示的开启事务:start transaction。一旦开启默认的事务便不 开 启了。

事务提交:commite,代表从开启到提交内部的所有语句都有效。

事务的回滚:rollback,操作不成功。

注意:在开启事务之后到提交事务之前,如果有update语句,磁 盘上没有数据,它写到了内存中,是可以query出来的。

2. Jdbc的事务操作:

默认也是自动事务,默认每执行一次executeUpdate()-自动提交。

通过API手动开启事务:

开启事务:conn.setAutoCommit(false);

提交事务:conn.commit();

回滚事务:conn.rollback();

注意:操作事务conntion必须为同一个

案例:try {Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql:///wjs", "root", "root");conn.setAutoCommit(false);Statement sta = conn.createStatement();ResultSet set = sta.executeQuery("select * from checkedperson");if (set!=null) {conn.commit();set.close();sta.close();conn.close();}} catch (Exception e) {// TODO Auto-generated catch blocktry {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}e.printStackTrace();}
3. DBUtils事务操作:

DBUtils是对JDBC的封装。它没有connectionconnectionc3p0 提供。

QueryRunner qr=new QueryRunner();有参构造将数据源(连接池)作为参数传入QueryRunnerQueryRunner会从连 接池中获得一个数据库连接资源操作数据库可给参数DataSource也可不 给参数,当不给参数时调用crud方法时需要给定Connection

案例:Dbutilsc3p0进行事务操作:因为操作事务需要给定 Connection所以使用QueryRunner的无参方法

QueryRunner qr=new QueryRunner();ComboPooledDataSource cpds = new ComboPooledDataSource();try {Connection conn = cpds.getConnection();conn.setAutoCommit(false);int i = qr.update(conn, "update ....");if (i>0) {conn.commit();conn.close();}} catch (Exception e) {// TODO Auto-generated catch blocktry {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}e.printStackTrace();}
4. pageContext.request是一个具体的request对象

requestScope是一个Map,这个Map中存放了在request作用域 中的属性键值对

5. 像除数为0ArithmeticException,强转异常,空指针异常,数组越 界异常)这种运行时异常可以通过程序员的良好编程习惯进行避 免的。

6. 总结使用事务模拟转账案例:(重要)

注意事项:service层处理web层传来的数据,调用Dao层的转 入和转出的方法。需开启事务。确定所有的conn都是同一个c onnection。在catch里面rollback()。在finally里面提交commit()

commit()方法用来结束事务。

Web层:request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");String chu = request.getParameter("chu");//从哪里转String ru = request.getParameter("ru");//转给谁System.out.println(chu+ru);String money = request.getParameter("money");//转给谁DataSource cpds = new ComboPooledDataSource();Connection conn;try {conn = cpds.getConnection();boolean b = Service.zhuan(chu,ru,conn,money);if (b) {response.getWriter().write("转账成功!");} else {response.getWriter().write("转账失败!");}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}Service层:public static boolean zhuan(String name,String ru, Connection conn, String money) {boolean isSuccess=true;try {conn.setAutoCommit(false);dao.zhuanchu(name, money, conn);int a=1/0;dao.zhuanru(ru, money, conn);} catch (Exception e) {isSuccess=false;System.out.println("系统出现异常");try {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}e.printStackTrace();}finally {try {conn.commit();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return isSuccess;}Dao层:public static void zhuanru(String name,String money,Connection conn){QueryRunner qr=new QueryRunner();try {String sql="update count set money=money+? where name=?";qr.update(conn, sql, money,name);} catch (Exception e) {e.printStackTrace();}}public static void zhuanchu(String name,String money,Connection conn){QueryRunner qr=new QueryRunner();try {String sql="update count set money=money-? where name=?";qr.update(conn, sql, money,name);} catch (Exception e) {e.printStackTrace();}}

7. 所有的方法调用用的都是同一个线程,除非新开启一 个线程!

8. ThreadLocalservice层不应该出现Connection的操作,所以使用ThreadLocal,一个线程只能绑定一个东西。底层是map key是当前线程,value是存放的数据

//获得Connection ----- 从连接池中获取private static ComboPooledDataSource dataSource = new ComboPooledDataSource();//创建ThreadLocalprivate static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();//开启事务public static void startTransaction() throws SQLException{Connection conn = getCurrentConnection();conn.setAutoCommit(false);}//获得当前线程上绑定的connpublic static Connection getCurrentConnection() throws SQLException{//从ThreadLocal寻找 当前线程是否有对应ConnectionConnection conn = tl.get();if(conn==null){//获得新的connectionconn = getConnection();//将conn资源绑定到ThreadLocal(map)上tl.set(conn);}return conn;}public static Connection getConnection() throws SQLException{return dataSource.getConnection();}//回滚事务public static void rollback() throws SQLException {getCurrentConnection().rollback();}//提交事务public static void commit() throws SQLException {Connection conn = getCurrentConnection();conn.commit();//将Connection从ThreadLocal中移除tl.remove();conn.close();}
9. 事务的特性和隔离级别 概念

ACID:原子性:事务是一个基本单位,不可分割,要么成功要么失败。

一致性:事务前后的完整性必须保持一致。

隔离性:多个事务之间数据要相互隔离。

持久性:事务一旦被提交,它对数据库的改变就是永久性的。

10. 并发访问问题-由隔离性引起的

1)脏读:B读到A尚未提交的数据

2)不可重复读:一个事物中两次读取的数据不同。一个事务提交了Update,另一个事务查询的数据不同。

3)幻读/虚读:一个事物中两次读取的数据数量不同。一个事务提交了insert,另一个事务查询的数据个数不同。

4)

解决:设置事务的隔离级别

read uncommitted都不能解决

read committed 解决脏读-oracle默认

repeatable read  可重复读取-mysql默认

Serializable:锁表,串行化

mysql数据库默认的隔离级别:select @@tx_isolation

设置mysql的隔离级别:set session transaction isolation level 设置事务隔离级别

安全性:从下到上

效率:从上到下

微信扫一扫

第七城市微信公众平台