事务
事务的基本概念
一组要么同时执行成功,要么同时执行失败的SQL语句,是数据库操作的一个执行单元
--事务开始于
- 连接到数据库上,并执行一条DML语句(insert,update或者delete)
- 前一个事务结束,又输入了另一条DML语句.
--事务结束于
- 执行commit或者rollback语句
- 执行一条DDL语句,例如created table语句; 在这种情况下,会自动执行commit语句
- 执行一条DCL语句,例如grant语句; 在这种情况下会自动执行commit语句
- 断开与数据库的连接
- 执行一条DML语句,该语句却失败了; 在这种情况下,会为这个无效的DML语句执行rollback语句
--事务的四大特点
- atomicity(原子性)
-->表示一个事务内所有的操作是一个整体,要么全部成功,要么全部失败;
- consistency(一致性)
-->表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前的状态;
- isolation(隔离性)
-->事务查看数据时数据所在的状态,要么是另一并发事务修改它之前的状态
,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据;
- durability(持久性)
-->持久性事务完成后,它对于系统的影响是永久性的.
--事务隔离级别从低到高: 效率从高到低
- 读取未提交(Read Uncommited): A和B同时修改数据库内容 ,假设a先修改数据,A只要修改,B就能看到
- 读取已提交(Read Commited):A和B同时修改数据库内容 ,A操作全部完成并且提交后,B才能看到A的修改 ---常见
- 可重复读(Repeatable Read)
- 序列化(serializable)
1 package com.jxust.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Statement; 9 10 11 12 public class Demo05 { 13 /**Batch 14 * 测试批处理的基本方法 15 * 对于大量的批处理,建议使用Statement,因为PrepareStatement的预编译空间有限,当数据量特别大时,会发生异常 16 */ 17 18 public static void main(String[] args) { 19 Statement stmt=null; //Statement就不能使用占位符?了 20 Connection conn=null; 21 ResultSet rs=null; 22 try { //加载驱动类 23 Class.forName("com.mysql.jdbc.Driver"); 24 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","z****"); 25 26 conn.setAutoCommit(false); //第一步:取消MySQL的自动提交,设置为手动提交 27 long start=System.currentTimeMillis(); 28 stmt=conn.createStatement(); 29 30 for(int i=0;i<20000;i++){ 31 stmt.addBatch("insert into t_user(username,pwd,regTime) values('ha"+i+"',6+i,now())"); 32 } 33 34 stmt.executeBatch(); 35 conn.commit(); //提交事务 36 long end=System.currentTimeMillis(); 37 System.out.println("插入20000条信息所耗时间为:"+(end-start)); 38 39 } catch (ClassNotFoundException | SQLException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 }finally{ 43 if(rs!=null){ 44 try { 45 rs.close(); 46 } catch (SQLException e) { 47 48 e.printStackTrace(); 49 } 50 } 51 if(stmt!=null){ 52 try { 53 stmt.close(); 54 } catch (SQLException e) { 55 e.printStackTrace(); 56 } 57 } 58 if(conn!=null){ 59 try { 60 conn.close(); 61 } catch (SQLException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 } 67 }
1 package com.jxust.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 9 public class Demo06 { 10 /** 11 测试事务基本概念和用法 12 */ 13 //alt+shift+r 更名 14 public static void main(String[] args) { 15 PreparedStatement ps1=null; 16 PreparedStatement ps2=null; 17 Connection conn=null; 18 try { 19 //加载驱动类 20 Class.forName("com.mysql.jdbc.Driver"); 21 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","z***"); 22 23 conn.setAutoCommit(false);//JDBC中默认true,自动提交事务 24 25 //这两条SQL语句在同一事务里 26 ps1=conn.prepareStatement("insert into t_user(username,pwd) values(?,?)"); 27 ps1.setObject(1, "ha"); 28 ps1.setObject(2, "1335"); 29 ps1.execute(); 30 System.out.println("插入一个用户ps1"); 31 32 33 try { 34 Thread.sleep(6000); //6s 35 } catch (InterruptedException e) { 36 e.printStackTrace(); 37 } 38 39 // 失败,所以因为事务的一致性,原子性,回滚到修改前的状态 40 ps2=conn.prepareStatement("insert into t_user(username,pwd) values(?,?,?)"); 41 ps2.setObject(1, "h"); 42 ps2.setObject(2, "13"); 43 ps2.execute(); 44 System.out.println("插入一个用户ps2"); 45 46 conn.commit(); 47 48 } catch (ClassNotFoundException | SQLException e) { 49 e.printStackTrace(); 50 try { 51 conn.rollback(); //异常就回滚 52 } catch (SQLException e1) { 53 e1.printStackTrace(); 54 } 55 }finally{ 56 if(ps1!=null){ 57 try { 58 ps1.close(); 59 } catch (SQLException e) { 60 e.printStackTrace(); 61 } 62 } 63 if(conn!=null){ 64 try { 65 conn.close(); 66 } catch (SQLException e) { 67 e.printStackTrace(); 68 } 69 } 70 } 71 } 72 }
事件类型
java.Util.Date ------------>以1970年1月1号为零刻度 使用long类型(可以往后推2亿年)的数表示,单位是毫秒
--子类:java.sql.Date 表示年月日
--子类:java.sql.Time 表示时分秒
--子类:java.sql.Timestamp 表示年月日时分秒
- 时间的比较处理
--插入随机日期
--取出指定日期范围的记录
//插入随机日期
1 package com.jxust.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.SQLException; 7 import java.sql.Timestamp; 8 import java.util.Random; 9 10 public class Demo07 { 11 /** 12 测试事件处理(java.sql.Date,Time,Timestamp) 13 */ 14 //alt+shift+r 更名 15 public static void main(String[] args) { 16 PreparedStatement ps1=null; 17 Connection conn=null; 18 try { 19 //加载驱动类 20 Class.forName("com.mysql.jdbc.Driver"); 21 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","****"); 22 23 for(int i=0;i<1000;i++){ 24 ps1=conn.prepareStatement("insert into t_user(username,pwd,regTime,lastLoginTime) values(?,?,?,?)"); 25 ps1.setObject(1, "ha"+i); //做添加1000条记录的标记 26 ps1.setObject(2, "133"); 27 28 //插入随机日期 29 int rand=100000000+new Random().nextInt(1000000000); //定义一个随机数 1亿+(0,10亿) 毫秒 30 31 32 java.sql.Date date=new java.sql.Date(System.currentTimeMillis()-rand); 33 Timestamp stamp=new Timestamp(System.currentTimeMillis()-rand); 34 35 ps1.setDate(3, date); 36 ps1.setTimestamp(4, stamp); 37 ps1.execute(); 38 39 //ps1.setTimestamp(4, stamp); 如我般,没看清楚,写在这里就是错得,因为此时已经提交 40 } 41 System.out.println("输入完成"); 42 } catch (ClassNotFoundException | SQLException e) { 43 e.printStackTrace(); 44 }finally{ 45 if(ps1!=null){ 46 try { 47 ps1.close(); 48 } catch (SQLException e) { 49 e.printStackTrace(); 50 } 51 } 52 if(conn!=null){ 53 try { 54 conn.close(); 55 } catch (SQLException e) { 56 e.printStackTrace(); 57 } 58 } 59 } 60 } 61 }
//取出指定日期范围的记录
1 package com.jxust.jdbc; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Timestamp; 9 import java.text.DateFormat; 10 import java.text.ParseException; 11 import java.text.SimpleDateFormat; 12 13 public class Demo08 { 14 /** 15 测试事件处理(java.sql.Date,Time,Timestamp) 取出指定时间段的数据 16 */ 17 //alt+shift+r 更名 18 19 /** 20 * 将字符串代表的日期转为long数字(格式: yyyy-MM-dd hh:mm:ss) 21 * 22 */ 23 public static long str2Date(String dateStr){ 24 DateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 25 try { 26 return format.parse(dateStr).getTime(); 27 } catch (ParseException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 return 0; 31 } 32 33 } 34 35 public static void main(String[] args) { 36 PreparedStatement ps=null; 37 Connection conn=null; 38 ResultSet rs=null; 39 try { 40 //加载驱动类 41 Class.forName("com.mysql.jdbc.Driver"); 42 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","z***"); 43 44 // ps=conn.prepareStatement("select *from t_user where regTime>?and regTime<?"); 45 // java.sql.Date start=new java.sql.Date(str2Date("2017-8-25 7:7:7")); 46 // java.sql.Date end=new java.sql.Date(str2Date("2017-8-27 23:7:7")); 47 // ps.setObject(1,start); 48 // ps.setObject(2,end); 49 50 ps=conn.prepareStatement("select*from t_user where lastLoginTime>? and lastLoginTime<? order by lastLoginTime"); 51 Timestamp start=new Timestamp(str2Date("2017-8-26 10:10:10")); 52 Timestamp end=new Timestamp(str2Date("2017-8-26 2:2:2")); 53 ps.setObject(1, start); 54 ps.setObject(2, end); 55 56 57 rs=ps.executeQuery(); 58 while(rs.next()){ //以名字取 59 // System.out.println(rs.getInt("id")+"--"+rs.getString("username")+"--"+rs.getDate("regTime")); 60 System.out.println(rs.getInt("id")+"--"+rs.getString("username")+"--"+rs.getTimestamp("lastLoginTime")); 61 } 62 63 64 } catch (ClassNotFoundException | SQLException e) { 65 e.printStackTrace(); 66 }finally{ 67 if(ps!=null){ 68 try { 69 ps.close(); 70 } catch (SQLException e) { 71 e.printStackTrace(); 72 } 73 } 74 if(conn!=null){ 75 try { 76 conn.close(); 77 } catch (SQLException e) { 78 e.printStackTrace(); 79 } 80 } 81 } 82 } 83 }