JDBC初体验(一)

一、JDBC概述

JDBC(Java DateBase Connectivity)是Java数据库连接技术的简称,提供连接各种常用数据库的能力

1.1 JDBC工作原理

JDBC API

提供者:Sun公司

作用:Java访问数据库的标准规范。提供给程序员调用的接口与类,集成在java.sql和javax.sql包中

DriverManager(驱动管理者)

提供者:Sun公司

作用:管理各种不同的JDBC驱动,并获取数据库连接

JDBC驱动

提供者:各大数据库厂商

作用:JDBC是接口,而JDBC驱动才是接口的实现。每个数据库厂商都有自己的驱动,用来连接自己公司的数据库

1.2 JDBC核心API简介

JDBC API的主要功能:与数据库建立连接、执行SQL语句、处理结果和释放资源

API名称API作用
DriverManager注册驱动,获取Connection连接对象
Connection负责连接数据库并担任传送数据的任务,最为重要的就是用来产生Statement对象
Statement负责向数据库发送SQL语句,这样数据库就会执行发送过来的SQL语句
ResultSetResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生,结果集是一个二维的表格

二、JDBC开发步骤

JDBC编程模板

①加载驱动

DriverManager用于加载驱动,并创建与数据库的连接,该API常用方法:

  • DriverManager.registerDriver(new Driver())
  • DriverManager.getConnection(url,user,password)

注意:在实际开发中不推荐采用registerDriver方法注册驱动,原因:

  1. 查看Driver源代码可以看到,如果采取该方式,会导致驱动程序注册两次,从而导致内存中会存在两个Driver对象
  2. 程序依赖MySQL的API,脱离MySQL的jar包,程序将无法编译,将来程序切换底层数据库的话会非常麻烦

②获取Connection对象

username和password是登录数据库的用户名和密码

url用来找到要连接数据库的“网址”。MySQL的URL:

jdbc:mysql://localhost:3306/myschool

JDBC规定url的格式由三部分组成,每个部分使用冒号分隔:

  • 第一部分是jdbc,是固定的
  • 第二部分是数据库厂商名称
  • 第三部分是数据库服务器的IP地址(localhost)、端口号(3306),已经数据库名称(该章节以数据库myschool作为演示)组成

Connection接口的常用方法

方法名方法的作用
createStatement()创建向数据库发送sql的statement对象
prepareStatement(sql)创建向数据库发送预编译sql的prepareStatement对象
prepareCall(sql)创建执行存储过程的callbleStatement对象
setAutoCommit(bollean autoCommit)设置事务是否自动提交
commit()在此连接上提交事务
rollback()在此连接上回滚事务
close()关闭数据库连接

③创建Statement对象,执行SQL语句

Statement对象是通过Connection对象的方式创建的

//创建Statement对象
Statement stmt = con.createStatement();

Statement对象用来向数据库发送要执行的SQL语句

//发送给服务器的SQL语句
String sql = "select username from users";

//执行SQL语句,并返回结果集
ResultSet rs = stmt.executeQuery(sql);

Statement接口的常用方法

④返回ResultSet对象,查询结果

//执行SQL语句,并返回结果集
String sql = "select username from users";
ResultSet rs = stmt.executeQuery(sql);

//读取结果
while(rs.next()){
    String userName=rs.getString("username");
    System.out.println(userName);
}

ResultSet接口的常用方法

⑤释放资源

  • jdbc程序运行完成后,一定要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet、Statement和Connection对象,特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是,尽量晚创建、尽量早释放
  • 为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中
//释放资源
try {
    if(rs!=null){
        rs.close();
    }
} catch (SQLException e) {
    e.printStackTrace();
}
try {
    if(stmt!=null){
        stmt.close();
    }
} catch (SQLException e) {
    e.printStackTrace();
}
try {
    if(conn!=null){
        conn.close();
    }
} catch (SQLException e) {
    e.printStackTrace();
}

三、代码演示

读取一共有几行数据

package day01;

import java.sql.*;

/**
 * @datetime: 2024/1/10
 * @desc:JDBC编程模板-读取一共有几行数据
 */

public class CheckTheQuantityOfData {
    // JDBC连接参数
    private static String url = "jdbc:mysql://127.0.0.1:3306/myschool?useSSL=false";
    private static String username = "root";
    private static String password = "这里填数据库的密码";

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

        try {
            //1、加载驱动
            Class.forName("com.mysql.jdbc.Driver");

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

            //3、创建statement对象,并发送/执行SQL
            stmt = conn.createStatement();
            String sql = "SELECT COUNT(1) FROM USER";
            rs = stmt.executeQuery(sql);

            //4、处理结果
            int userCount = 0;
            while (rs.next()) {
                userCount = rs.getInt("count(1)");
            }
            System.out.println("该表中一共有" + userCount + "条记录");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5、释放资源
            try {
                if(rs!=null){
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(stmt!=null){
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

显示整个表格

package day01;

import java.sql.*;

/**
 * @datetime: 2024/1/10
 * @desc:JDBC编程模板-显示整个表格
 */

public class DisplayTable {
    //JDBC连接参数
    private static String url = "jdbc:mysql://127.0.0.1:3306/myschool?useSSL=false";
    private static String username = "root";
    private static String password = "这里填的是数据库密码";

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

        try {
            //1、加载驱动
            Class.forName("com.mysql.jdbc.Driver");

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

            //3、创建statement对象,并发送/执行SQL
            stmt = conn.createStatement();
            //查询全部
            String sql = "SELECT ID,USERNAME,USERPASS,ROLE FROM USER";
            rs = stmt.executeQuery(sql);

            //4、处理结果
            while (rs.next()) {
                int id = rs.getInt("ID");
                String userName = rs.getString("USERNAME");
                String userPass = rs.getString("USERPASS");
                int role = rs.getInt("ROLE");

                System.out.println("ID:" + id + "\t\t用户名:" + userName + "\t\t密码:" + userPass + "\t\t角色:" + role);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //5、释放资源
            try {
                if(rs!=null){
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(stmt!=null){
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

四、带详细解释版代码

UserJdbc

package JDBC.userjdbc;

import java.sql.*;

/**
 * @author: zkz
 * @datetime: 2024/2/17
 * @desc:
 */

public class UserJdbc {
    private static String url = "jdbc:mysql://127.0.0.1:3306/myschool?useSSL=false";     //这里的“myschool”是数据库名称,不是表名称
    private static String userName = "这里填数据库名称";
    private static String password = "这里填数据库密码";

    public static void main(String[] args) {
        //下面这三个的意思是:第五步释放资源的时候,因为这三个的主体和第五步不在一个作用域
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            //(为什么这几步要写在一个异常里?因为各自都有需要处理的异常,所以直接写在一个try catch里)

            //1、加载驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2、获取连接
            conn = DriverManager.getConnection(url,userName,password);   //因为这三个参数是固定的不会改变,所以直接在最上面写成静态变量

            //3、创建Statement对象,并发送/执行sql语句
            stmt = conn.createStatement();
            String sql = "SELECT COUNT(1) FROM USER";   //这条sql语句的意思是,查询表中一共有多少条数据
            //3.1发送sql语句
            rs = stmt.executeQuery(sql);

            //4、处理结果
            //因为返回的结果集是一个表,表都有可能是多行多列的,所以需要用循环去解析,
            // 并且要判断有没有下一个结果(rs.next()判断的条件是这个结果集有数据的时候,next表示接下来还有数据)
            int userCount = 0;      //因为这里做演示的是查询表中一共有多少条数据,所以定义一个int型记录次数
            while (rs.next()) {
                userCount = rs.getInt(1);       //因为返回的结果集只有一列
            }
            System.out.println("该表中一共有" + userCount + "条数据");
        } catch (ClassNotFoundException e) {
           e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {

            //5、释放资源
            //关闭资源的时候,因为是正着创建的,所以要倒着去关
            try {
                if (rs != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (stmt != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

    }
}

UserJdbc02

UserJdbc01的更新,改了sql语句,sql语句变为了查询表中全部数据

package JDBC.userjdbc;

import java.sql.*;

/**
 * @author: zkz
 * @datetime: 2024/2/17
 * @desc:UserJdbc01的更新,改了sql语句,sql语句变为了查询表中全部数据
 */

public class UserJdbc02 {
    private static String url = "jdbc:mysql://127.0.0.1:3306/myschool?useSSL=false";     //这里的“myschool”是数据库名称,不是表名称
    private static String userName = "这里填数据库用户名";
    private static String password = "这里填数据库密码";

    public static void main(String[] args) {
        //下面这三个的意思是:第五步释放资源的时候,因为这三个的主体和第五步不在一个作用域
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            //(为什么这几步要写在一个异常里?因为各自都有需要处理的异常,所以直接写在一个try catch里)

            //1、加载驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2、获取连接
            conn = DriverManager.getConnection(url,userName,password);   //因为这三个参数是固定的不会改变,所以直接在最上面写成静态变量

            //3、创建Statement对象,并发送/执行sql语句
            stmt = conn.createStatement();
            String sql = "SELECT * FROM USER;";   //这条sql语句的意思是:查询表中全部数据
            //3.1发送sql语句
            rs = stmt.executeQuery(sql);

            //4、处理结果
            //因为返回的结果集是一个表,表都有可能是多行多列的,所以需要用循环去解析,
            // 并且要判断有没有下一个结果(rs.next()判断的条件是这个结果集有数据的时候,next表示接下来还有数据)

            //所有的查询操作,第一行都是这样写while (rs.next())

            while (rs.next()) {
                int id = rs.getInt(1);
                String username = rs.getString(2);
                String userpass = rs.getString(3);
                int role = rs.getInt(4);

                System.out.println("ID:" + id + "\t\tUSERNAME:" + username + "\t\tUSERPASS:" + userpass + "\t\tROLE:" + role);
            }

        } catch (ClassNotFoundException e) {
           e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {

            //5、释放资源
            //关闭资源的时候,因为是正着创建的,所以要倒着去关
            try {
                if (rs != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (stmt != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

    }
}

UserJdbc03

UserJdbc01的更新,跟pojo实体类相关

pojo实体类文件夹

user类
package JDBC.pojo;

/**
 * @author: zkz
 * @datetime: 2024/2/17
 * @desc:接UserJdbc03
 * //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~如果要统一管理统一去使用的话,还是要使用java对象甚至集合的     实体类对象
 * pojo指实体类
 * ~~~~~~~~~~带有此符号代表UserJdbc03跟该类的连接
 */

public class User {
    private int id;
    private String userName;
    private String userPass;
    private int role;

    //生成以上四个的get、set方法和为了方便操作的toString
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPass() {
        return userPass;
    }
    public void setUserPass(String userPass) {
        this.userPass = userPass;
    }

    public int getRole() {
        return role;
    }
    public void setRole(int role) {
        this.role = role;
    }

    @Override
    public String toString() {
        return "user{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", userPass='" + userPass + '\'' +
                ", role=" + role +
                '}';
    }
}

UserJdbc03主体

package JDBC.userjdbc;

import JDBC.pojo.User;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: zkz
 * @datetime: 2024/2/17
 * @desc:UserJdbc01的更新,跟pojo实体类相关
 */

public class UserJdbc03 {
    private static String url = "jdbc:mysql://127.0.0.1:3306/myschool?useSSL=false";     //这里的“myschool”是数据库名称,不是表名称
    private static String userName = "填用户名";
    private static String password = "填密码";

    public static void main(String[] args) {
        //!!!!!!!!!!这一部分原来的代码统一写到了下面的方法里了,以下是新代码:
        List<User> userList = getUserList();
        //做一个判断,如果是空或者是空集合的话输出未查询到任何数据,否则的话输出查询结果
        if (userList == null || userList .isEmpty()) {
            System.out.println("未查询到任何数据!");
        } else {
            userList.forEach(System.out::println);      //只要类中有tostring方法,就可以使用这个Lambda表达式
        }
    }

    //!!!!!!!!!!直接写到一个方法里
    public static List<User> getUserList() {
        //下面这三个的意思是:第五步释放资源的时候,因为这三个的主体和第五步不在一个作用域
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        //~~~~~~~~~~创建一个集合(泛型)
        List<User> userList = new ArrayList<>();

        try {
            //(为什么这几步要写在一个异常里?因为各自都有需要处理的异常,所以直接写在一个try catch里)

            //1、加载驱动
            Class.forName("com.mysql.jdbc.Driver");

            //2、获取连接
            conn = DriverManager.getConnection(url,userName,password);   //因为这三个参数是固定的不会改变,所以直接在最上面写成静态变量

            //3、创建Statement对象,并发送/执行sql语句
            stmt = conn.createStatement();
            String sql = "SELECT ID,USERNAME,USERPASS,ROLE FROM USER";   //这条sql语句的意思是,查询表中ID,USERNAME,USERPASS,ROLE四列的数据
            //3.1发送sql语句
            rs = stmt.executeQuery(sql);

            //4、处理结果
            //因为返回的结果集是一个表,表都有可能是多行多列的,所以需要用循环去解析,
            // 并且要判断有没有下一个结果(rs.next()判断的条件是这个结果集有数据的时候,next表示接下来还有数据)
            //所有的查询操作,第一行都是这样写while (rs.next())
            //~~~~~~~~~~~~~~~~~~只要有一条数据,就要创建一个新的对象,有了一个新的对象表示要new一个构造方法出来
            User user = null;       //只要有下一条数据,就在循环中创建新对象
            while (rs.next()) {
                //创建新对象的语法:
                user = new User();

                user.setId(rs.getInt(1));
                user.setUserName(rs.getString(2));
                user.setUserPass(rs.getString(3));
                user.setRole(rs.getInt(4));

                //~~~~~~~~~~~每一个对象遍历完后添加到这个集合里去
                userList.add(user);
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {

            //5、释放资源
            //关闭资源的时候,因为是正着创建的,所以要倒着去关
            try {
                if (rs != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    rs.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (stmt != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {       //关闭资源的时候,需要判断rs是否为空(空值判断)
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return userList;
    }
}

  • 31
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值