栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

一文看懂JDBC(两万字)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一文看懂JDBC(两万字)

目录

1.JDBC是什么?

2.JDBC的本质是什么?

3.开发前的准备工作

4.JDBC编程六步(背会熟记)

5. 具体实现

1.注册驱动

2.获取连接

3.获取数据库操作对象

4.执行sql 关闭连接

6. JDBC执行删除与更新

1.删除操作

 2.更新操作

7.类加载的方式注册驱动

8.从属性资源文件中读取连接数据库信息

9.处理查询结果集

10.PreparedStatement的使用


1.JDBC是什么?

Java Database Connectivity(Java语言连接数据库)

2.JDBC的本质是什么?

JDBC是sun公司置顶的一套接口(interface)

java.sql.*;(这个软件包下有很多接口)

接口都有调用者和实现者

面向接口调用、面向接口写实现类,这都属于面向接口编程

思考:为什么sun公司置顶一套JDBC接口呢?

因为每一个数据库的底层实现原理不一样

Oracle数据库有自己的原理

Mysql数据库也有自己的原理

SqlServer数据库也有自己的原理

...

每一个数据库产品都有自己独特的实现原理

原理图如下:

思考:为什么要面向接口编程?

解耦合:降低程序的耦合度,提高程序的扩展力

多态机制就是非常典型的:面向抽象编程(不要面向具体编程)

//建议:
Animal a = new Cat();
Animal a = new Dog();

//不建议:
Dog d = new Dog();
Cat c = new Cat();

3.开发前的准备工作

JDBC开发前的准备工作,先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中(如果使用IDEA工具的时候,不需要配置环境变量,配置环境变量只针对文本编辑器开发)。

官网下载jar包的地址

MySQL :: Download Connector/J

配置环境变量classpath

 而如果我们用的IDEA工具,那么操作起来就非常简单了

如果创建的是MAVEN项目,我们直接在pom.xml文件中添加依赖

    
        
            mysql
            mysql-connector-java
            8.0.26
        
    

4.JDBC编程六步(背会熟记)

第一步:注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)

第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道)

第三步:获取数据库操作对象(专门执行sql语句的对象)

第四步:执行sql语句(DQL DML...)

第五步:处理查询结果集(只有当第四步执行的select语句的时候,才由第五步处理查询结果集)

第六步:释放资源(使用完资源之后一定要关闭资源,Java和数据库属于进程间的通信,开启之后一定要关闭)

5. 具体实现

1.注册驱动

我们首先查看jdk帮助文档,发现有两个方法可以注册驱动

我们查看方法具体的解释,发现会抛出一个SQLException的异常 ,我们用try..catch来捕获异常

 编写代码:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCTest01 {
    public static void main(String[] args) throws SQLException {
        try {
            //1.注册驱动
            Driver driver = new com.mysql.cj.jdbc.Driver();//父类型引用指向子类型对象
            DriverManager.registerDriver(driver);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        //2.获取连接
        //3.获取数据库操作对象
        //4.执行sql
        //5.处理查询结果
        //6.关闭连接
    }
}

2.获取连接

我们查看jdk帮助文档,其中有三个方法可以获取连接

我们常用的是第三个,查看第三个的详细解释

 可以看到是返回的是一个Connection对象,这个就是获取到的连接对象

编写程序:

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCTest01 {
    public static void main(String[] args) throws SQLException {
        try {
            //1.注册驱动
            Driver driver = new com.mysql.cj.jdbc.Driver();//父类型引用指向子类型对象
            DriverManager.registerDriver(driver);

            //2.获取连接
            
            String url = "jdbc:mysql://127.0.0.1:3306/demodatabase2";
            String user = "root";
            String password = "root";
            Connection connection = DriverManager.getConnection(url, user, password);
            System.out.println("数据库连接对象:" + connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }


        //3.获取数据库操作对象
        //4.执行sql
        //5.处理查询结果
        //6.关闭连接
    }
}

 运行以下,控制台输出:

3.获取数据库操作对象

 查看jdk帮助文档

发现有三个方法,常用的是第一个方法,我们查看具体的解释

 可以发现这个方法返回一个Statement对象,用于将sql语句发送到数据库

编写代码:

import java.sql.*;

public class JDBCTest01 {
    public static void main(String[] args) throws SQLException {
        try {
            //1.注册驱动
            Driver driver = new com.mysql.cj.jdbc.Driver();//父类型引用指向子类型对象
            DriverManager.registerDriver(driver);

            //2.获取连接
            
            String url = "jdbc:mysql://127.0.0.1:3306/demodatabase2";
            String user = "root";
            String password = "root";
            Connection connection = DriverManager.getConnection(url, user, password);
            System.out.println("数据库连接对象:" + connection);

            //3.获取数据库操作对象
            Statement stmt = connection.createStatement();
            
        } catch (SQLException e) {
            e.printStackTrace();
        }



        //4.执行sql
        //5.处理查询结果
        //6.关闭连接
    }
}

4.执行sql 关闭连接

我们查看jdk帮助文档

首先我们执行一次INSERT插入操作,我们可以看到用红色标注起来的这个方法,点进去查看具体的解释

 返回的是一个int类型,表示影响数据库中的记录条数

这里我们用insert来对数据库中student表进行插入操作

数据库中的student表是这样设计的

编写代码:

import java.sql.*;

public class JDBCTest01 {
    public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        Connection connection = null;
        try {
            //1.注册驱动
            Driver driver = new com.mysql.cj.jdbc.Driver();//父类型引用指向子类型对象
            DriverManager.registerDriver(driver);

            //2.获取连接
            
            String url = "jdbc:mysql://127.0.0.1:3306/demodatabase2";
            String user = "root";
            String password = "root";
            connection = DriverManager.getConnection(url, user, password);
            System.out.println("数据库连接对象:" + connection);

            //3.获取数据库操作对象
            stmt = connection.createStatement();

            //4.执行sql
            String sql = "INSERT INTO student(id,age,name) VALUES(16,65,"魏桑")";
            //专门指定DML语句的(insert delete update)
            //返回值是"影响数据库中的记录条数"
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1 ? "保存成功" : "保存失败");

            //5.处理查询结果集(只有select语句才会使用到)
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.关闭连接
            //为了保证资源一定释放,在finally语句块中关闭资源
            //并且要遵循从小到大依次关闭
            //分别对其try...catch
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }
}

控制台输出: 

我们查看student表,发现插入的数据已经插入了。 

6. JDBC执行删除与更新

1.删除操作

仿照第五步的操作步骤,我们来删除student表中上一步添加的id为16号的数据

编写代码

import com.mysql.cj.jdbc.Driver;

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

public class JDBCTest02 {
    public static void main(String[] args) {
        Statement stmt = null;
        Connection conn = null;
        try {
            //1.注册驱动
            Driver driver = new Driver();
            DriverManager.registerDriver(driver);
            //2.获取连接
            String url = "jdbc:mysql://localhost:3306/demodatabase2";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url,user,password);

            //3.获取数据库操作对象
            stmt = conn.createStatement();

            //4.执行sql语句
            String sql = "DELETE FROM student WHERe id = 16";
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1 ? "删除成功" : "删除失败");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 控制台输出:

查看student的表,id为16的数据已经被删除了。

 2.更新操作

我们直接在上一步的基础上来更改代码,将id为15的名字改为魏桑

编写代码:

import com.mysql.cj.jdbc.Driver;

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

public class JDBCTest03 {
    public static void main(String[] args) {
        Statement stmt = null;
        Connection conn = null;
        try {
            //1.注册驱动
            Driver driver = new Driver();
            DriverManager.registerDriver(driver);
            //2.获取连接
            String url = "jdbc:mysql://localhost:3306/demodatabase2";
            String user = "root";
            String password = "root";
            conn = DriverManager.getConnection(url,user,password);

            //3.获取数据库操作对象
            stmt = conn.createStatement();

            //4.执行sql语句
            String sql = "UPDATE student SET name = "魏桑" WHERe id = 15";
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1 ? "更新成功" : "更新失败");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

控制台输出:

我们查看student表,可以看到id为15的数据更新成功了 

7.类加载的方式注册驱动

我们查看mysql公司实现的Driver接口

 而DriverManager.registerDriver(new Driver())在静态代码块中

如果我们要想将类的静态代码块加载,只需要加载这个类即可,那么显而易见我们可以通过反射来实现。

编写代码:

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

public class JDBCTest04 {
    public static void main(String[] args) {

        try {
            //1.注册驱动
            //这是注册驱动的第一种写法
            //DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
            //这是第二种方式,也最常规的写法,通过类加载机制
            //为什么这种方式最常用? 因为参数时一个字符串,字符串可以写到xxx.properties文件中
            //以下方法不需要接收返回值,因为我们只想用它的类加载动作
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2.获取连接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demodatabase2", "root", "root");
            System.out.println(conn);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

8.从属性资源文件中读取连接数据库信息

我们创建jdbc.properties文件,里面填入driver,url,user,password

重新编写代码

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTest05 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        Properties properties = new Properties();
        FileReader fr = null;
        try {
            fr = new FileReader("java-15-JDBC\src\main\java\jdbc.properties");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            properties.load(fr);
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(properties.getProperty("driver"));

        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");

        try {
            //1.注册驱动

            Class.forName(driver);

            //2.获取连接
            conn = DriverManager.getConnection(url,user,password);

            //3.获取操作对象
            stmt = conn.createStatement();

            //4.执行sql
            String sql = "INSERT INTO student(id,age,name) VALUES(16,45,"周星驰")";
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1 ? "插入成功" : "插入失败");
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 或者我们使用资源绑定器来优化代码

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.ResourceBundle;

public class JDBCTest06 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;

        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");

        String driver = bundle.getString("driver");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");

        try {
            //1.注册驱动

            Class.forName(driver);

            //2.获取连接
            conn = DriverManager.getConnection(url,user,password);

            //3.获取操作对象
            stmt = conn.createStatement();

            //4.执行sql
            String sql = "INSERT INTO student(id,age,name) VALUES(17,45,"周星驰")";
            int count = stmt.executeUpdate(sql);
            System.out.println(count == 1 ? "插入成功" : "插入失败");
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

9.处理查询结果集

我们查看jdk帮助文档,返回一个ResultSet结果集对象

 我们查看详细的解释

我们再去查看ResultSet类,里面有一个next方法

 我们来完善代码:

package com.lu.jdbc;

import java.sql.*;
import java.util.ResourceBundle;

public class JDBCTest07 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("driver");
        String user = bundle.getString("user");
        String url = bundle.getString("url");
        String password = bundle.getString("password");

        try {
            //1.注册驱动
            Class.forName(driver);

            //2.获取连接
            conn = DriverManager.getConnection(url,user,password);

            //3.获取数据库操作对象
            stmt = conn.createStatement();

            //4.执行sql语句
            String sql = "SELECT * FROM student";
            rs = stmt.executeQuery(sql);//专门执行DQL的方法

            //5.处理查询结果集
            while (rs.next()) {
                String id = rs.getString("id");//JDBC中所有下标都是从1开始,不是从0开始
                String age = rs.getString("age");
                String name = rs.getString("name");
                System.out.print("id: " + id);
                System.out.print(" age: " + age);
                System.out.println(" name: " + name);
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 控制台输出:

10.PreparedStatement的使用

解决sql注入问题,属于预编译的数据库操作对象

PreparedStatement的原理是:预先对SQL语句的框架进行编译,然后再给sql语句传“值”

我们来编写代码

package com.lu.jdbc;

import java.sql.*;
import java.util.ResourceBundle;

public class JDBCTest08 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("driver");
        String user = bundle.getString("user");
        String url = bundle.getString("url");
        String password = bundle.getString("password");

        try {
            //1.注册驱动
            Class.forName(driver);

            //2.获取连接
            conn = DriverManager.getConnection(url,user,password);

            //3.获取数据库操作对象
            String sql = "SELECt * FROM student WHERe id = ?";
            ps = conn.prepareStatement(sql);
            //给占位符?传值(第一个问号下标是1,第二个问号下标是2,JDBC中所有下标从1开始)
            ps.setInt(1,15);

            //4.执行sql语句
            rs = ps.executeQuery();

            //5.处理查询结果集
            while (rs.next()) {
                String id = rs.getString("id");//JDBC中所有下标都是从1开始,不是从0开始
                String age = rs.getString("age");
                String name = rs.getString("name");
                System.out.print("id: " + id);
                System.out.print(" age: " + age);
                System.out.println(" name: " + name);
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Statement和PreparedStatement的区别

1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程

2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。

3.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得,   preparedstatement支持批处理

结论:

PreparedStatement使用较多,只有极少数的情况下需要使用Statement

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346014.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号