C/C++教程

JDBC知识点整理

本文主要是介绍JDBC知识点整理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JDBC入门

1 JDBC:Java DataBase Connectivity

1.1JDBC的概念

JDBC规范定义接口,具体的实现由各大数据库厂商来实现。

JDBC是Java访问数据库的标准规范,真正的怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的驱动。所以只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供

  • 使用JDBC的好处:
    1. 程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类如何实现的。
    2. 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库。
    3. 代码不依赖于任何的数据库

1.1.2 使用JDBC开发使用的包

会使用到的包说明
java.sql所有与JDBC访问数据库相关的接口和类
javax.sql数据库扩展,提供数据库额外的功能。
数据库的驱动由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类

1.2JDBC的核心API

接口或类作用
DriverManager类1. 管理和注册数据库驱动;2. 得到数据库连接对象
Connection 接⼝⼀个连接对象,可⽤于创建 Statement 和 PreparedStatement对象
Statement 接⼝⼀个 SQL 语句对象,⽤于将 SQL 语句发送给数据库服务器。
PreparedStatement 接⼝⼀个 SQL 语句对象,是 Statement 的⼦接⼝
ResultSet 接⼝⽤于封装数据库查询的结果集,返回给客户端 Java 程序

1.3加载和注册驱动

加载和注册驱动的⽅法描述
Class.forName(数据驱动实现类)加载和注册数据库驱动,数据库驱动由数据库厂商实现; MySQL ⼚商: “com.mysql.jdbc.Driver”
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //抛出类找不到的异常,注册数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
    }
}

从JDBC3开始,目前已经普遍使用的版本,可以不用注册驱动而直接使用,Class.forName这句话可以省略

2.DriverManager类

2.1DriverManager作用

  1. 管理和注册驱动
  2. 创建数据库的连接

2.2类中的方法

DriverManager类中的静态方法描述
Connection getConnection(String url, String user,String password)通过连接字符串,⽤户名,密码来得到数据库的连接对象
Connection getConnection (String url, Properties info)通过连接字符串,属性对象来得到连接对象

2.3使用JDBC连接数据库的四个参数

JDBC连接数据库的四个参数说明
⽤户名登录的⽤户名
密码登录的密码
连接字符串 URL不同的数据库 URL 是不同的,mysql 的写法jdbc:mysql://localhost:3306/数据库[?参数名=参数值]
驱动类的字符串名com.mysql.jdbc.Driver

2.4连接数据库的URL地址格式

  • 协议名:子协议://服务器名或IP地址:端口号/数据库名?参数=参数值

2.4.1MySQL写法

URL用于标识数据库的位置,程序员通过URL地址
JDBC程序连接哪个数据库,URL的写法为:

jdbc:mysql://localhost:3306/test?参数=参数值

注:jdbc:协议;
mysql:子协议;
localhost:3306: 主机:端口
test:子协议

2.4.2MySQL中可以简写

前提:必须是本地服务器,端口号是3306

jdbc:mysql:///数据库名

2.4.3乱码的处理

如果数据库出现乱码,可以指定参数:?characterEncoding=utf8,表示让数据库以UFT-8编码来处理数据。

jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8

3 Connection接口

流程:

  1. 导入jar包
  2. 加载驱动类
    Class.forName(“com.mysql.jdbc.Driver”);
    Class.forName(“com.mysql.cj.jdbc.Driver”);

3.1Connection作用

Connection接口,具体的实现类由数据库的厂商实现,代表一个连接对象。

3.2Connection方法

Connection接口中的方法:

Statement createStatement() -- 创建一条SQL语句对象

4 Statement接口

4.1 JDBC访问数据库的步骤

  1. 注册和加载驱动(可以省略)
  2. 获取连接
  3. Connection获取Statement对象
  4. 使用Statement对象执行SQL语句
  5. 返回结果集
  6. 释放资源

4.2 Statement作用

代表一条语句对象,用于发送SQL语句给服务器,用于执行静态SQL语句并返回它所生成结果的对象。

4.3 Statement中的方法

Statement接口中的方法描述
int executeUpdate(String sql)用于发送DML语句,增删改的操作,insert、update、delete 参数:SQL语句 返回值:返回对数据库影响的行数
ResultSet executeQuery(String sql)用于发送DQL语句,执行查询的操作select 参数:SQL语句 返回值:查询的结果集

4.4释放资源

  1. 需要释放的对象:ResultSet结果集,Statement语句,Connection连接
  2. 释放原则:先开的后关,后开的先关。ResultSet -> Statement -> Connection
  3. 放在哪个代码块中:finally块

4.5DDL操作

步骤:

  1. 创建连接对象
  2. 创建Statement语句对象
  3. 执行SQL语句:execute(sql)
  4. 返回影响的行数
  5. 释放资源

4.6DML操作

步骤:

  1. 创建连接对象
  2. 创建Statement语句对象
  3. 执行SQL语句:executeUpdate(sql)
  4. 返回影响的行数
  5. 释放资源

4.7执行DQL操作

  • 作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录

  • 接口中的方法

ResultSet 接⼝中的⽅法描述
boolean next()1. 游标向下移动 1 ⾏;2. 返回 boolean 类型,如果还有下⼀条记录,返回 true,否则返回 false
数据类型 getXxx()1. 通过字段名,参数是 String 类型。返回不同的类型;2. 通过列号,参数是整数,从 1 开始。返回不同的类型

注:java.sql.Date、Time、Timestamp(时间戳),三个共同⽗类是:java.util.Date

4.7.3 需求

确保数据库中有3条以上的记录,查询所有的学员信息

  • 步骤:
    1. 得到连接对象
    2. 得到语句对象
    3. 执行SQL语句得到结果集ResultSet对象
    4. 循环遍历取出每一条记录
    5. 输出的控制台上
    6. 释放资源

4.7.4关于ResultSet 接口中的注意事项

  1. 如果光标在第一行之前,使用rs.getXXX()获取列值,报错:Before start of result set
  2. 如果光标在最后一行,使用rs.getXXX()获取列值,报错:After end of result set
  3. 使用完毕以后要关闭结果集ResultSet,再关闭Statement,再关闭Connection
上述知识要点整合代码:
import java.sql.*;

public class JDBCDemo01 {
    public static void main(String[] args) {
        try {
            //可能出现的异常:ClassNotFoundException
            /*原因:
            *       1.java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Drive  类名写错
            *       2.jar包未导入
            * */
            Class.forName("com.mysql.cj.jdbc.Driver");
            //3.可能出现的异常:获得数据库连接
            /*SQLException
            * 原因:1.jdbc:mysql: 其中任何一段字符串写错, ip地址协议错误
            *      2. Unknown database xxxx 数据库名字错误 找不到这个数据库
            *      3.SQLException: Access denied for user 'roo'@'localhost' (using password: YES) 数据库用户名或密码错误
            * com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure  localhost:330
            * 原因:端口错误,防火墙阻拦
            *ip地址出错,不会抛出异常,程序会阻塞,一直尝试连接
            * */
            String url = "jdbc:mysql://localhost:3306/java2106";
            Connection connection = DriverManager.getConnection(url,"root","123456");
            //System.out.println(connection);
            //4.获得执行SQL语句的Statement对象
            Statement statement = connection.createStatement();
            //执行DDL 通常用execute
            /*String sql = "create table test01(id int(6)  PRIMARY KEY)";
            boolean execute = statement.execute(sql);
            System.out.println(execute);*/
            /*//执行DML 通常用executeUpdate 如果增删改成功则返回1,增删改失败则返回0
            String sql = "update test01 set id = 1";
            int i = statement.executeUpdate(sql);
            System.out.println(i);*/
            //5.执行DQL获得 ResultSet
            String sql = "select * from emp";
            //执行可能发生的异常SQLSyntaxErrorException 一般是sql语句出现异常,根据具体信息修改异常
            ResultSet rs = statement.executeQuery(sql);
            //处理结果集 rs.next() boolean 移动到下一个位置,判断是否存在字段,如果存在则返回true
            while (rs.next()){
                int empno = rs.getInt("empno");
                String ename = rs.getString("ename");
                Date hiredate = rs.getDate("hiredate");

                System.out.println(empno + " " + ename + " " + hiredate);
            }
            //上述代码使得next()指向了结果集的最后行,再下一个则会超出范围
            //SQLException: After end of result set
            /*int no = rs.getInt("empno");
            String name = rs.getString("ename");
            Date hireDate = rs.getDate("hiredate");
            System.out.println(no + name + hireDate);*/
            //关闭资源
            rs.close();
            statement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

一些注意事项整理
import java.sql.*;

public class JDBCDemo02 {
    public static void main(String[] args) {
        try {
            Connection connection = JDBCUtils.getConnection();
            //4.获得执行SQL语句的Statement对象
            Statement statement = connection.createStatement();
            String sql = "select * from emp";
            ResultSet rs = statement.executeQuery(sql);
            //处理结果集 rs.next() boolean 移动到下一个位置,判断是否存在字段,如果存在则返回true
            while (rs.next()){
                /*int empno = rs.getInt("empno");
                String ename = rs.getString("ename");
                Date hiredate = rs.getDate("hiredate");
                System.out.println(empno + " " + ename + " " + hiredate);*/
                Emp emp = new Emp();
                emp.setEmpno(rs.getInt("empno"));
            }
            //上述代码使得next()指向了结果集的最后行,再下一个则会超出范围
            //SQLException: After end of result set
            /*int no = rs.getInt("empno");
            String name = rs.getString("ename");
            Date hireDate = rs.getDate("hiredate");
            System.out.println(no + name + hireDate);*/
            //关闭资源
            rs.close();
            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

5 数据库工具类JdbcUtils

自己创建工具类:
如果一个功能经常要用到,建议把这个功能做成一个工具类,可以再不同的地方重用。

5.1需求

出现很多的重复的代码,可以把这些公共代码抽取出来。

5.2创建类JbdcUtil包含3个方法

  1. 可以把几个字符串定义成常量:用户名,密码,URL,驱动类

  2. 得到数据库的连接:getConnection()

  3. 关闭所有打开的资源

     close(Connection conn, Statement stmt),close(Connection conn, Statement stmt, ResultSet rs)
    

5.3步骤

  1. 得到用户从控制台上输入的用户名和密码来查询数据库

  2. 写一个登陆方法

    a. 通过工具类得到连接

    b. 创建语句对象,使用拼接字符串的方式生成SQL语句

    c. 查询数据库,如果有记录则登陆成功,否则登录失败

    d. 释放资源

5.4 SQL注入问题

用户输入的密码和SQL语句的字符串拼接。用户输入的内容作为SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入,要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。

6 PreparedStatement接⼝

6.1继承结构与作用

接口:Statement、Wrapper

所有已知子接口:
CallableStatement

preparedStatement是Statement接口的子接口,继承于父接口中所有的方法。它是一个预编译的SQL语句。

作用:

  1. 因为有预先编译的功能,提高SQL的执行效率
  2. 可以有效的防止SQL注入的问题,安全性更高。

6.2 Connection 创建 PreparedSatement 对象

Connection 接⼝中的⽅法描述
PreparedStatement prepareStatement(String sql)指定预编译的 SQL 语句,SQL 语句中使⽤占位符?创建⼀个语句对象

6.3 PreparedSatement 接⼝中的⽅法

PreparedStatement 接⼝中的⽅法描述
int executeUpdate()执⾏ DML,增删改的操作,返回影响的⾏数。
ResultSet executeQuery()执⾏ DQL,查询的操作,返回结果集

6.4 PreparedSatement 的好处

  1. prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引⽤着
    预编译后的结果。可以多次传⼊不同的参数给 PreparedStatement 对象并执⾏。减少 SQL
    编译次数,提⾼效率。
  2. 安全性更⾼,没有 SQL 注⼊的隐患。
  3. 提⾼了程序的可读性。

6.5 使⽤ PreparedStatement 的步骤

  1. 编写 SQL 语句,未知内容使⽤?占位:“SELECT * FROM user WHERE name=? AND
    password=?”;
  2. 获得 PreparedStatement 对象
  3. 设置实际参数:setXxx (占位符的位置,真实的值)
  4. 执⾏参数化 SQL 语句
  5. 关闭资源
PreparedStatement 中设置参数的⽅法描述
void setDouble(int parameterIndex, double x)将指定参数设置为给定 Java double值。
void setFloat(int parameterIndex, float x)将指定参数设置为给定 Java float 值。
void setInt(int parameterIndex, int x)将指定参数设置为给定 Java int 值。
void setLong(int parameterIndex, long x)将指定参数设置为给定 Java long 值。
void setObject(int parameterIndex, Object x)使⽤给定对象设置指定参数的值。
void setString(int parameterIndex, String x)将指定参数设置为给定 Java String 值。
import java.sql.*;
import java.util.Scanner;

public class LoginDemo02 {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入密码:");
        String password = scanner.nextLine();

        Connection connection = JDBCUtils.getConnection();
        String sql = "select * from user where username=? and password=?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,username);
        preparedStatement.setString(2,password);
        //String sql = "select * from user where username = '" + username +"' and password = '"+ password +"'";
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()){
            System.out.println("用户登陆成功");
        }else {
            System.out.println("用户名或密码错误");
        }
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}

7 JDBC 事务的处理

7.1 API介绍

Connection 接⼝中与事务有关的⽅法说明
void setAutoCommit(boolean
autoCommit)参数是 true 或 false。如果设置为 false,表示关闭⾃动提交,相当于开启事务
void commit()提交事务
void rollback()回滚事务

7.2 开发步骤

  1. 获取连接
  2. 开启事务
  3. 获取到 PreparedStatement
  4. 使⽤ PreparedStatement 执⾏两次更新操作
  5. 正常情况下提交事务
  6. 出现异常回滚事务
  7. 最后关闭资源
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Demo04 {
    public static void main(String[] args) {
        Connection connection = JDBCUtils.getConnection();//连接
        String sql1 = "update customer set account = account - ? where cust_id = ?";//转出
        String sql2 = "update customer set account = account + ? where cust_id = ?";//转入
        try {
            //事务手动提交设置
            connection.setAutoCommit(false);
            PreparedStatement statement1 = connection.prepareStatement(sql1);
            PreparedStatement statement2 = connection.prepareStatement(sql2);
            statement1.setInt(1,100);
            statement1.setInt(2,1);
            statement1.executeUpdate();

            //出现异常
            //int i = 1/0;
            statement2.setInt(1,100);
            statement2.setInt(2,2);
            statement2.executeUpdate();
            //转账入账的流程结束,提交事务,事务流程结束
            connection.commit();
        } catch (SQLException throwables) {
            try {
                //如果出现异常就对事务进行回滚,结束事务
                connection.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtils {
    private static String url;
    private static String username;
    private static String password;
    private static String driver;

    static {
        Properties pro = new Properties();
        try {
            pro.load(JDBCUtils.class.getResourceAsStream("jdbc.properties"));
            url = pro.getProperty("jdbc.url");
            username = pro.getProperty("jdbc.username");
            password = pro.getProperty("jdbc.password");
            driver = pro.getProperty("jdbc.driver");
            Class.forName(driver);
        }catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public  static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,username,password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            return null;
        }
    }
}

jdbc.driver = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/java2106
jdbc.username = root
jdbc.password = 123456
这篇关于JDBC知识点整理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!