基本

概述

是一种用于执行SQL语句的Java 的API.可以为多种关系型数据库提
供统一的访问.它是由一组使用Java语言编写的类或接口组成.
  • 1.什么是JDBC以及为什么要使用JDBC

  • 2.JDBC核心API的讲解

  • 3.使用JDBC核心API进行CRUD操作

  • 4.JDBC的工具类的抽取与改进

  • 5.JDBC的SQL注入漏洞分析与解决方案

  • 6.使用JDBC的PreparedStatement预编译对象进行CRUD操作(重点)

  • 7.JDBC的批处理操作

简说:用java语言编写的一组用于访问关系型数据库的接口和类.

作用:使用Java语言连接到数据库

驱动:两个设备之间的通信桥梁.

Java语言要连接数据库必须使用数据库的驱动
  • 本质:
SUN公司提供了一组接口,各个数据库生产商提供了这套接口的实现.(这组规范就是JDBC规范.)
image.png
image.png

1、Driver接口

  • Java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现

  • 在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。

  • 加载和注册JDBC驱动

    • 加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名

    • DriverManager 类是驱动程序管理器类,负责管理驱动程序

    • 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。

  • 建立连接

    • 可以调用 DriverManager 类的 getConnection() 方法建立到数据库的连接
      JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。

    • JDBC URL的标准由三部分组成,各部分间用冒号分隔。

      • jdbc:<子协议>:<子名称>
      • 协议:JDBC URL中的协议总是jdbc
      • 子协议:子协议用于标识一个数据库驱动程序
      • 子名称:一种标识数据库的方法。子名称可以依不同的子协议而变化,用子名称的目的是为了定位数据库提供足够的信息
  • 几种常用的JDBC URL

对于 Oracle 数据库连接,采用如下形式:
jdbc:oracle:thin:@localhost:1521:sid

对于 SQLServer 数据库连接,采用如下形式:
jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid

对于 MYSQL 数据库连接,采用如下形式:
jdbc:mysql://localhost:3306/sid

2、Statement

通过调用 Connection 对象 的 createStatement 方法创建该对象
该对象用于执行静态的 SQL 语句,并且返回执行结果

Statement 接口中定义了下列方法用于执行 SQL 语句:

  • Statement有两个子类,分别是
ResultSet excuteQuery(String sql)
int excuteUpdate(String sql)
  • 访问数据库
数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
-Statement
- PrepatedStatement(预编译SQL语句的方式,防止注入攻击,执行SQL语句)
- CallableStatement(调用数据库过程)
- Praparedstatement和CallableStatement,

3、ResultSet

通过调用 Statement 对象的 excuteQuery() 方法创建该对象

ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商实现

ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行

ResultSet 接口的常用方法:

boolean next()
getString()

4、数据类型转换

image.png

小结

java.sql.DriverManager用来装载驱动程序,获取数据库连接。
java.sql.Connection完成对某一指定数据库的联接
java.sql.Statement在一个给定的连接中作为SQL执行声明的容器,他包含了两个重要的子类型。
Java.sql.PreparedSatement 用于执行预编译的sql声明
Java.sql.CallableStatement用于执行数据库中存储过程的调用
java.sql.ResultSet对于给定声明取得结果的途径

使用

- 设置工作空间的编码为utf-8

- SQL脚本:

create database web_test3;

use web_test3;

create table user(

id int primary key auto_increment,

username varchar(20),

password varchar(20),

nickname varchar(20),

age int

);

insert into user values (null,'aaa','123','小丽',34);

insert into user values (null,'bbb','123','大王',32);

insert into user values (null,'ccc','123','小明',28);

insert into user values (null,'ddd','123','大黄',21);

步骤:

1.引入数据库的驱动((注意:复制驱动包过来后,一定要选中, add to Build Path)

2.加载驱动.

3.获得连接.

4.获得语句(Statement )对象

5.执行SQL

6.释放资源.
public class JDBCDemo1 {

@Test

/**

* JDBC的入门

 */

**public** **void** demo1() **throws** Exception{

// 1.加载驱动

Class.*forName*("com.mysql.jdbc.Driver");

// 2.获得连接

Connection conn = DriverManager.*getConnection*("jdbc:mysql://localhost:3306/web_test3", "root", "abc"); //注意:密码改成你的密码

// 3.基本操作:执行SQL

// 3.1获得执行SQL语句的对象

Statement statement = conn.createStatement();

// 3.2编写SQL语句:

String sql = "select * from user";

// 3.3执行SQL:

ResultSet rs = statement.executeQuery(sql);

// 3.4遍历结果集:

**while**(rs.next()){

System.***out***.print(rs.getInt("id")+" ");

System.***out***.print(rs.getString("username")+" ");

System.***out***.print(rs.getString("password")+" ");

System.***out***.print(rs.getString("nickname")+" ");

System.***out***.print(rs.getInt("age"));

System.***out***.println();

}

// 4.释放资源

rs.close();

statement.close();

conn.close();

}

}

DriverManager

  • 获取连接的url路径的含义?
指定数据库的网络位置以及帐号密码
  • DriverManager对象有什么作用?
DriverManager对象两个作用:1、注册驱动管理驱动2、获取连接;
  • 为什么没有使用registerDriver()注册驱动?
原来这样写:

DriverManager.*registerDriver*(**new** com.mysql.jdbc.Driver());

现在这样写:

Class.forName(“com.mysql.jdbc.Driver”);//强制加载class到内存

直接调用registerDriver方法会导致驱动加载2次,因为com.mysql.jdbc.Driver是Java类,其内部有一个静态代码块,在类加载
的时候就会执行,而静态代码块中的内容就是注册驱动,所以只需要Class.forName(“com.mysql.jdbc.Driver”);就可以完成
驱动的注册

Connection对象

  • 作用一、创建执行sql语句的对象Statement或其子类

  • 作用二:开启事务和提交事务

connection.setAutoCommit(false);//手动开启事务

connection.commit()

connection.rollback();

Statement

  • 作用一:执行sql语句
  • 作用二:进行批处理(就是把几条sql语句添加到Statement对象命令列表中,一次性执行多条sql语句。)

ResultSet的介绍

  • ResultSet代表select查询后的结果集
遍历结果集:

Result rs = statement.executeQuery(“select * from user”);

while(rs.next()){

int id = rs.getInt("id");

String username = rs.getString("username");

String password = rs.getString("password");

System.out.println(id+"    "+username+"    "+password);

}

获得结果集中的数据:

int id = rs.getInt("id");

String username = rs.getString("username");

String password = rs.getString("password");

**如果结果集中只有一条记录:**

if(rs.next()){

...

}

JDBC的资源的释放

  • Connection的使用原则:尽量要晚创建,尽量早释放!!!
把释放资源的代码放到finally里面去执行,因为finally无论如何都是会执行的s

try{
  ...
}catch(){...}

finally {....}
注意关闭顺序是遵从栈顺序的
finally {

  if (resultSet!=null) {

try {

resultSet.close();

} catch(SQLException e) {

e.printStackTrace();

}

resultSet=null;

}

if(statement!=null) {

try {

statement.close();

} catch (SQLException e) {

e.printStackTrace();

}

statement=null;

}

if(conn!=null) {

try {

conn.close();

} catch(SQLException e) {

e.printStackTrace();

}

conn=null;

}

}

JDBC的CRUD操作之插入

1.加载驱动

2.获得连接

3.获得Statement对象,执行SQL

4.释放资源

/**

*保存操作的代码实现

 */

public void demo1(){

Connection conn = null;

Statement stmt = null;

try{

//注册驱动:

Class.forName("com.mysql.jdbc.Driver");

//获得连接:

conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

//执行操作:

//创建执行SQL语句对象:

stmt = conn.createStatement();

//编写SQL语句:

String sql = "insert into user values (null,'eee','123','阿黄',21)";

//执行SQL语句:

int num = stmt.executeUpdate(sql);

if(num > 0){

System.out.println("保存用户成功!!!");

}

}catch(Exception e){

e.printStackTrace();

}finally{

//资源释放:

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

stmt = null;

}

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

JDBC的CRUD操作之修改

/**

*修改操作的代码实现

 */

public void demo2(){

Connection conn = null;

Statement stmt  = null;

try{

//注册驱动:

Class.forName("com.mysql.jdbc.Driver");

//获得连接

conn = DriverManager.*getConnection*("jdbc:mysql:///web_test3", "root", "abc");

//执行操作:

//创建执行SQL语句的对象:

stmt = conn.createStatement();

//编写SQL语句:

String sql = "update user set password='abc',nickname='旺财' where id = 5";

//执行SQL语句:

int num = stmt.executeUpdate(sql);

if(num > 0){

System.out.println("修改用户成功!!!");

}

}catch(Exception e){

e.printStackTrace();

}finally{

//资源释放:

if(stmt != null){

try{

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

stmt = null;

}

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

JDBC的CRUD操作之删除

/**

*删除操作的代码实现

 */
public void demo3(){

Connection conn = null;

Statement stmt = null;

try{

//注册驱动:

Class.forName("com.mysql.jdbc.Driver");

//获得连接:

conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

//创建执行SQL语句对象:

stmt = conn.createStatement();

//编写SQL:

String sql = "delete from user where id = 5";

//执行SQL:

int num = stmt.executeUpdate(sql);

if(num > 0){

System.out.println("删除用户成功!!!");

}

}catch(Exception e){

e.printStackTrace();

}finally{

//资源释放:

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

e.printStackTrace();

}

stmt = null;

}

if(conn != null){

try{

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

JDBC的CRUD操作之查询

/**

*查询多条记录

 */

public void demo4(){

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

try{

//注册驱动

Class.forName("com.mysql.jdbc.Driver");

//获得连接

conn = DriverManager.*getConnection*("jdbc:mysql:///web_test3", "root", "abc");

//执行操作

//创建执行SQL语句的对象:

stmt = conn.createStatement();

//编写SQL:

String sql = "select * from user";

//执行SQL:

rs = stmt.executeQuery(sql);

//遍历结果集:

while(rs.next()){

System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));

}

}catch(Exception e){

e.printStackTrace();

}finally{

//资源释放:

if(rs != **null**){

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

rs = null;

}

if(stmt != null){

try{

stmt.close();

} catch(SQLException e) {

e.printStackTrace();

}

stmt = null;

}

if(conn != null){

try {

conn.close();

} catch(SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

JDBC的工具类的抽取

  • 关于JDBC可以抽取:加载驱动、获取连接、释放资源这三部分的代码。
/**

* JDBC的工具类

 * **@author**  itheima

 */

**public** **class** JDBCUtils {

**private** **static** **final** String ***driverClassName***;

**private** **static** **final** String ***url***;

**private** **static** **final** String ***username***;

**private** **static** **final** String ***password***;

**static**{

***driverClassName***="com.mysql.jdbc.Driver";

***url***="jdbc:mysql:///web_test3";

***username***="root";

***password***="abc";

}

/**

*注册驱动的方法

 */

**public** **static** **void** loadDriver(){

**try** {

Class.*forName*(***driverClassName***);

} **catch** (ClassNotFoundException e) {

e.printStackTrace();

}

}

/**

*获得连接的方法

 */

**public** **static** Connection getConnection(){

Connection conn = **null**;

**try**{

//将驱动一并注册:

*loadDriver*();

//获得连接

conn = DriverManager.*getConnection*(***url***,***username***, ***password***);

}**catch**(Exception e){

e.printStackTrace();

}

**return** conn;

}

/**

*释放资源的方法

 */

**public** **static** **void** release(Statement stmt,Connection conn){

**if**(stmt != **null**){

**try** {

stmt.close();

} **catch** (SQLException e) {

e.printStackTrace();

}

stmt = **null**;

}

**if**(conn != **null**){

**try** {

conn.close();

} **catch** (SQLException e) {

e.printStackTrace();

}

conn = **null**;

}

}

**public** **static** **void** release(ResultSet rs,Statement stmt,Connection conn){

//资源释放:

**if**(rs != **null**){

**try** {

rs.close();

} **catch** (SQLException e) {

e.printStackTrace();

}

rs = **null**;

}

**if**(stmt != **null**){

**try** {

stmt.close();

} **catch** (SQLException e) {

e.printStackTrace();

}

stmt = **null**;

}

**if**(conn != **null**){

**try** {

conn.close();

} **catch** (SQLException e) {

e.printStackTrace();

}

conn = **null**;

}

}

}

测试工具类

@Test

/**

*查询操作:使用工具类

 */

**public** **void** demo1(){

Connection conn = **null**;

Statement stmt = **null**;

ResultSet rs = **null**;

**try**{

//获得连接:

conn = JDBCUtils.getConnection();

// 创建执行SQL语句的对象:

stmt = conn.createStatement();

//编写SQL:

String sql = "select * from user";

//执行查询:

rs = stmt.executeQuery(sql);

//遍历结果集:

**while**(rs.next()){

System.***out***.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

//释放资源:

JDBCUtils.release(rs, stmt, conn);

}

}

JDBC的配置信息提取到配置文件

1.定义配置文件

2.获取配置文件中的信息

使用PreparedStatement防止JDBC的SQL注入攻击(篡改SQL语句)

PreparedStatement有一个预编译的过程,这个过程会固定sql语句的格式,对于变量要求是用?来占位,那么传递过来
的数据即使包含了sql关键字也不会当做关键字来识别。


**public** **class** UserDao {

**public** **boolean** login(String username,String password){

Connection conn = **null**;

**PreparedStatement** pstmt = **null**;

ResultSet rs = **null**;

//定义一个变量:

**boolean** flag = **false**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL语句:

String **sql** = "select * from user where username = ? and password = ?";

//预编译SQL

pstmt = conn.**prepareStatement**(sql);

//设置参数:

pstmt.**setString**(1, username);

pstmt.**setString**(2, password);

//执行SQL语句:

rs = pstmt.executeQuery();**//无需传入SQL**

**if**(rs.next()){

//说明根据用户名和密码可以查询到这条记录

flag = **true**;

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(rs, pstmt, conn);

}

**return** flag;

}
/**

*保存操作

 */

**public** **void** demo1(){

Connection conn = **null**;

PreparedStatement pstmt = **null**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL语句:

String **sql** = "insert into user values (null,?,?,?,?)";

//预编译SQL:

pstmt = conn.**prepareStatement**(**sql**);

//设置参数:

pstmt.**setString**(1, "eee");

pstmt.**setString**(2, "abc");

pstmt.**setString**(3, "旺财");

pstmt.**setInt**(4, 32);

//执行SQL

**int** num = pstmt.**executeUpdate**();//**不传SQL**

**if**(num > 0){

System.***out***.println("保存成功!");

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(pstmt, conn);

}

}
/**

*修改操作

 */

**public** **void** demo2(){

Connection conn = **null**;

**PreparedStatement pstmt = null;**

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL语句:

String **sql** = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";

//预编译SQL:

pstmt = conn.**prepareStatement(sql);**

//设置参数:

pstmt.setString(1, "abc");//设置第一个?的值

pstmt.setString(2, "1234");

pstmt.setString(3, "旺旺");

pstmt.setInt(4, 23);

pstmt.setInt(5, 4);

//执行SQL:

**int** num = pstmt.executeUpdate();

**if**(num > 0){

System.***out***.println("修改成功!");

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(pstmt, conn);

}

}

/**

*删除操作

 */

**public** **void** demo3(){

Connection conn = **null**;

PreparedStatement pstmt  = **null**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL语句:

String **sql** = "delete from user where id = ?";

//预编译SQL

pstmt = conn.**prepareStatement**(**sql**);

//设置参数:

pstmt.**setInt**(1, 4);

//执行SQL:

**int** num = pstmt.**executeUpdate**();

**if**(num > 0){

System.***out***.println("删除成功!");

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(pstmt, conn);

}

}

/**

*查询操作

 */

**public** **void** demo4(){

Connection conn = **null**;

**PreparedStatement** pstmt = **null**;

ResultSet rs = **null**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL:

String **sql** = "select * from user";

//预编译SQL:

pstmt = conn.**prepareStatement**(sql);

//设置参数:

//执行SQL:

rs = pstmt.**executeQuery**();

//遍历结果集:

**while**(rs.next()){

System.***out***.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname"));

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(rs, pstmt, conn);

}

}

JDBC的批处理操作

批处理:一批SQL一起执行

@Test

/**

*批处理基本操作

 */

**public** **void** demo1(){

Connection conn = **null**;

Statement stmt = **null**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//创建执行批处理对象:

stmt = conn.createStatement();

//编写一批SQL语句:

String sql1 = "create database test1";

String sql2 = "use test1";

String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";

String sql4 = "insert into user values (null,'aaa')";

String sql5 = "insert into user values (null,'bbb')";

String sql6 = "insert into user values (null,'ccc')";

String sql7 = "update user set name = 'mmm' where id = 2";

String sql8 = "delete from user where id = 1";

//添加到批处理

stmt.addBatch(sql1);

stmt.addBatch(sql2);

stmt.addBatch(sql3);

stmt.addBatch(sql4);

stmt.addBatch(sql5);

stmt.addBatch(sql6);

stmt.addBatch(sql7);

stmt.addBatch(sql8);

//执行批处理:

stmt.executeBatch();

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(stmt, conn);

}

}

批量插入(使用PreparedStatement)

@Test

/**

*批量插入记录:

*需要在url后面拼接一个参数即可,效率高

         ?rewriteBatchedStatements=true

 */

**public** **void** demo2(){

//记录开始时间:

**long** begin = System.*currentTimeMillis*();

Connection conn = **null**;

PreparedStatement pstmt = **null**;

**try**{

//获得连接:

conn = JDBCUtils.*getConnection*();

//编写SQL语句:

String sql = "insert into user values (null,?)";

//预编译SQL:

pstmt = conn.**prepareStatement**(sql);

**for**(**int** i=1;i<=10000;i++){

pstmt.**setString**(1, "name"+i);

//添加到批处理

pstmt.**addBatch**();

//注意问题:

//执行批处理

**if**(i % 1000 == 0){

//执行批处理:

pstmt.**executeBatch**();

//清空批处理:

pstmt.**clearBatch**();

}

}

}**catch**(Exception e){

e.printStackTrace();

}**finally**{

JDBCUtils.*release*(pstmt, conn);

}

**long** end = System.*currentTimeMillis*();

System.***out***.println((end-begin));

}

你可能感兴趣的:(基本)