1.自动提交机制
1.1.重点3行代码:
-
conn.setAutoCommit(false / true); false / true 决定自动提交开关
-
conn.commit();
-
conn.rollback();
1.2.银行转账
-
账户1——>账户2 , 转账999
1.2.1.创建账户:
-
drop table if exists t_act; create table t_act( actno int, balance double(7,2) //7位有效数字。2位小数 ); insert into t_act(actno,balance) values (1,1999); insert into t_act(actno,balance) values (2,0); commit;
1.3.开启自动提交
-
conn.setAutoCommit(true); //开启自动提交
-
插入空指针异常,来中断代码,测试是否关闭自动提交!!!!!!
-
String str = null; str.toString();
原账户:
执行结果:(错误)
public class JdbcAutoCommit {
public static void main(String[] args) {
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
String url = "jdbc:mysql://localhost:3306/bjpowernode"; //自己的地址链接
String user = "root";
String password = "333";
conn = DriverManager.getConnection(url,user,password);
conn.setAutoCommit(true); //开启自动提交
// conn.setAutoCommit(false); //关闭自动提交
//3.获取数据库操作对象(专门执行sql语句的对象)
//一个问号表示一个占位符
//改
String sql2 = "update t_act set balance= ? where actno=?";
ps = conn.prepareStatement(sql2);
// 给占位符传值
ps.setDouble(1,1000);
ps.setInt(2,1);
int count = ps.executeUpdate();
//插入空指针异常,来中断代码,测试是否关闭自动提交!!!!!!
String str = null;
str.toString();
// 再给占位符传值
ps.setDouble(1,999);
ps.setInt(2,2);
count += ps.executeUpdate();
System.out.println(count==2?"转账成功":"转账失败");
//查
String sql4 = " select * from t_act";
ps = conn.prepareStatement(sql4);
// 给占位符传值
//程序执行到此,会发送sql语句”框子“给DBMS,然后它进行‘预编译
conn.commit(); //提交代码
//4.执行sql语句(主要执行DQL、DML……)
rs = ps.executeQuery(); //专门执行DQL查询语句
//5.处理查询结果集(只有当第4步执行的是select语句时,才有这第5步)
boolean flag = false;
flag = rs.next();
while (flag){
//列表标签
String actno = rs.getString("actno");
String balance = rs.getString("balance");
System.out.println(actno+","+balance);
flag = rs.next();
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源(使用完资源后一定要关闭资源,java和数据库属于进程间通信,开启后一定要关闭)
try {
if (ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (conn != null)
conn.rollback();
// conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (rs != null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
1.4.关闭自动提交:
原账户:
执行结果:(正确)
public class JdbcAutoCommit {
public static void main(String[] args) {
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
String url = "jdbc:mysql://localhost:3306/bjpowernode"; //自己的地址链接
String user = "root";
String password = "333";
conn = DriverManager.getConnection(url,user,password);
conn.setAutoCommit(false); //关闭自动提交
//3.获取数据库操作对象(专门执行sql语句的对象)
//一个问号表示一个占位符
//改
String sql2 = "update t_act set balance= ? where actno=?";
ps = conn.prepareStatement(sql2);
// 给占位符传值
ps.setDouble(1,1000);
ps.setInt(2,1);
int count = ps.executeUpdate();
//插入空指针异常,来中断代码,测试是否关闭自动提交!!!!!!
// String str = null;
// str.toString();
// 再给占位符传值
ps.setDouble(1,999);
ps.setInt(2,2);
count += ps.executeUpdate();
System.out.println(count==2?"转账成功":"转账失败");
//查
String sql4 = " select * from t_act";
ps = conn.prepareStatement(sql4);
// 给占位符传值
//程序执行到此,会发送sql语句”框子“给DBMS,然后它进行‘预编译
conn.commit(); //提交代码
//4.执行sql语句(主要执行DQL、DML……)
rs = ps.executeQuery(); //专门执行DQL查询语句
//5.处理查询结果集(只有当第4步执行的是select语句时,才有这第5步)
boolean flag = false;
flag = rs.next();
while (flag){
//列表标签
String actno = rs.getString("actno");
String balance = rs.getString("balance");
System.out.println(actno+","+balance);
flag = rs.next();
}
}catch (Exception e){
e.printStackTrace();
}finally {
//6.释放资源(使用完资源后一定要关闭资源,java和数据库属于进程间通信,开启后一定要关闭)
try {
if (ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (conn != null)
conn.rollback();
// conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (rs != null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
2.工具类封装(演示模糊查询)
把JDBC的第1、2、6步封装
- 1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
- 2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
- 6.释放资源(使用完资源后一定要关闭资源,java和数据库属于进程间通信,开启后一定要关闭)
2.1. 封装部分
import java.sql.*;
/**
* 简化JDBC编程
*/
public class DBUtils {
/**
* 工具类中的构造方法都是私有的
* 因为工具类中的方法都是静态的,不用new对象
*/
private DBUtils(){}
/**
* 静态代码块,只在类加载的时候执行1次
* 驱动只注册1次就行了
*/
static {
//1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 封装JDBC的连接部分
* @return
* @throws Exception
*/
public static Connection getConnection() throws Exception {
//2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
String url = "jdbc:mysql://localhost:3306/bjpowernode"; //自己的地址链接
String user = "root";
String password = "333";
return DriverManager.getConnection(url, user, password);
}
/**
* 封装JDBC的close部分
* @param connection
* @param ps
* @param resultSet
*/
public static void close(Connection connection, Statement ps, ResultSet resultSet){
try{
if(ps != null){
ps.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try{
if(connection != null){
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try{
if(resultSet != null){
resultSet.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2.2.模糊查询——调用部分
- 查找emp表内,ename含有字母A的
执行结果:
明显可见,代码量少很多。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* 模糊查询
* 查找emp表内,ename含有字母A的
*/
public class JDBCFuzzyQuery {
public static void main(String[] args) {
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
//3.获取数据库操作对象(专门执行sql语句的对象)
//一个问号表示一个占位符
String sql = "select ename from emp where ename like ?";
ps = conn.prepareStatement(sql);
// 给占位符传值
ps.setString(1,"%A%");
//4.执行sql语句(主要执行DQL、DML……)
rs = ps.executeQuery(); //专门执行DQL查询语句
while (rs.next()){
String ename = rs.getString("ename");
System.out.println(ename);
rs.next();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
DBUtils.close(conn,ps,rs);
}
}
}
3.悲观锁、乐观锁
演示行级锁,需要用到两个程序
程序1:查询输出job是manager的员工
-
// for update 加上悲观锁 String sql = " select ename,job,sal from emp where job=? for update";
-
说明:如果给程序1在commit或之前,加上断点
那程序2会卡住,必须等待程序1执行完才能继续执行
import java.sql.*;
/**
* 演示乐观锁、悲观锁
*/
public class JDBCLock01 {
public static void main(String[] args) {
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
//1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
String url = "jdbc:mysql://localhost:3306/bjpowernode"; //自己的地址链接
String user = "root";
String password = "333";
conn = DriverManager.getConnection(url,user,password);
conn.setAutoCommit(false);//关闭自动提交
//3.获取数据库操作对象(专门执行sql语句的对象)
//一个问号表示一个占位符
// for update 加上悲观锁
String sql = " select ename,job,sal from emp where job=? for update";
ps = conn.prepareStatement(sql);
// 给占位符传值
ps.setString(1,"MANAGER");
//程序执行到此,会发送sql语句”框子“给DBMS,然后它进行‘预编译
//4.执行sql语句(主要执行DQL、DML……)
rs = ps.executeQuery(); //专门执行DQL查询语句
//5.处理查询结果集(只有当第4步执行的是select语句时,才有这第5步)
while (rs.next()){
//列表标签
String ename = rs.getString("ename");
String job = rs.getString("job");
String sal = rs.getString("sal");
System.out.println(ename+","+job+","+sal);
// rs.next();
}
conn.commit();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (conn != null)
conn.rollback();
// conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (rs != null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
程序2:为job是manager的每个人加薪10%
-
String sql = "update emp set sal=sal*1.1 where job=manager";
import java.sql.*;
/**
* 演示乐观锁、悲观锁
*/
public class JDBCLock02 {
public static void main(String[] args) {
//JDBC代码
Connection conn = null;
PreparedStatement ps = null;
try{
//1.注册驱动(作用:告诉java程序,即将要连接哪个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接(表示JVM的进程和数据库进程之间的 通道 打开了,使用完之后 必须关闭)
String url = "jdbc:mysql://localhost:3306/bjpowernode"; //自己的地址链接
String user = "root";
String password = "333";
conn = DriverManager.getConnection(url,user,password);
conn.setAutoCommit(false);//关闭自动提交
//3.获取数据库操作对象(专门执行sql语句的对象)
//一个问号表示一个占位符
String sql = "update emp set sal=sal*1.1 where job=? ";
// String sql = " select ename,job,sal from emp where job=? for update";
ps = conn.prepareStatement(sql);
// 给占位符传值
ps.setString(1,"MANAGER");
int count = ps.executeUpdate();
System.out.println(count==3?"运行成功":"运行失败");
//程序执行到此,会发送sql语句”框子“给DBMS,然后它进行‘预编译
conn.commit();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (ps != null)
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (conn != null)
conn.rollback();
// conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}