JDBC基本使用

JDBC的简介

  • JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
  • JDBC可以在各种平台上使用Java,如Windows,Mac OS和各种版本的UNIX。
  • JDBC库包括与数据库使用相关的API。

JDBC体系结构

  • JDBC API支持用于数据库访问的两层和三层处理模型,但通常,JDBC体系结构由两层组成:
    • JDBC:提供了应用程序到数据库连接规范。
    • JDBC驱动程序:连接数据库的驱动程序的实现。

JDBC

JDBC核心组件

DriverManager: 此类管理数据库驱动程序列表。使用通信协议将来自java应用程序的连接请求与适当的数据库驱动程序匹配。 Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用DriverManager对象来管理这种类型的对象。 Connection:该接口具有用于连接数据库的所有方法。连接对象表示通信上下文,数据库的所有通信仅通过连接对象。 Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派生接口还接受参数。 ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一个迭代器,允许我们移动其数据。 SQLException:此类处理数据库应用程序中发生的任何异常。

JDBC初始

使用步骤

(1) 导入JDBC驱动包:需要下载包含数据库编程所需的JDBC的jar包。

  • 在项目下创建lib目录,右击目录,选择Add as Library

(2) 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。

  • 代码示例:
     //两种方式注册驱动
     1. Class.forName("com.mysql.jdbc.Driver");//(推荐使用)
     2. Driver myDriver = new com.mysql.jdbc.Driver();
      DriverManager.registerDriver( myDriver );
    

(3) 创建连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表示与数据库的物理连接。

  • 三个重载的DriverManager.getConnection()方法:
  • getConnection(String url)
  • getConnection(String url,Properties prop)
  • getConnection(String url,String user,String password)
RDBMS JDBC驱动程序名称 连接字符串格式
MySQL的 com.mysql.jdbc.Driver jdbc:mysql://hostname:3306 / databaseName
ORACLE oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@ hostname:port Number:databaseName
DB2 COM.ibm.db2.jdbc.net.DB2Driver jdbc:db2:hostname:port Number / databaseName
SYBASE com.sybase.jdbc.SybDriver jdbc:sybase:Tds: hostname:port Number / databaseName
  • 代码示例:
     //也可以使用jdbc:mysql:///xxx
     //三个斜杠代表“localhost:3306
     String URL = "jdbc:mysql://localhost:3306/xxx";
     String USER = "root";
     String PASS = "root"
     Connection conn = DriverManager.getConnection(URL, USER, PASS);
    

(4) 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。

  • 代码示例:
    Statement stmt = conn.createStatement( );
    
  • 创建Statement对象后,您可以使用它来执行一个SQL语句,其中有三个执行方法之一。
    • boolean execute(String SQL):如果可以检索到ResultSet对象,则返回一个布尔值true; 否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。
    • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。
    • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。

关闭Statement对象

  • 就像我们关闭一个Connection对象以保存数据库资源一样,由于同样的原因,还应该关闭Statement对象。
  • 一个简单的调用close()方法将执行该作业。如果先关闭Connection对象,它也会关闭Statement对象。但是,应始终显式关闭Statement对象,以确保正确清理。
  • 代码示例:
    stmt.close();
    

(5) 从结果集中提取数据:需要使用相应的ResultSet.getXXX()方法从结果集中检索数据。

  • 使用next()获取数据,也可使用previous()倒序。使用倒序时,需要让指针指向最后一个元素,才可逆序打印

ResultSet

  • SELECT语句是从数据库中选择行并在结果集中查看行的标准方法。该java.sql.ResultSet中的接口表示结果集数据库查询。
  • ResultSet对象维护指向结果集中当前行的游标。术语“结果集”是指包含在ResultSet对象中的行和列数据。
  • 如果没有指定任何ResultSet类型,您将自动获得一个TYPE_FORWARD_ONLY。
类型 描述
ResultSet.TYPE_FORWARD_ONLY 光标只能在结果集中向前移动。
ResultSet.TYPE_SCROLL_INSENSITIVE 光标可以向前和向后滚动,结果集对创建结果集后发生的数据库的其他更改不敏感。
ResultSet.TYPE_SCROLL_SENSITIVE。 光标可以向前和向后滚动,结果集对创建结果集之后发生的其他数据库所做的更改敏感。

(6) 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

  • 代码示例:
    conn.close();
    

JDBC执行SQL语句

  • 一旦获得了连接,我们可以与数据库进行交互。JDBC Statement和PreparedStatement接口定义了使您能够发送SQL命令并从数据库接收数据的方法和属性。
接口 使用
Statement 用于对数据库进行通用访问。在运行时使用静态SQL语句时很有用。Statement接口不能接受参数。
PreparedStatement(推荐使用) 当您计划多次使用SQL语句时使用。PreparedStatement接口在运行时接受输入参数。

SQL注入

  • 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。
  • 代码示例:
    String username = xxx ' or 1=1 #;//'
    ResultSet rs=stat.executeQuery("select * from user where username='"+username+"' and password='"+password+"'");
    
  • 解释:当username等于上面的变量后(不包括//'),那个单引号就和SQL语句中的单引号匹配上,而且#后面的会被注释掉。那么这个SQL语句就失去了原来的执行能力。(可以把上面SQL语句复制到MySQL中进行测试)

PreparedStatement

  • PreparedStatement的接口扩展了Statement接口,它为您提供了一个通用的Statement对象有两个优点附加功能。
  • 作用:
    • 1预编译,效率高
    • 2 安全,避免SQL注入
  • 代码示例:
     String SQL = "Update Employees SET age = ? WHERE id = ?";
     PreparedStatement pstmt = conn.prepareStatement(SQL);
    
  • JDBC中的所有参数都由?符号,这被称为参数标记(占位符)。在执行SQL语句之前,必须为每个参数提供值。
  • 所述的setXXX()方法将值绑定到所述参数,其中XXX代表要绑定到输入参数的值的Java数据类型。如果忘记提供值,将收到一个SQLException。
  • 每个参数标记由其顺序位置引用。第一个标记表示位置1,下一个位置2等等。该方法与Java数组索引不同,从0开始。
  • 代码示例:
     //和上面对应,第一个参数是"?"(占位符)的位置
     pstmt.setInt(1,12);//age
     pstmt.setInt(2,1);//id
     PreparedStatement pstmt = conn.prepareStatement(SQL);
    

关闭PreparedStatement对象

  • 就像关闭Statement对象一样,由于同样的原因,还应该关闭PreparedStatement对象。
  • 一个简单的调用close()方法将执行该作业。如果先关闭Connection对象,它也会关闭PreparedStatement对象。但是,应始终显式关闭PreparedStatement对象,以确保正确清理。

抽取数据库工具类

  • 代码示例:
public class DbUtil {

    private static String driver;//驱动名称
    private static String url;//URL连接字符
    private static String username;//数据库用户名
    private static String password;//数据库密码

    static {  
      //driver="com.mysql.jdbc.Driver";  
      //url="jdbc:mysql://localhost:3306/myschool?useSSL=true&characterEncoding=utf8";  
      //username="root";  
      //password="root";  

        try {//改用读取配置文件形式。把上面注释的写入db.properties配置文件中,手动创建db.prperties文件(db.properties书写形式,不会就百度)
            Properties properties = new Properties();
            InputStream is = DbUtil.class.getClassLoader().getResourceAsStream("db.properties");
            properties.load(is);

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("创建驱动失败");
       }
    }
    //创建连接
    public static Connection getConnection() {
        try {
            return DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //执行命令
    public static int executeUpdate(String sql, Object... params) {
        Connection conn = getConnection();
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    ps.setObject(i + 1, params[i]);
                }
            }
            return ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(conn, ps, null);
        }
        return -1;
    }
    //释放资源
    public static void closeAll(Connection conn, Statement stat, ResultSet rs) {
        try {
            if (conn != null) {
                conn.close();
            }
            if (stat != null) {
                stat.close();
            }
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}


转载请注明:Memory的博客 » 点击阅读原文

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦