JDBC中的事务提交机制
JDbC 事务机制:
JDBC中的事务是自动提交的,即JDBC中DML语句执行一次,事务自动提交一次,
这是JDBC默认的事务行为,但是在实际的业务开发中,通常都是N条DML语句共同联合才能完成的,
必须保证这些DML语句在同一个事务中同时成功或者同时失败
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDbC 事务机制:
* 1、JDBC中的事务是自动提交的,即JDBC中DML语句执行一次,事务自动提交一次
* 这是JDBC默认的事务行为,但是在实际的业务开发中,通常都是N条DML语句共同联合才能完成的
* 必须保证这些DML语句在同一个事务中同时成功或者同时失败
* 2、以下程序会先验证JDBC的事务是否是自动提交机制
*测试结果:JDBC中只要执行任意一条SQL语句,事务就自动提交一次
*
*/
public class Demo05 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps =null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
// conn = DriverManager.getConnection("jdbc:mysql//localhost:3306/bjpowernode","root","333");注意URL的书写格式
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
//3.获取数据库预编译对象,写SQL语句
String sql ="update dept set dname = ? where deptno = ?";
//4.执行第一个SQL语句
ps =conn.prepareStatement(sql);
ps.setString(1,"X部门");
ps.setInt(2,30);
int count = ps.executeUpdate();
System.out.println(count);
//第二次执行SQL语句
ps.setString(1,"Y部门");
ps.setInt(2,60);
count = ps.executeUpdate();
System.out.println(count);
//5.遍历查询结果集
} catch (Exception e) {
e.printStackTrace();
}finally {
if (ps !=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}if(conn !=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC 完成银行转账业务
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
*sql脚本
* drop table if exists t_cat;
* create table t_act(
* actno int,
* balance double(7,2)//注意7表示有效数字的个数,2表示小数位的个数。
* );
* insert into t_act(actno,balance) values (111,20000);
* insert into t_act(actno,balance) values (222,0);
* commit;
* selece *from t_act;
*
*
*
*/
public class Demo06 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps =null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
//将自动提交机制修改为手动提交机制
conn.setAutoCommit(false);//开启事务
//3.获取数据库预编译对象,写SQL语句
//4.执行SQL语句
String sql ="update t_act set balance = ? where actno = ?";
ps = conn.prepareStatement(sql);
//传值
ps.setDouble(1,10000);
ps.setInt(2,111);
int count = ps.executeUpdate();
/**手动生成异常
String s = null;
s.toString();
*/
//第二次传值
ps.setDouble(1,10000);
ps.setInt(2,222);
count +=ps.executeUpdate();
System.out.println(count == 2 ? "转账成功":"转账失败");
//执行到此说明程序没出现异常,此时可以提交事务
conn.commit();//手动提交事务
//5.遍历查询结果集
} catch (Exception e) {
//回滚事务
if (conn !=null ){
try {
conn.rollback();
} catch (SQLException ex) {
e.printStackTrace();
}
}
}finally {
if (ps !=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}if(conn !=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC 的工具类
package utils;
/*
* JDBC 工具类
* */
import java.sql.*;
public class DBUtil {
/*
* 工具类中的构造方法都是私有的。
* 因为工具类中的方法都是静态的,不需要new对象,直接采用类名调用
* */
private DBUtil(){}
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode","root","333");
}
/**
* 关闭资源
* @param conn 数据库连接对象
* @param ps 数据库操作对象
* @param rs 结果集
*/
public static void close(Connection conn, Statement ps, ResultSet rs){
if (rs!= null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps!= null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn!= null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC 完成模糊查询
package DemoCode;
/*
*两个任务:
* 第一、测试util工具类是否可用
* 第二、JDBC进行模糊查询
*
* */
import utils.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo07 {
public static void main(String[] args) {
Connection conn =null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
//获取预编译的数据库操作对象
//错误的写法
// String sql = "select ename from emp where ename like '_?%'";
// ps = conn.prepareStatement(sql);
// ps.setString(1,"A");
String sql = "select ename from emp where ename like ?";
ps = conn.prepareStatement(sql);
ps.setString(1,"_A%");
rs = ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("ename"));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DBUtil.close(conn,ps,rs);
}
}
}
乐观锁与悲观锁简介
行级锁:select enamel,job,sal from emp where job='manager' for update;
其中加入的‘for update’称为行级锁,即其他语句在该事务结束之前无法对岗位为‘manager’这一行记录进行改动。又被称为悲观锁
悲观锁:事务必须排队执行。数据锁住了,不允许并发。
乐观锁:支持并发,事务也不需要排队,但是需要一个版本号。
package DemoCode;
/*
Demo08、09进行演示乐观锁与悲观锁
这个程序开启一个事务,这个事务专门进行查询,并且使用行级锁/悲观锁,锁住相关的记录
* */
import utils.DBUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Demo08 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps =null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql = "select ename,job,sal from emp where job = ? for update";
ps = conn.prepareStatement(sql);
ps.setString(1,"MANAGER");
rs = ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("ename")+","+rs.getString("job")+","+rs.getInt("sal"));
}
//提交事务(事务结束)
conn.commit();
} catch (SQLException e) {
if (conn != null){
try {
conn.rollback();//回滚事务(事务结束)
} catch (SQLException ex) {
e.printStackTrace();
}
}
}finally {
DBUtil.close(conn,ps,rs);
}
}
}
package DemoCode;
/*
Demo08、09进行演示乐观锁与悲观锁
这个程序开启一个事务,这个事务进行修改锁定的记录
* */
import utils.DBUtil;
import java.awt.dnd.DnDConstants;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo09 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps =null;
try {
conn = DBUtil.getConnection();
conn.setAutoCommit(false);
String sql = "update emp set sal =sal*1.1 where job = ?";
ps = conn.prepareStatement(sql);
ps.setString(1,"MANAGER");
int count = ps.executeUpdate();
System.out.println(count);
conn.commit();
} catch (SQLException e) {
if (conn !=null){
try {
conn.rollback();
} catch (SQLException ex) {
e.printStackTrace();
}
}
}finally {
DBUtil.close(conn,ps,null);
}
}
}
JDBC到此可告一段落!