目录
1.JDBC的本质
2.JDBC的使用步骤
3.DriverManager对象
4.Connectioin对象
5.Statement对象
6.ResultSet对象
7.JDBC工具类
8.PreparedStatement类
9.JDBC管理事务

1.JDBC的本质

Java DataBase Connectivity(Java语言连接数据库)
JDBC是SUN公司制定的一套接口(interface)

2.JDBC的使用步骤

第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL DML…)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)

代码模版:

package testJdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class test2 {public static void main(String[] args) throws SQLException, ClassNotFoundException {//1、注册驱动String JDBCDriver = "com.mysql.jdbc.Driver";Class.forName(JDBCDriver);//2、连接数据库String url="jdbc:mysql://127.0.0.1:3306/school";  //链接数据的urlString user="root"; //登录数据库的用户名String password="123456"; //用户的密码Connection conn = DriverManager.getConnection(url, user, password);Statement st = conn.createStatement();//一、查询sqlString sql="select * from student";ResultSet rs = st.executeQuery(sql);System.out.println("SId"+" "+"Sname"+" "+"Sage"+" "+"Ssex");while (rs.next()) {System.out.println(rs.getString("SId")+" "+rs.getString("Sname")+" "+rs.getString("Sage")+" "+rs.getString("Ssex"));}/*//二、修改数据int update = st.executeUpdate("update student set Sname='xiaolizi' where SId=2");System.out.println("修改后成功的条数:"+update);*///三、删除//st.execute("delete from student where SId='2'");//四、添加数据
//      String sql1 = "insert into student(SId,Sname,Sage,Ssex) values('4','郑','3','2')";
//      st.execute(sql1);//关闭连接conn.close();st.close();rs.close();}
}

3.DriverManager对象

3.1DriverManager对象简介

DriverManager是驱动管理对象,有两个功能,第一个功能是注册驱动,第二个功能是获取数据库连接

3.2DriverManager注册驱动

我们查看DriverManager类发现它有这么一个方法

static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager

但是我们可以看到我们的注册驱动用到的是
String JDBCDriver ="com.mysql.jdbc.Driver";
Class.forName(JDBCDriver);
这样的两句代码,那么好像和我们的DriverManager无关。
其实不是,我们写代码使用的是Class.forName("com.mysql.jdbc.Driver")把Driver加载到JVM中,
类里面有静态代码块自动执行

public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}
static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}}

看到这样的两句代码是不是就恍然大悟,原来在加载这个类的同时执行了同同步代码块,就是在注册驱动

再看下面一张图

我们可以看到这个jar包已经包含了这个驱动加载,如果我们没有写注册驱动,他也会自动加载驱动(也就是说Mysql5之后的版本驱动的jar包可以省略注册驱动的步骤)

3.2DriverManager获取数据库连接

方法:

public static Connection getConnection(String url,String user,String password)

参数:
*url:指定连接的路径
*语法:jdbc:mysql://ip地址(域名):端口号/数据库名
*例子:jdbc:mysql://localhost:3306/db3
*细节:如果连接的是本机mysql服务器且端口号为3306,可以省略jdbc:mysql:///数据库连接名

4.Connectioin对象

Connection:数据库连接对象,它的功能有:

1.功能:
获取执行sql的对象
Statement createStatement()
PreparedStatement prepareStatement(String sql)
2.管理事务:
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
提交事务:commit();
回滚事务:rollback();

5.Statement对象

它的作用的执行sql语句,对应的方法有:

(1) boolean execute(String sql):可以执行任意的sql ,不常用(因为他多用于处理相对复杂的sql语句)了解即可
(2) int executeUpdate(String sql):执行DML(insert update delete) DDL(create alert drop)语句
返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功
(3)ResultSet executeQuery(String sql): 执行DQL语句

6.ResultSet对象

ResultSet对象:结果集对象,我们DQL查询的结果都在这个对象里,它里边的方法有:

1 . next():游标向下移动一行(如下图游标默认指向id所在行,所以我们需要此方法移动游标)
2 .getXXX(参数):获取数据
XXX代表数据类型 如:int getInt(); String getString();
$参数:
1.int:代表列的编号,从1开始 如:getString(1);【对应下图id】
2.String代表的是列的名称,如:getDouble(“balance”);

我们获取结果集里边的数据,需要按照如图的方式:

代码模版

while(rs.next()){//6.2获取数据int id=rs.getInt(1);//参数可以是数字代表列,可以直接是列名String name=rs.getString("name");double balance=rs.getDouble(3);System.out.println(id+"---"+name+"---"+balance);
}

我举个例子,下表打印出来

package cn.itcast.JDBC;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class jdbc {public static void main(String[] args)  {Connection conn=null;Statement stmt=null;ResultSet res=null;List<student> list=new ArrayList<>();try{Class.forName("com.mysql.jdbc.Driver");conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");String str="select * from student";stmt=conn.createStatement();res=stmt.executeQuery(str);while(res.next()){student stu=new student();stu.setName(res.getNString(1));stu.setAge(res.getInt(2));stu.setSex(res.getNString(3));list.add(stu);}}catch(Exception e) {e.printStackTrace();}finally {if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if(stmt!=null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(res!=null){try {res.close();} catch (SQLException e) {e.printStackTrace();}}}for (int i = 0; i <list.size() ; i++) {System.out.println(list.get(i).getName());System.out.println(list.get(i).getAge());System.out.println(list.get(i).getSex());}}
}
class student{private String name;private int age;private String sex;public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
运行结果:
李四
11
男
张三
12
女
翠花
12
女

7.JDBC工具类

刚才我举的例子可以看出来每一次使用JDBC就会有很多重复的代码块(注册驱动释放资源都是重复的代码),JDBC的工具类就是把那么多重复的代码块封装起来变成一个新的类,每次使用的时候就调用这类里的个方法,那么当我们多次使用JDBC的时候就会简便的多,我们把上面的例子拿过来,然后进行改进

我们知道获取连接的时候就是上面例子的这段代码:
conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");,现在们把这段代码包装成一个方法,我们的要求是,方法不允许有参数,还要保证方法的通用性,这时候我们就需要用到我们的配置文件了,里边记录我们获取连接的三个参数,然后把释放资源也包装成一个方法。然后再把我们释放资源封装成一个方法,就有了如下工具类

package JDBCtool;import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;public class jdbctool {private static String url;private static String user;private static String password;static {  //静态代码块自动读取配置文件到内存try{//创建一个Properties集合类Properties pro=new Properties();//下面三行代码是获取src目录的绝对路径(目的是获取配置文件的路径,但是博主把配置文件放在了src的目录下)ClassLoader classLoader=jdbctool.class.getClassLoader();URL res=classLoader.getResource("jdbc.properties");String path=res.getPath();//把读取的配置文件加载进内存pro.load(new FileReader(path));//利用类本身的属性获取配置文件里的数据url=pro.getProperty("url");//括号里边的为键名user=pro.getProperty("user");password=pro.getProperty("password");}catch(IOException e){e.printStackTrace();}}public static Connection getConnection() throws SQLException//获取连接对象{return DriverManager.getConnection(url,user,password);}public  static void close(Statement stmt,Connection conn,ResultSet res){if(stmt!=null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if(res!=null){try {res.close();} catch (SQLException e) {e.printStackTrace();}}}
}

配置文件里有:
那么每当我们使用JDBC的时获取连接和释放资源都可以使用这个工具类,配置文件的三个参数根据连接的数据库不同适当更改,就会方便很多

8.PreparedStatement类

8.1登录案例

我们做一个登录案例试试:
我们的student数据库里边有一个表user,然后利用这一个表做一个登录的案例:
user表:

那么我们按照上图的用户名和密码进行登录,代码如下

package Login;import java.sql.*;
import java.util.Scanner;public class login {public boolean LoGin(String username,String password){if(username==null||password==null)return false;Connection conn=null;Statement stmt=null;ResultSet res=null;try{Class.forName("com.mysql.jdbc.Driver");conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");stmt=conn.createStatement();String str="select * from user where name='"+username+"' and password='"+password+"'";res = stmt.executeQuery(str);return res.next();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally {if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if(stmt!=null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}} if(res!=null){try {res.close();} catch (SQLException e) {e.printStackTrace();}}}return false;}public static void main(String[] args) {Scanner p=new Scanner(System.in);System.out.println("请输入用户名:");String username=p.next();System.out.println("请输入密码:");String password=p.next();boolean bool=new login().LoGin(username,password);if(bool){System.out.println("登录成功");}else{System.out.println("登录失败");}}
}

运行结果:

那么其实这里有一个bug,比如下面的语句查出了所有的用户

我们举一个例子:

我们的表里明明没有这一个user信息为啥会登录成功呢,那么这里就牵扯到我们的SQL注入问题

SQL注入:在拼接sql语句时有一些sql的特殊关键字参与字符串的拼接,会造成安全性的问题

按照上图输入我们的实际的查询语句是:

当然可以查到用户,而且是相当于查询所有的用户,因为有一个or和一个恒等式

这时候就要用到我们的PreparedStatement类,父类是Statement

1.Statement:执行静态的sql语句,就是直接把我们输入的数据偷换掉sql语句重的username和password,
2.PreparedStatement:首先预编译sql语句,参数使用占位符?替换

和Statement用法有所不同的是

  • sql参数使用占位符如:"select * from user where name=? and password=?"
  • 需要用PrepareStatement对象的方法给占位符赋值
  • 在执行sql的时候不需要传递sql语句了,因为在获取PreparedStatement对象时候需要传递一个sql语句用于预编译

那么我们按照描述修改例子的代码:

package Login;import java.sql.*;
import java.util.Scanner;public class login {public boolean LoGin(String username,String password){if(username==null||password==null)return false;Connection conn=null;PreparedStatement pstmt=null;ResultSet res=null;try{Class.forName("com.mysql.jdbc.Driver");conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/student","root","2332402105");//定义预编译sql语句strString str="select * from user where name=? and password=?" ;//获取 PreparedStatement对象并且传递预编译sql语句pstmt=conn.prepareStatement(str);//set方法给占位符赋值,第一个参数1代表第一个占位符,2代表第二个占位符,第二个参数是赋的值pstmt.setString(1,username);pstmt.setString(2,password);res = pstmt.executeQuery();return res.next();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally {if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if(pstmt!=null){try {pstmt.close();} catch (SQLException e) {e.printStackTrace();}} if(res!=null){try {res.close();} catch (SQLException e) {e.printStackTrace();}}}return false;}public static void main(String[] args) {Scanner p=new Scanner(System.in);System.out.println("请输入用户名:");String username=p.next();System.out.println("请输入密码:");String password=p.next();boolean bool=new login().LoGin(username,password);if(bool){System.out.println("登录成功");}else{System.out.println("登录失败");}}
}


成功解决sql注入问题

9.JDBC管理事务

在获取到Connection对象后,用Connection对象方法setAutoCommit(boolean autoCommit):参数为false开启事务
然后整个语句结束后使用Connection对象的commit()方法对事务进行提交,我们还可以使用Connection对象的rollback()方法对事务进行回滚

JDBC有这一篇就够了(万字JDBC附代码详解)相关推荐

  1. 干货 | OpenCV看这篇就够了,9段代码详解图像变换基本操作

    作者 | 王天庆,长期从事分布式系统.数据科学与工程.人工智能等方面的研究与开发,在人脸识别方面有丰富的实践经验.现就职某世界100强企业的数据实验室,从事数据科学相关技术领域的预研工作. 来源 |  ...

  2. 高能干货:OpenCV看这篇就够了,9段代码详解图像变换基本操作

    导读:OpenCV是一个以BSD许可证开源的.跨平台的计算机视觉库.它提供了Python.C++.Java.Matlab等多种编程语言接口.它集成了很多计算机视觉算法,具有非常强大的功能,是计算机视觉 ...

  3. 一下子搞懂JDBC,看这篇就够了--以MySQL为例。

    一下子搞懂JDBC,看这篇就够了–以MySQL为例. 文章目录 一下子搞懂JDBC,看这篇就够了--以MySQL为例. 一.什么是JDBC? 二.JDBC的使用步骤 三.jdbc进阶--上述各个类或接 ...

  4. 深度篇——目标检测史(七) 细说 YOLO-V3目标检测 之 代码详解

    返回主目录 返回 目标检测史 目录 上一章:深度篇--目标检测史(六) 细说 YOLO-V3目标检测 下一章:深度篇--目标检测史(八) 细说 CornerNet-Lite 目标检测 论文地址:< ...

  5. c linux time微秒_学习linux,看这篇1.5w多字的linux命令详解(6小时讲明白Linux)

    用心分享,共同成长 没有什么比每天进步一点点更重要了 本篇文章主要讲解了一些linux常用命令,主要讲解模式是,命令介绍.命令参数格式.命令参数.命令常用参数示例.由于linux命令较多,我还特意选了 ...

  6. Kotlin——中级篇(二): 属性与字段详解

    在前面的章节中,详细的为大家讲解到了Kotlin中对类的类的定义.使用.初始化.初始化.类继承等内容,但是在一个类中,几乎上是不可能不出现属性与字段(field)的,这一篇文章就为大家奉上Kotlin ...

  7. 来FAL学风控|风控策略分析师的日常是怎样的?(案例+代码详解篇)

    风控策略分析师的日常是怎样的?(案例+代码详解篇) FAL金科应用研究院 做了5年的金融,3年的数据分析工作,从17年6月才真正接触代码,算不到熟练,但在不断的学习和工作实践中目前是可以解决任何问题的 ...

  8. 微信小程序系列(7)如何用微信小程序写一个论坛?贴心代码详解(五)删帖页【完结篇】

    源代码已开源,如果对你有帮助可以点个星:https://github.com/linkaimin/xdzs 写论坛不难,重点是各页面之间的信息传递! 先放成品图,虽然有点单调....但是麻雀虽小五脏俱 ...

  9. 第二篇supervisor集群管理工具cesi安装详解-如何安装supervisor-cesiwebUI

    第二篇supervisor集群管理工具cesi安装详解-如何安装supervisor-cesiwebUI 介绍 安装 解压 安装依赖 修改配置 注册为系统服务 启动 登录一下,发现报错了 解决方法 介 ...

最新文章

  1. Linux环境编译安装Mysql以及PHP中文乱码解决
  2. Complete Tripartite CodeForces - 1228D(三分图染色)
  3. duilib清空richedit内容
  4. 前端学习(1750):前端调试值之call stack
  5. 版本控制:集中式(SVN) vs 分布式(GIT)
  6. 无监督学习之聚类方法(K-Means、层次聚类)
  7. elipse安装php
  8. 基于Linux的嵌入式文件系统构建与设计
  9. mysql分表和分区的区别
  10. mysql cpu高 重启无效_解决mysqlcpu高的问题
  11. sql多行插入insert多行无法分析查询文本_收藏!SQL语法全集合!
  12. C#语句之while语句
  13. QQ正常网页无法访问故障分析
  14. xlsxwriter 简单用法
  15. Python-有道翻译
  16. APP定制开发之前,这6条铁律要牢记
  17. 计算机控制中的pid是什么意思,PID 是什么意思
  18. c++中的trivial
  19. html加水平线紧挨文字,html怎么设置水平线与文字的距离
  20. 重装Ubuntu(Linux)后快速搭建工作环境(深度学习环境)

热门文章

  1. 互联网1分钟 | 1015
  2. SpringMVC-RestfulCRUD
  3. Java vs Kotlin,Android开发人员应该选择哪种语言?
  4. 小白入门angular-cli的第一次旅程(学习目标 1.路由的基础知识 参数订阅写法)
  5. linux中sudo如何读取标准输入作为密码,避免每次都输入密码?
  6. 从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
  7. Oracle 11g Dataguard 物理备库配置(四)之broker snapshot standby测试
  8. Powershell管理系列(三十九)PowerShell查询和解锁AD账号
  9. 偶遇mysql(Percona Server)的一个新bug
  10. 【mysql】[error]group_concat造成的sql语法错误