JDBC简介

一、简介

1.JDBC概念

客户端操作MySQL数据库的方式:

  1. 使用第三方给客户端来访问MySQLSQLyogNavicatSQLWaveMyDB StudioEMS SQL Manager for MySQL
  2. 使用MySQL自带的命令行方式。
  3. 使用Java来访问MySQL数据库。
    什么是jdbcJava数据库连接,JDBC是一种用于执行SQL语句的Java API,可以为多种数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一组标准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
    有了JDBC,向各种数据库发送SQL语句就是一件很容易的事。换言之,有了JDBC API,就不必为访问MySQL数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问DB2数据库又编写另一个程序等等,程序员只需用JDBC API写一个程序就够了,它可
    向相应数据库发送SQL调用。同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java语言“编写一次,处处运行”的优势。
    Java数据库连接体系结构是用于应用程序连接数据库的标准方法。对程序员而言是,对实现与数据库连接的服务提供商而言是接口模型。作为,为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。

2.JDBC的作用

JDBC是用于执行SQL语句的Java API(Java语言通过JDBC可以操作数据库)。
JDBC 可以干三件事:
4. 与数据库建立连接。
5. 将Java中拼写的SQL语句发送到数据库中执行。
6. 处理执行结果

3.JDBC在开发中的地位

在技术上,JDBC实现数据的添加、删除、修改、查询等操作,是Java应用程序与数据库通信的桥梁。
软件开发中的界面负责数据输入,并将输入的数据提交给Java程序,Java程序通过JDBC将数据保存到数据库中。JDBC也负责从数据库中获取数据,然后将数据交给Java程序,最后Java程序将数据交给界面显示,如下图所示。
JDBC简介_第1张图片

二、 JDBC API

Java程序访问数据库,使用JDBC提供的一套标准API,这套API主要是接口,由各个数据库的厂商去实现,并封装成jar包的形式提供给开发人员,如下图所示:
JDBC简介_第2张图片
在实际项目开发中,我们确定要连接的数据库,在对应的数据库官方网站下载厂商已经实现的数据库连接用的驱动jar包,将驱动jar包导入到我们的项目中即可完成项目对特定数据库连接的支持。
项目支持了数据库的连接之后,就需要开发人员开发具体的程序来实现数据库数据的操作了。java是面向对象的语言,java提供了以下接口和类来支持和数据库之间的操作。

类或接口 作用
java.sql.DriverManager类 表示数据库驱动包的管理对象
java.sql.Connection接口 表示数据库的连接对象
java.sql.Statement接口 表示发送sql给数据库执行的对象
java.sql.PreparedStatement接口 java.sql.Statement的子接口,表示sql预编译对象
java.sql.ResultSet接口 表示从数据库操作返回的结果数据
JDBC在运行时的大致步骤如下图所示,执行的顺序如下。
  1. 由 DriverManager 类驱动数据库。
  2. 由 Connection 接口负责将Java程序和数据库建立连接。
  3. 由 Statement/PreparedStatement 接口将SQL语句发送到数据库中。
  4. 由 ResultSet 接口处理数据库返回的结果集。
    JDBC简介_第3张图片
    JDBC简介_第4张图片

1.DriverManager

java.sql.DriverManager 用于管理一组 JDBC 驱动程序的基本服务。可以通过该管理类来建立并获取和指定数据库之间的连接。

public class DriverManager

static方法

常用的方法有:

  • public static Connection getConnection(String url, String user, String password) :使用账号 user 和密码 password ,建立到指定数据库 URL 的连接,连接成功后返回新的数据库连接。
  • public static Connection getConnection(String url) :尝试查找了解给定URL的驱动程序(将数据库用户信息包含在url中)。
  • public static void registerDriver(java.sql.Driver driver) :向 DriverManager 注册给定驱动程序。

数据库连接字符串

DriverManager类在加载数据库驱动时,需要指明url,url通常指数据库连接字符串。数据库连接字符串通常用于连接协议、连接的数据库服务器、端口号、数据库名称及其连接参数。
其格式如下:

主协议:子协议://数据库服务器:端口号/数据库名称?连接参数

jdbc:mysql://localhost:3306/companys?user=root&password=root

常用参数表:
JDBC简介_第5张图片

characterEncoding=utf8&useSSL=false&serverTimezone=UTC

2.Connection

java.sql.Connection用于与数据库的连接,执行SQL语句并在上下文中返回结果。只有在数据库连接后,才能将SQL语句发送到数据库执行。

public interface Connection extends Wrapper, AutoCloseable

常用方法:

  • Statement createStatement():创建一个Statement对象,用于将SQL语句发送到数据库。
  • PreparedStatement prepareStatement(String sql):创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
  • PreparedStatement prepareStatement(String sql, int autoGeneratedKeys):创建一个默认的PreparedStatement对象,该对象获取自动生成的键,autoGeneratedKeys值可以是:Statement.RETURN_GENERATED_KEYS / Statement.NO_GENERATED_KEYS
  • void setAutoCommit(boolean autoCommit):将此连接的自动提交模式设置为给定状态,默认为自动提交。
  • void commit():使自上次提交/回滚以来所做的所有更改都永久化,并释放此Connection对象当前所持有的数据库锁。
  • void rollback():撤消在给定的 Savepoint对象设置后进行的所有更改。
  • Savepoint setSavepoint():在当前事务中创建一个未命名的保存点,并返回代表它的新的 Savepoint对象。
  • Savepoint setSavepoint(String name):在当前事务中创建具有给定名称的保存点,并返回代表它的新的 Savepoint对象。
  • boolean isClosed() :检索此 Connection对象是否已关闭。
  • void close():Connection释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放。 在已关闭的Connection对象上调用方法close是无操作的。

3.Statement

java.sql.Statement用于执行静态SQL语句并返回其生成的结果的对象。默认情况下,每个Statement对象只能有一个ResultSet对象同时打开。

public interface Statement extends Wrapper, AutoCloseable

常用方法:

  • boolean execute(String sql):执行指定的SQL语句,这可能会返回多个结果。
    - boolean execute(String sql, int autoGeneratedKeys):执行给定的 SQL 语句(该语句可能返回多个结果),并通知驱动程序所有自动生成的键都应该可用于获取。autoGeneratedKeys值可以是:Statement.RETURN_GENERATED_KEYS / Statement.NO_GENERATED_KEYS
  • ResultSet getGeneratedKeys():检索由执行此Statement对象而创建的任何自动生成的密钥。 如果此Statement对象未生成任何键,则返回空的ResultSet对象
  • ResultSet getResultSet() :检索当前结果为ResultSet对象。 每个结果应该只调用一次这个方法。
    - int getUpdateCount() :将当前结果作为更新计数检索; 如果结果是ResultSet对象或没有更多的结果,则返回-1。 每个结果应该只调用一次这个方法。
  • int executeUpdate(String sql) :执行给定的SQL语句,这可能是 INSERTUPDATE,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。
  • ResultSet executeQuery(String sql) :执行给定的SQL语句,该语句返回单个ResultSet对象
  • boolean isClosed() :如果这个Statement对象关闭,则为true; 如果它仍然开放,则为false
  • void close():Statement释放此Statement对象的数据库和JDBC资源,而不是等待其自动关闭时发生。调用已关闭的Statement对象上的方法close不起作用。当一个Statement对象关闭时,其当前的ResultSet对象(如果存在)也被关闭

4.PreparedStatement

java.sql.PreparedStatement 表示预编译的SQL语句的对象,SQL语句已预编译并存储在PreparedStatement对象中。 然后可以使用该对象多次有效地执行此语句。

public interface PreparedStatement extends Statement

常用方法

该接口继承自Statment接口

  • void setObject(int parameterIndex, Object x) :使用给定对象设置指定参数的值。
  • ResultSet executeQuery() :执行此PreparedStatement对象的SQL查询,并返回查询的PreparedStatementResultSet对象。
  • int executeUpdate():执行在该SQL语句PreparedStatement对象,它必须是一个SQL数据操纵语言(DML)语句,如INSERT,UPDATEDELETE;或不返回任何内容的SQL语句,例如DDL语句。

5.ResultSet

java/sql.ResultSet表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。

public interface ResultSet extends Wrapper, AutoCloseable

常用方法:

  • boolea next():将光标从当前位置向后移动一行。ResultSet光标最初位于第一行之前;第一次调用方法next使第一行成为当前行;第二个调用使第二行成为当前行,以此类推。如果新的当前行有效返回true,没有更多行返回false
  • Object getObject(int columnIndex):获取当前行中指定列的值,第一列是1。
  • Object getObject(String columnLabel):获取当前行中指定列的值,使用指定列的标签。
  • void close():关闭此ResultSet对象的数据库和JDBC资源,而不是等待此事件自动关闭。
  • boolean isClosed():检索此ResultSet对象是否已关闭。

6.ResultSetMetaData

java.sql.ResutSetMetaData可用于获取有关ResultSet对象中列的类型和属性的信息的对象。使用ResultSet对象的getMetaData()获取。

public interface ResultSetMetaData extends Wrapper

方法

JDBC简介_第6张图片
JDBC简介_第7张图片
JDBC简介_第8张图片

使用JDBC

使用JDBC实现业务的步骤:

  1. 导入数据库驱动jar
  2. 注册数据库驱动程序
  3. 建立和数据库之间的连接
  4. 拼写SQL语句
  5. 向数据库发送并执行SQL语句
  6. 处理执行结果
  7. 关闭资源

导入jar包

MySQLjdbc jar包是mysql-connector-java-xx.jar,将其添加到项目依赖即可。

注册驱动

Java程序需要通过数据库驱动才能连接到数据库,因此需要注册驱动。MySQL的驱动的入口类是:com.mysql.jdbc.Driver

使用

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

查看com.mysql.jdbc.Driver源代码发现:
JDBC简介_第9张图片
Driver类中有一个static块,在类被加载时会注册驱动。所以使用DriverManager.registerDriver(new com.mysql.jdbc.Driver());注册驱动会导致注册两次驱动。因此不推荐用此方法注册,而是使用Class.forName(str);加载驱动,这样只会注册一次驱动。

获取连接

//创建连接
        String url="jdbc:mysql://localhost:3306/company?serverTimezone=UTC";
        String user="root";
        String pass="";
        Connection connection = DriverManager.getConnection(url, user, pass);

实现业务

在MySQL中,只要不是查询就是修改。executeUpdate:用于执行增删改,executeQuery:用于执行查询。

实现增加用户业务

package jdbc.day5;

import java.sql.*;

/**
 * @author Administrator
 */
public class Demo01 {
    public static void main(String[] args) {
        try (Connection connection = getConnection()) {
            Statement statement = connection.createStatement();
            String sql = "insert into emp(ENAME) values ('%s')".formatted("浩哥");
            int rows = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            if (rows > 0) {
                System.out.println("执行成功");
                ResultSet generatedKeys = statement.getGeneratedKeys();
                if (generatedKeys.next()) {
                    System.out.println(generatedKeys.getObject(1));
                }
            }
            // 关闭Statement对象
            statement.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    private static Connection getConnection() {
        //注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        //获取连接
        String url="jdbc:mysql://localhost:3306/company";
        String user="root";
        String pass="";
        try {
            Connection connection = DriverManager.getConnection(url, user, pass);
            return connection;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

    }
}

如果出现乱码,设置连接参数中的characterEncoding

获取主键

package jdbc.day6_930;

import java.sql.*;

public class major {
    public static void main(String[] args) {
        //注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            //创建数据库连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/company", "root", "");
            //定义SQL语句
            String sql="insert into books(id,book_title) values(1,'活着')";

            //创建执行SQL的对象
            Statement statement = connection.createStatement();

            //执行SQL,返回影响行数
            int i = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
            if (i>0){
                System.out.println("添加成功,影响行数:"+i);
            }else {
                System.out.println("添加失败");
            }

            //获取主键
            ResultSet generatedKeys = statement.getGeneratedKeys();
            if (generatedKeys!=null){
                while (generatedKeys.next()){
                    System.out.println("主键:"+generatedKeys.getObject(1));
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }


    }
}

查询所有用户

package jdbc.day5;

import java.sql.*;

public class Demo04 {
    public static void main(String[] args) {
        int no=1;
        String password="1111' or no= '1";

        boolean login=login(no,password);
        if (login){
            System.out.println("登陆成功");
        }else {
            System.out.println("登陆失败");
        }
    }

    private static boolean login(int no, String password) {
        String url="jdbc:mysql://localhost:3306/companys";
        String user="root";
        String pass="";

        try (Connection connection = DriverManager.getConnection(url, user, pass);
             Statement statement = connection.createStatement()){

            //用formatted()构建一个SQL查询语句
            String sql="select * from category where no=%d and name='%s'".formatted(no,password);
            System.out.println(sql);
            ResultSet resultSet = statement.executeQuery(sql);

            //resultSet.next()判断结果集中是否有数据
            return  resultSet.next();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

ResultMetaData使用

package jdbc.day6_930;

import java.sql.*;

public class MetaDataTest {
    public static void main(String[] args) {
        //注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            //创建数据库连接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/company", "root", "");
            String sql="select * from emp";

            //创建执行SQL的对象
            Statement statement = connection.createStatement();

            //执行SQL,返回结果集
            ResultSet resultSet = statement.executeQuery(sql);
            ResultSetMetaData data = resultSet.getMetaData();

            //遍历列名称-列类型  getColumnCount列数
            for (int i = 1; i <= data.getColumnCount(); i++) {

                System.out.println(data.getColumnName(i)+"--"+data.getColumnTypeName(i));
            }
            connection.close();
            statement.close();
            resultSet.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

PreparedStatement使用

PreparedStatement具有高效率的优点:如果用一条SQL语句每次都分析语法,编译,执行,显然效率低下。使用PreparedStatement接口将编译过的SQL语句缓存,当再次执行缓存的SQL语句时,会忽略分析语法和编译的过程,提高了运行效率。在开发中建议使用PreparedStatement接口执行SQL语句。
PreparedStatement具有安全的优点:PreparedStatement可以以防止SQL注入。SQL注入是利用SQL语句的漏洞对数据库发送有潜在威胁的SQL语句。

你可能感兴趣的:(JDBC,开发语言,数据结构,java,tomcat,spring,intellij-idea)