Java Database Connectivity
- 加载驱动程序(高版本mysql的驱动要用cj包下的)
- 获得数据库连接
- 创建Statement对象(操作 sql 语句的对象)
- 执行 sql 并返回一个结果集
package com.pang.studentweb;
import java.sql.*;
/**
* @author pangjian
* @ClassName JDBCTest
* @Description TODO
* @date 2021/4/12 10:20
*/
public class JDBCTest {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "123456";
String sql = "select * from 商品";
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
// 获得数据库连接
conn = DriverManager.getConnection(url,username,password);
// 创建Statement对象(操作sql语句的对象)
statement = conn.createStatement();
// 执行查询sql,返回一个结果集
resultSet = statement.executeQuery(sql);
// 遍历结果集
while (resultSet.next()){
// 商品名称是商品表的属性
System.out.println(resultSet.getObject("商品名称"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//关闭连接,先开后关
try {
resultSet.close();
statement.close();
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
JDBC事务
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
Statement:用于执行静态SQL语句并返回所生成结果的对象
PreparedStatement:SQL语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句
package com.pang.studentweb;
import java.sql.*;
/**
* @author pangjian
* @ClassName JDBCTest
* @Description TODO
* @date 2021/4/12 10:20
*/
public class TransactionTest {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "123456";
String sql1 = "update 银行 set 存款 = 存款 - 1000 where 用户 = \"小明\"";
String sql2 = "update 银行 set 存款 = 存款 + 2000 where 用户 = \"小明\"";
Connection conn = null;
try {
// 加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
// 获得数据库连接
conn = DriverManager.getConnection(url,username,password);
// 数据库开启事务,false是开启
conn.setAutoCommit(false);
// 创建prepareStatement对象(操作sql语句的对象),小明取了1000
conn.prepareStatement(sql1).executeUpdate();
// 假如系统出现错误
int i = 1/0;
// 小明存了2000
conn.prepareStatement(sql2).executeUpdate();
// 如果小明的事务(两个操作:取1000,存2000)都成功了才提交,事务要么成功要么失败
conn.commit();
System.out.println("提交成功!");
} catch (Exception e) {
try {
// 如果出现错误则回滚事务
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
} finally {
//关闭连接,先开后关
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
结论
- 如果在执行事务的时候,系统出现了故障,则需要回滚到执行事务之前,如果事务执行成功了,则是不能回滚到事务之前的。这里如果小明取了1000后系统出现故障,导致存两千失败,那么事务失败了,因为这里事务假设为小明先取了1000和存了两千,事务要么完成,要么失败。数据也不会运行小明得到1000块,也不会让小明存2000。一切回到没取钱之前的存款(假设小明取的一千块被警察追回来)
- 上面出现了零除错误后数据库不会变
- 事务一旦提交完成,则不能回滚
JDBC执行存储过程
package JDBC;
import oracle.jdbc.OracleTypes;
import java.sql.*;
/**
* @author pangjian
* @ClassName SelectDemo
* @Description TODO
* @date 2021/4/23 10:50
*/
public class SelectDemo {
public static void main(String[] args) {
Connection connection = null;
String url = "jdbc:oracle:thin:@47.119.128.150:1521:orcl";
CallableStatement callableStatement = null; //调用存储过程的对象,和执行sql对象不一样
String sql = "call proc_page(?,?,?,?,?)";
ResultSet rs = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = DriverManager.getConnection(url,"scott","tiger");
callableStatement = connection.prepareCall(sql);
// 处理输入参数
callableStatement.setString(1,"emp");
callableStatement.setInt(2,2); // 每页2条记录
callableStatement.setInt(3,1); // 当前页
// 处理输出参数,让Java知道是什么类型,方便接收输出参数,数据库类型如果不处理,Java不知道是什么类型
callableStatement.registerOutParameter(4, OracleTypes.INTEGER);
callableStatement.registerOutParameter(5,OracleTypes.CURSOR);
callableStatement.execute();
int totalPage = callableStatement.getInt(4);
System.out.println("总页数:"+totalPage);
rs=(ResultSet) callableStatement.getObject(5); // 取第五个参数,也就是存储过程中的游标输出参数,强转为结果集类型
while (rs.next()){
int emp_id = rs.getInt("EMPNO"); // 一共只有两条记录,按字段名取值,循环取了两条记录
String name = rs.getString("ENAME");
System.out.print(emp_id+"----");
System.out.println(name);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
rs.close();
callableStatement.close();
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}