JDBC笔记

JDBC

一、JDBC简介

1. JDBC 概念

  • JDBC 就是使用Java语言操作关系型数据库的一套API
  • 全称:(Java DataBase Connectivity)Java 数据库连接

2. JDBC 本质

  • 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
  • 各个数据库厂商实现这套接口,提供数据库驱动jar包
  • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类

3. JDBC 好处

  • 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
  • 可随时替换底层数据库,访问数据库的Java代码基本不变
Java代码
JDBC
MySQL驱动
Oracle驱动
DB2驱动

数据库驱动就是 JDBC 的实现类

二、JDBC快速入门

步骤

这里呢仅仅对JDBC进行了一个简单的介绍,在之后的内容中会介绍 JDBC API。本文使用的数据库版本为MySQL 5.7.29,驱动包为5.1.27。

package com.itheima.jdbc;

import java.sql.*;

/**
 * JDBC入门
 */
public class JDBCDemo {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/itheima";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql
        String sql = "SELECT * FROM play";

        //4. 获取执行sql的对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs  = stmt.executeQuery(sql);

        //6. 处理结果
        //这里打印的结果为查询到的行数
        int count = 0;
        while(rs.next()){
            count++;
        }
        System.out.println(count);

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

三、JDBC API

1. DriverManager

注册驱动
Class.forName("com.mysql.jdbc.Driver");
  • 查看 Driver 类源码
static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

提示:

  • MySQL 5之后的驱动包,可以省略注册驱动的步骤
  • 原因是自动加载jar包中META-INF/services.java.sql.Driver文件中的驱动类
获取连接
public static Connection getConnection(String url,
String user, String password)
  • 参数
    • url:连接路径
      • 语法: jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2
      • 示例: jdbc:mysql://172.0.0.1:3306/itheima?useSSL=false
      • 细节:
        • 如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
        • 配置useSSL=false参数,禁用安全连接方式,解决警告提示
    • user:用户名
    • password:密码
package com.itheima.jdbc;

import java.sql.*;

/**
 * JDBC API 详解:DriverManager
 */
public class JDBCDemo {

    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接:如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306,则url可以简写为
        String url = "jdbc:mysql:///itheima?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql
        String sql = "SELECT * FROM play";

        //4. 获取执行sql的对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs  = stmt.executeQuery(sql);

        //6. 处理结果
        //这里打印的结果为查询到的行数
        int count = 0;
        while(rs.next()){
            count++;
        }
        System.out.println(count);

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

2 . Connection

获取执行 SQL 的对象
  • 普通执行SQL对象
Statement createStatement()
  • 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement preparedStatement(sql)
  • 执行存储过程的对象
CallableStatement prepareCall(sql)
事务管理
  • MySQL 事务管理

    开启事务:BEIGN; /START TRANSACTION;
    提交事务:COMMIT;
    回滚事务:ROLLBACK
    MySQL自动提交事务

  • JDBC 事务管理:Connection接口中定义了3个对应的方法

    开启事务:setAutoCommit(boolean autoCommit): true为自动提交事务;false为手动提交事务,即为开启事务
    提交事务:commit()
    回滚事务:rollback()

//我使用的是查询语句,对于事务的演示不是一个好的例子……
package com.itheima.jdbc;

import java.sql.*;

/**
 * JDBC API 详解:Connection
 */
public class JDBCDemo3_Connection {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接:如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306,则url可以简写为:
        String url = "jdbc:mysql:///itheima?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);
        Statement stmt = null;

        try {
            //开启事务
            conn.setAutoCommit(false);

            //3. 定义sql
            String sql = "SELECT * FROM play";

            //4. 获取执行sql的对象
            stmt = conn.createStatement();
            //5. 执行sql
            ResultSet rs  = stmt.executeQuery(sql);

            //6. 处理结果
            //这里打印的结果为查询到的行数
            int count = 0;
            while(rs.next()){
                count++;
            }
            System.out.println(count);
            //提交事务
            conn.commit();

        } catch (Exception e) {
            //回滚事务
            conn.rollback();
            e.printStackTrace();
        }

        //7. 释放资源
        stmt.close();
        conn.close();
    }
}

3. Statement

Statement 作用
  • 执行SQL语句

    int executeUpdate(sql): 执行DML、DDL语句
    返回值:(1)DML语句影响的行数 (2)DDL语句执行后,执行成功也可能返回0

    ResultSet executeQuery(sql): 执行DQL语句
    返回值: ResultSet 结果对象集

ResultSet
  • ResultSet(结果集对象)作用:封装了DQL查询语句的结果

  • 获取查询结果

    boolean next(): (1)将光标从当前位置向后移动一行 (2) 判断当前行是否为有效行
    返回值:
    true:有效行,当前行有数据
    false:无效行,当前行没有数据

    DateType getDateType (参数): 获取数据
    DateType:数据类型,如int getInt(参数); String getString(参数)
    参数:
    int: 列的编号,从1开始
    String: 列的名称

  • 使用步骤

//循环判断游标是否是最后一行末尾
while(rs.next()){
	//获取数据
	rs.getDateType(参数);
}
  • 示例
package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * JDBC API 详解:ResultSet
 */
public class JDBCDemo4_ResultSet {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接:如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306,则url可以简写为:
        String url = "jdbc:mysql:///itheima?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql
        String sql = "SELECT * FROM play";

        //4. 获取执行sql的对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //6. 处理结果
        //光标向下移动一行,并且判断当前行是否有数据
        while (rs.next()) {
            /*int id = rs.getInt(1);
            String title = rs.getString(3);
            String duration = rs.getString(5);*/
            int id = rs.getInt("pid");
            String title = rs.getString("title");
            String duration = rs.getString("duration");

            System.out.println("id:" + id + "   title:" + title + "  duration:" + duration);
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

ResultSet查询出来的数据可以用JavaBean结合ArrayList进行处理

package com.itheima.jdbc;

public class Play {
    int id;
    String title;
    String duration;

    public Play() {
    }

    public Play(int id, String title, String duration) {
        this.id = id;
        this.title = title;
        this.duration = duration;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDuration() {
        return duration;
    }

    public void setDuration(String duration) {
        this.duration = duration;
    }

    @Override
    public String toString() {
        return "Play{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", duration='" + duration + '\'' +
                '}';
    }
}

package com.itheima.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * JDBC API 详解:ResultSet
 */
public class JDBCDemo4_ResultSet {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接:如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306,则url可以简写为:
        String url = "jdbc:mysql:///itheima?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql
        String sql = "SELECT * FROM play";

        //4. 获取执行sql的对象
        Statement stmt = conn.createStatement();

        //5. 执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //6. 处理结果
        //光标向下移动一行,并且判断当前行是否有数据
        List<Play> list = new ArrayList<>();
        while (rs.next()) {
            /*int id = rs.getInt(1);
            String title = rs.getString(3);
            String duration = rs.getString(5);*/
            int id = rs.getInt("pid");
            String title = rs.getString("title");
            String duration = rs.getString("duration");
            list.add(new Play(id, title, duration));
        }
        for (Play play : list) {
            System.out.println(play);
        }

        //7. 释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
}

4. PreparedStatement

SQL注入
  • SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法

SQL注入示例

package com.itheima.jdbc;

import java.sql.*;

public class JDBCDemo5_UserLogin{
    public static void main(String[] args) throws Exception{

        /**
         * SQL注入
         * test 数据库中存在一个名为user的表,包含字段username 和 password
         * 其中一条数据为 username = 'Sakura' password = "Ki2HQYr91e"
         */
        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);
        Statement stmt = conn.createStatement();

        /*正常登录用户
        String name = "Sakura";
        String pwd = "Ki2HQYr91e";*/
        
        //SQL 注入登录
        String name = "Sakura";
        String pwd = "' or '1' = '1";

        String sql = "select * from user where username = '"+name+"' && password = '"+pwd+"'";
        System.out.println(sql);
        ResultSet rs = stmt.executeQuery(sql);
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登陆失败!");
        }

        conn.close();
        rs.close();
        stmt.close();
    }
}

执行结果
执行结果

PreparedStatement 作用
  • 预编译SQL语句并执行:预防SQL注入问题
  • 执行步骤:
  1. 获取 PreparedStatement 对象

//SQL语句中的参数值,使用?占位符代替
String sql = "select * from user where username = ? && password = ?";
//通过Connect对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);

  1. 设置参数值

PreparedStatement对象:setDateType(参数1, 参数2): 给 ? 赋值
DateType: 数据类型;如setInt(参数1, 参数2)
参数:

  • 参数1:? 的位置编号,从1开始
  • 参数2:? 的值
  1. 执行SQL

excuteUpdate(); /excuteQuery(); //不需要再传递sql

package com.itheima.jdbc;

import java.sql.*;

/**
 * JDBC API 详解:PreparedStatement
 */
public class JDBCDemo6_PreparedStatement {
    public static void main(String[] args) throws Exception{

        /**
         * test 数据库中存在一个名为user的表,包含字段username 和 password
         * 其中一条数据为 username = 'Sakura' password = "Ki2HQYr91e"
         */
        String url = "jdbc:mysql:///test?useSSL=false";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //正常登录用户
        String name = "Sakura";
        String pwd = "Ki2HQYr91e";

        /*//SQL 注入登录
        String name = "Sakura";
        String pwd = "' or '1' = '1";*/

        //SQL语句中的参数值,使用?占位符代替
        String sql = "select * from user where username = ? && password = ?";
        //通过Connect对象获取,并传入对应的sql语句
        PreparedStatement pstmt = conn.prepareStatement(sql);

        //设置参数值
        pstmt.setString(1, name);
        pstmt.setString(2, pwd);

        //执行sql语句,不能再传入sql
        ResultSet rs = pstmt.executeQuery();
        if(rs.next()){
            System.out.println("登录成功!");
        }else{
            System.out.println("登陆失败!");
        }

        conn.close();
        rs.close();
        pstmt.close();
    }
}

PreparedStatement 原理
  • PareparedStatement好处:
    • 预编译SQL,性能更高
    • 防止SQL注入:将敏感字符进行转义
  • PreparedStatement 预编译功能开启:useServerPrepStmts=true
  • PreparedStatement 原理:
    1. 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
    2. 执行时就不用再执行这些步骤了,速度更快
    3. 如果sql模板一样,则只需要进行一次检查编译

四、数据库连接池

1.数据库连接池简介

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
  • 好处:
    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏

2.数据库连接池实现

  • 标准接口:DataSource
    • 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口
    • 功能:获取连接 Connection getConnection
  • 常见的数据库连接池
    • DBCP
    • C3P0
    • Druid
  • Druid(德鲁伊)
    • Druid连接池是阿里巴巴开源的数据库连接池项目
    • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

3. Druid使用步骤

注意:本文使用的数据库连接池为:druid-1.1.12.jar

  • 导入jar包
  • 定义配置文件

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql:///test?useSSL=false&useServerPrepStmts=true
    username=root
    password=root
    /# 初始化连接数量
    initialSize=5
    /# 最大连接数
    maxActive=10
    /# 最大等待时间
    maxWait=3000

  • 加载配置文件
  • 获取数据库连接池对象
  • 获取连接
package com.itheima.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * Druid 数据库连接池演示
 */
public class DruidDemo {
    public static void main(String[] args) throws Exception {
        //1. 导入jar包
        //2. 定义配置文件
        //3. 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("E:\\IdeaProjects\\itheimaProject\\jdbc_demo\\src\\druid.properties"));

        //4. 获取数据库连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        //5. 获取数据库连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

声明: 本文内容整理自:黑马程序员新版JavaWeb基础教程,Java web从入门到企业实战完整版

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、概述: JDBC从物理结构上说就是Java语言访问数据库的一套接口集合。从本质上来说就是调用者(程序员)和实现者(数据库厂商)之间的协议。JDBC的实现由数据库厂商以驱动程序的形式提供。JDBC API 使得开发人员可以使用纯Java的方式来连接数据库,并进行操作。 ODBC:基于C语言的数据库访问接口。 JDBC也就是Java版的ODBC。 JDBC的特性:高度的一致性、简单性(常用的接口只有4、5个)。 1.在JDBC中包括了两个包:java.sql和javax.sql。 ① java.sql 基本功能。这个包中的类和接口主要针对基本的数据库编程服务,如生成连接、执行语句以及准备语句和运行批处理查询等。同时也有一些高级的处理,比如批处理更新、事务隔离和可滚动结果集等。 ② javax.sql 扩展功能。它主要为数据库方面的高级操作提供了接口和类。如为连接管理、分布式事务和旧有的连接提供了更好的抽象,它引入了容器管理的连接池、分布式事务和行集等。 注:除了标出的Class,其它均为接口。 API 说明 java.sql.Connection 与特定数据库的连接(会话)。能够通过getMetaData方法获得数据库提供的信息、所支持的SQL语法、存储过程和此连接的功能等信息。代表了数据库java.sql.Driver 每个驱动程序类必需实现的接口,同时,每个数据库驱动程序都应该提供一个实现Driver接口的类。 java.sql.DriverManager (Class) 管理一组JDBC驱动程序的基本服务。作为初始化的一部分,此接口会尝试加载在”jdbc.drivers”系统属性中引用的驱动程序。只是一个辅助类,是工具。 java.sql.Statement 用于执行静态SQL语句并返回其生成结果的对象。 java.sql.PreparedStatement 继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。然后可以使用此对象高效地多次执行该语句。 java.sql.CallableStatement 用来访问数据库中的存储过程。它提供了一些方法来指定语句所使用的输入/输出参数。 java.sql.ResultSet 指的是查询返回的数据库结果集。 java.sql.ResultSetMetaData 可用于获取关于ResultSet对象中列的类型和属性信息的对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想写代码的Rayoung

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值