一天学完JDBC[详细知识点大吐血]
JDBC的定义与作用
-
JDBC 是Java DataBase Connectivity 的缩写,即(Java语言连接数据库);
-
JDBC的本质是SUN公司制定的一套接口(interface),在java.sql.*; (这个软件包下有很多接口。);
-
为什么SUN制定一套JDBC接口呢?;
因为每一个数据库的底层实现原理都不一样;每一个数据库产品都有自己独特的实现原理。 -
JDBC开发前的准备工作:
先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
mysql-connector-java-8.0.11 提取码[aaaa]
MySql Connector Java 5.1.23 提取码[aaaa]; -
使用IDEA工具配置驱动;
一、右键目标模块
二、
三、点击“+”,选择Java
四、找到驱动
五、选择目标模块
-
JDBC编程六步;
第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL DML…)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
JDBC 编程6步(以下使用的MySQL版本为8.0)
第一步:注册驱动(两种方式)
-
第一种方式 :
Driver driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver); -
第二种方式 :
String driver = “com.mysql.cj.jdbc.Driver”;
Class.forName(driver); -
对于这两种方式来说,第二种方式更加的通用一些,为什么呢?我们可以看下源码:
在类加载的时候,静态代码块执行。
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
第二步:连接驱动
-
url :统一资源定位符(网络中某个资源的绝对路径)
https://www.baidu.com/ 这就是URL
URL 包括哪几部分?
协议
IP
PORT
资源名http://182.61.200.7:80/index.html http:// 通信协议 182.61.200.7 服务器IP地址 80 服务器上软件的端口 index.html 服务器上某个资源名 jdbc:mysql://localhost:3306/myMySQL?useSSL=false&serverTimezone=UTC jdbc:mysql:// 协议 localhost IP 3306 端口 myMySQL 具体的数据库实例名 ?useSSL=false&serverTimezone=UTC 是否使用 SSL 安全验证及指定服务器上的时区 说明 : localhost 和 127.0.0.1 都是本机IP地址。 什么是通信协议?有什么用? 通信协议是 通信之前就提前定好的数据传送格式。 数据包具体怎么传数据,格式是提前订好的。
-
MySQL5.0版本:
String url = "jdbc:mysql://localhost:3306/myMysql;
String user = "root";
String password = "123456";
con = DriverManager.getConnection(url,user,password);
- MySQL8.0及以上版本 :
String url = "jdbc:mysql://localhost:3306/myMysql?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "123456";
con = DriverManager.getConnection(url,user,password);
- 因为在JDBC中,对事物是自动提交的,执行一条SQL语句,提交一次,存在安全隐患,所以我们需要关闭自动提交,开启手动提交模式
Connection conn = null;
conn.setAutoCommit(false); // 开启事物
conn.commit(); // 关闭事物
conn.rollback(); // 回滚事务(在catch语句块中执行)
第三步 :获取数据库操作对象(2种)
- 获取数据库操作对象(Statement)
Statement st = 驱动.createStatement(); - 获取预编译的数据库操作对象(PreparedStatement)
// SQL语句的框架,其中一个?,表示一个占位符,一个?将来接受一个“值”,注意:占位符不能使用单引号括起来
String sql = "select * from t_user where loginName = ? and loginPwd = ?"; //
// 程序执行到此处,会发送SQL语句框子给DBMS,然后DBMS进行SQL语句的预编译。
ps = conn.prepareStatement(sql);
// 给占位符传值,第一个?下标是1,第二个?下标是2,JDBC中所有下标从1开始
ps.setString(1,loginName);
ps.setString(2,loginPwd);
- 什么是SQL注入?
程序对用户输入数据的合法性没有判断或过滤不严 - SQL注入的原因 ?
用户输入的信息中含有SQL语句的关键字,并且这些关键字参与了SQL语句的编译过程,
导致SQL语句的原因被扭曲,进而导致SQL注入。 - 对比一下Statement 和 PreparedStatement ?
- Statement 存在SQL注入问题 ,PreparedStatement 解决了SQL注入问题
- Statement 对SQL语句是编译一次执行一次 ,PreparedStatement 对SQL语句是编译一次执行N次 ,
PreparedStatement 执行效率较高。 - PreparedStatement 会在编译阶段做安全检查
- 综上所述 :PreparedStatement 的使用比较多,只有极少情况下,必须使用Statement
第四步 :执行SQL语句(分为2种)
- 使用 Statement 对象
String sql = "insert into dept(deptno,dname,loc) values(50,'人事部','北京')";
//专门执行DML语句的 int count = statement.executeUpdate(sql);*****************
// 返回值是“影响数据库中的记录条数”
// jdbc 中的SQL语句不需要写 分号 ";"
int count = statement.executeUpdate(sql);
==============================================================
// 专门执行DQL
String sql = "select * from emp";
// ***********************************专门执行DQL的语句 ****************************************
ResultSet result = state.executeQuery(sql);
- 使用 PreparedStatement 对象
// 专门执行DML
int count = PreparedStatement 对象.executeUpdate();
// 专门执行DQL
ResultSet result = ps.executeQuery();
第五步 :处理查询结果集
注意:只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。
boolean flag = result.next();
System.out.println(flag); // 如果有数据,返回true
if (flag){
// 光标指向的行有数据
// 获取数据
// getString()方法的特点 :不管数据库当中的数据类型是什么,都以String的形
// JDBC所有下标都是从1开始,而不是从0开始
// 一下程序的 1 2 3 代表的是第几列
// 一、通过特定的列数获取
String empno = result.getString(1);
// 二、通过字段名获取
String ename = result.getString("ename");
// 三、除了可以以String类型取出,还可以以特定的类型取出
double sal = result.getDouble(3);
第六步 :释放资源
- 为了保证资源一定释放,在finally语句当中关闭资源
并且要遵循从小到大依次关闭
例如 con 调用 createStatement()方法 获取 statement,所以先关闭statement再关闭con
finally {
// 6、释放资源
if (result != null) { // ResultSet 对象
try {
result.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (state != null) { // Statement 对象
try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (con != null) { // Connection 对象
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
完整代码
- 工具类(自己定义的)
/**
* JDBC工具类,简化JDBC编程
*/
public class DBUtil {
/**
* 工具类中的构造方法都是私有的。
* 因为工具类当中的方法都是静态的,不需要new对象,直接采用类名调用
*/
private DBUtil(){
}
// 静态代码块在类加载时执行,并且只执行一次
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/myMySQL?useSSL=false&serverTimezone=UTC"
, "root","123456");
}
/**
* 关闭资源
* @param conn 连接对象
* @param state 数据库操作对象
* @param rs 结果集
*/
public static void close(Connection conn, Statement state, ResultSet rs){
if (rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (state != null){
try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
- 主程序
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,sal,job 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.getDouble("sal")+","+
rs.getString("job"));
}
// 提交事务(事务结束)
conn.commit();
} catch (SQLException throwables) {
// 回滚事务(事务结束)
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
throwables.printStackTrace();
}finally {
DBUtil.close(conn,ps,rs);
}
}
结语
如果对您有收获的话,您还可以看看其它的文章,希望对您有用。