事务:就是保证操作的一致性,所有的操作要么全部成功,要么全部失败;
事务本身具有四个特性:原子性、一致性、隔离性或独立性、持久性;
原子性:
是事务最小的单元,是不可在分割的单元,相当于一个个小的数据库操作,这些操作必须同时完成,
如果有一个失败了,则一切的操作完全失败;
假设A给B转账,则这时A转账和B接账是两个不可分的操作,如果A的转账失败,则B的
操作也肯定无法成功;
一致性:
指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作,
则系统会维持有效性,如果事务出现了错误,则回到原始状态,也要维持其有效性,这样
保证事务在开始时和结束时系统处于一致状态;
隔离性:
多个事务可以同时进行,彼此之间无法访问,只有当事务完成最终操作的时候,才可以看到结果;
持久性:
当一个系统崩溃时,一个事务依然可以坚持提交,当一个事务完成后,操作的结果保存在磁盘中,
永远不会被回滚;
如果要想操作事务的话,则必须按照以下的步骤完成;
1.取消掉自动提交:每次执行数据库更新的时候,实际上发出sql命令后就已经提交上去了;
2.开始事务:
3.进行一系列的操作:
4.如果操作全部合格,则提交事务:
5.如果发现有一个地方有问题,则可以进行回滚:
6.或者设置一个SAVEPOINT保证事务的提交点:
//sql 语句:
set autocommit=0;---取消自动提交;
begin;---启动事务;
insert into user(name,password,age,sex,birthday) values ('仰望','456',21,'男','1988-08-08');
rollback;---事务回滚,取消commit以前的所有操作;
commit;---提交,提交后用rollback也不能撤销的;
/*---创建数据库表
drop table user;
create table user(
id int auto_increment primary key,
name varchar(30) not null,
password varchar(32) not null,
age int not null,
sex varchar(2) default '男',
birthday Date
);
*/
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.Blob;
import java.sql.ResultSet;
import java.util.*;
import java.io.*;
import java.text.*;
public class Demo{
//定义数据库的驱动程序
public static final String DBDRIVER="org.gjt.mm.mysql.Driver";
//定义数据库的连接地址:
public static final String DBURL="jdbc:mysql://localhost:3306/lid";
//定义数据库的用户名
public static final String DBUSER="root";
//定义数据库的密码
public static final String DBPASSWORD="123";
public static void main(String args[]) throws Exception{
Connection conn=null;
Statement stmt=null;//数据库操作
ResultSet rs=null;
//加载数据库驱动
Class.forName(DBDRIVER);//创建一个该驱动类的Class对象;
conn=DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
stmt=conn.createStatement();
//加入批处理
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_1','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_2','456',21,'男','1988-08-08')");
//此时让sql语句中多以个"'"这样语句就会有错误
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_'3','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_4','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_5','456',21,'男','1988-08-08')");
int i[]=stmt.executeBatch();
System.out.println("更新了:"+i.length+"条数据");
stmt.close();
conn.close();
}
}
以上的操作只是将第三条sql语句不正确的没有执行,而其他的都插入成功了,那么如果这五条数据有关联的话,
那么上面就会出现错误-----有一个出错,其他的也不应该插入进去;
以下操作增加了事务处理:
/*---创建数据库表
drop table user;
create table user(
id int auto_increment primary key,
name varchar(30) not null,
password varchar(32) not null,
age int not null,
sex varchar(2) default '男',
birthday Date
);
*/
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.Blob;
import java.sql.ResultSet;
import java.util.*;
import java.io.*;
import java.text.*;
public class Demo{
//定义数据库的驱动程序
public static final String DBDRIVER="org.gjt.mm.mysql.Driver";
//定义数据库的连接地址:
public static final String DBURL="jdbc:mysql://localhost:3306/lid";
//定义数据库的用户名
public static final String DBUSER="root";
//定义数据库的密码
public static final String DBPASSWORD="123";
public static void main(String args[]) throws Exception{
Connection conn=null;
Statement stmt=null;//数据库操作
ResultSet rs=null;
//加载数据库驱动
Class.forName(DBDRIVER);//创建一个该驱动类的Class对象;
conn=DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
conn.setAutoCommit(false);//取消自动提交
stmt=conn.createStatement();
//加入批处理
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_1','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_2','456',21,'男','1988-08-08')");
//此时让sql语句中多以个"'"这样语句就会有错误
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_'3','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_4','456',21,'男','1988-08-08')");
stmt.addBatch("insert into user(name,password,age,sex,birthday) values ('仰望_5','456',21,'男','1988-08-08')");
try{
int i[]=stmt.executeBatch();
System.out.println("更新了:"+i.length+"条数据");
conn.commit();//能执行到此所以sql语句没有错误,所以可以提交
}
catch(Exception e){//如果有错误
try{
conn.rollback();
}
catch(Exception ex){
ex.printStackTrace();
}
}
stmt.close();
conn.close();
}
}
要实现事务操作其实就添加几句:
conn.setAutoCommit(false);
正确的话:conn.commit();
不正确的话:conn.rollback();
正常情况下,可以通过Savepoint保存事务的操作点,因为默认情况下所有的回滚,就是将全部的操作取消
掉,而通过savepoint可以设置回退的位置;
一个session的操作(每个连接到数据库上的用户都称为一个session)
操作 1
操作 2
savepoint 记录点 1
操作 3
操作 4
rollback 记录点 1;---这样设置了savepoint前面的操作1 和操作2就不会被回滚了;
设置Savepoint:
Savepoint setSavepoint()
throws SQLException
//创建保存点;
/*---创建数据库表
drop table user;
create table user(
id int auto_increment primary key,
name varchar(30) not null,
password varchar(32) not null,
age int not null,
sex varchar(2) default '男',
birthday Date
);
*/
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.Savepoint;
public class Demo{
//定义数据库的驱动程序
public static final String DBDRIVER="org.gjt.mm.mysql.Driver";
//定义数据库的连接地址:
public static final String DBURL="jdbc:mysql://localhost:3306/lid";
//定义数据库的用户名
public static final String DBUSER="root";
//定义数据库的密码
public static final String DBPASSWORD="123";
public static void main(String args[]) throws Exception{
Connection conn=null;
Statement stmt=null;//数据库操作
//加载数据库驱动
Class.forName(DBDRIVER);//创建一个该驱动类的Class对象;
conn=DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
conn.setAutoCommit(false);//取消自动提交
stmt=conn.createStatement();
//加入批处理
stmt.executeUpdate("insert into user(name,password,age,sex,birthday) values ('仰望_1','456',21,'男','1988-08-08')");
stmt.executeUpdate("insert into user(name,password,age,sex,birthday) values ('仰望_2','456',21,'男','1988-08-08')");
Savepoint sp=conn.setSavepoint();//设置保存点
stmt.executeUpdate("insert into user(name,password,age,sex,birthday) values ('仰望_4','456',21,'男','1988-08-08')");
stmt.executeUpdate("insert into user(name,password,age,sex,birthday) values ('仰望_5','456',21,'男','1988-08-08')");
try{
conn.rollback(sp);
conn.commit();
}
catch(Exception e){
}
stmt.close();
conn.close();
}
}