javaweb基础----JDBC(一)

news2024/12/26 22:14:55

一、什么是JDBC

JDBC全称为Java数据库连接(Java Database Connectivity),是一套用于执行SQL语句的Java API。应用程序可以通过这套API连接到关系型数据库,并使用SQL语句完成对数据中数据的查询、增加、更新和删除等操作。

JDBC在应用程序与数据库之间起到了一个桥梁作用,当应用程序使用JDBC访问特定的数据库时,需要通过不同数据库驱动(所谓数据库驱动就是数据库厂商提供链接数据库的jar包)与不同数据库进行连接,连接后即可对该数据库进行相应的操作。

由于不同的数据库厂商提供的数据库驱动各不相同,在使用不同的数据库的时候需要学习对应的数据库驱动的api,对于开发人员来说学习成本会非常高.

于是sun公司提供了jdbc规范.本质上是一大推的接口,所有的数据库驱动都实现这一套接口,这样如果换数据库只需要换驱动包即可.

驱动包和jdbc规则的关系是父接口和实现类的关系.

JDBC常用API主要位于Java.sql包中,该包定义了一系列访问数据库的接口和类:

1.Driver 接口:代表驱动程序;

2.DriverManager 类:驱动程序管理员;

3.Connection 接口:代表数据库连接;

4.Statement 、PreparedStatement、CallableStatement 接口:代表数据库操作对象;

5.ResultSet 接口:代表结果集;

6.DatabaseMetadata、ResultSetMetadata接口:代表元数据;

7.Types 类:代表JDBC类型。  

二、JDBC入门代码

1 、在IDEA下新建工程并在工程目录下新建lib文件夹

2、 将数据库驱动拷贝到lib文件夹下

这是Java与数据库建立链接的前提基础。

然后现在来准备数据,构建一个数据库表:

前提条件准备完毕,开始在IDEA中写代码与数据库建立链接。

导入包。

public class Demo1 {                          //抛异常
    public static void main(String[] args) throws Exception {
        //1 注册驱动                  //报错1、抛异常2、或者try/catch捕获异常
        DriverManager.registerDriver(new Driver());
        //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb_21","root","*******");
        //3 获取执行sql语句的对象
        Statement stat = conn.createStatement();
        //4 执行sql语句并拿到结果
        //查询操作使用的方法只能是executeQuery
        ResultSet rs=stat.executeQuery("select * from user"); //ResultSet结果集/虚拟表
        //5 处理执行结果
        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));

        }
        //6 释放资源
        conn.close();
        stat.close();
        rs.close();
    }
}

异常的处理方法:1、直接抛异常,throws Exception    2、用try / catch捕获处理异常

第一步(1)注册驱动    DriverManager.registerDriver(new Driver() );

用驱动包中的驱动程序管理员创建注册驱动Driver。

第二步(2)获取链接    Connection conn = DriverManager.getConnection(url:" jdbc:mysql://localhost:3306/mydb_21", user:" root ",password:" ******* ");

用驱动管理程序创建获取链接,getConnection方法有3个重载方法,上文的这个是包含3个string类型的方法,url:数据库地址,后面是 "协议 : 子协议 :// IP:端口号 / 数据库名称 "

user: 数据库用户名 ,password:密码。

重载方法2:

我们知道要链接到数据库需要数据库地址、数据库用户名和密码3样东西,无论如何都绕不开这些,这里2个参数保留了数据库地址参数,而将用户名密码封装在Properties中。

      //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Properties info = new Properties();
        info.setProperty("user","root");
        info.setProperty("password","*********");
        Connection conn=DriverManager.getConnection("",info);
创建一个Properties对象info,将用户名密码封装其中。

重载方法3:

如上所述,连接数据库绕不开三要素,这里只需要一个参数url,实际上是用? 和&符号将用户名密码连到数据库地址后面:

      //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb-21?user=root&password=*********");

类似网址中的:
CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor?spm=1011.2124.3001.6192

第三步(3)  获取执行sql语句的对象

 Statement stat = conn.createStatement();

用上一步的conn对象创建stat对象,用于执行sql语句。

第四步(4)  查询sql语句并拿到结果

ResultSet rs = stat.executeQuery("select* from user);

stat是用来执行sql语句select* from user的对象,将结果赋给rs变量,executeQuery方法是只能查询操作使用,返回值是ResultSet,还有一个方法是executeUpdate,返回值是int。

ResultSet是结果集/虚拟表。

 第五步(5)  处理执行结果

        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }

 将执行结果(数据库数据)打印在终端上。

  rs.next() 是游标,数据库下一行有数据时返回true,否则返回false。

getObject()是获取数据,因为不知道数据库表中存的是什么类型的数据,Object是所有类的子类。

第六步(6)  释放资源

conn.close();

stat.close();

rs.close();     顺序无所谓,哪个关闭都行。

一定要记得关闭释放资源,否则内存会不够。

上述流程可以形象地抽象为下面一张图:

左边是IDEA,可抽象为城市A,右边是与之建立链接的数据库,可抽象为城市B。

中间要想建立连接需要搭建桥梁Connection,也需要建桥的人DriverManager,开往B的车辆Statement返回时以ResultSet的形式返回。

三、各部分详解

(1)DriverManager.registerDriver(new Driver() );

 进入registerDriver方法的定义中,我们发现驱动被注册了2次,并且高度依赖驱动包。这是该语句的2个问题。

解决方法:使用驱动的加载。

Class.forName("com.mysql.jdbc.Driver"); 用该语句代替上面的注册驱动。

(2)stat执行sql语句

有executeQuery方法和executeUpdate方法,前者用于查询操作,后者用于增删改操作。

executeUpdate方法的返回值是int,以下是示例:

public class Demo2 {
    @Test                                      //抛异常
    public void test01() throws Exception {
        //1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        Properties info = new Properties();
        info.getProperty("user", "root");
        info.getProperty("password", "********");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb-21");
        Statement stat = conn.createStatement();
        int i = stat.executeUpdate("insert into user values(5,'eee',29,'男')");
        if (i > 0) {
            System.out.println("更新成功");
        } else {
            System.out.println("更新失败");
        }
        conn.close();
        stat.close();
    }
}

PS:这里的@Test是:  在Java中,@Test 是JUnit测试框架中的一个注解,用于标记一个测试方法。使用 @Test 注解可以告诉JUnit测试运行器(test runner)该方法是一个测试方法,并且应该被执行。(不同@Test直接创建其它类也可以)

 插入一条数据,如果插入成功返回1,失败返回0.   

删除语句

    public void test02() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection
                ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=*******");
        Statement stat = conn.createStatement();
        int i = stat.executeUpdate("delete from user where id = 4");
        if(i > 0){
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
        conn.close();
        stat.close();
    }
}

(3) 结果集的处理

像上面

   //5 处理执行结果
        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }

这就是结果集的处理的第一种方式;

又比如:

  while (rs.next()){
       System.out.println(rs.getInt("id"));
       System.out.println(rs.getString("name"));
       System.out.println(rs.getInt("age"));
   }

这就是结果集的处理的第二种方式,但是这2种方法都存在问题。因此我们最好将结果集封装起来。

创建一个User类,用于创建对象将数据添加到结果集中。

User类:

public class User {
    private int id;
    private String name;
    private int age;
    private char sex;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                " id= " + id +
                " ,name = " + name+
                " ,age = " + age+
                " ,sex = " + sex+
                " }";
    }

这里的User类实际上就是一个JavaBean(avaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。)

封装用集合,不用数组,因为数组大小固定不方便操作,用泛型ArrayList<>实现。

    ResultSet rs = stat.executeQuery("select* from user");
    ArrayList<User> list= new ArrayList<>();
    while(rs.next()){
        User u = new User();
        u.setId(rs.getInt("id"));
        u.setName(rs.getString("name"));
        u.setAge(rs.getInt("age"));
        u.setSex(rs.getString("sex"));
        list.add(u);
    }
    conn.close();
    stat.close();
    rs.close();

(4)处理可能出现的异常

 如上一段代码,如果在ResultSet rs = stat.executeQuery(...);执行完之后出现异常,那么后续代码不会执行,也就是资源不会关闭释放,那么会造成系统负担。因此我们需要在前面加上try /catch /finally的异常捕获机制来避免这种情况的发生。

public class Demo3 {
    @Test
    public void practice01() throws Exception {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection
                    ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=1194006164qwer");
            stat = conn.createStatement();
            rs = stat.executeQuery("select* from user");
        while (rs.next() ){
            System.out.println(rs.getObject(1));
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            conn.close();
            stat.close();
            rs.close();
    }
  }
}

注意:被try包裹后,finally中的3个变量就没有定义了,需要在开头声明成全局变量。

在关闭conn,stat,rs的时候也要注意可能会出现异常,就像关机的时候进程太多出现关机错误,所以也需要加上捕获异常的措施try-catch-finally。当conn,stat,rs不为null时,尝试正常close,如果失败,就手动置空。

完整格式:

public class Demo3 {
    @Test
    public void practice01() throws Exception {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection
                    ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=1194006164qwer");
            stat = conn.createStatement();
            rs = stat.executeQuery("select* from user");
            while (rs.next()) {
                System.out.println(rs.getObject(1));
                System.out.println(rs.getObject(2));
                System.out.println(rs.getObject(3));
                System.out.println(rs.getObject(4));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(conn != null){
                try {
                    conn.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    conn = null;
                }
            }
            if(stat != null){
                try{
                    stat.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    stat.close();
                }
            }
            if(rs != null){
                try{
                    rs.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    rs.close();
                }
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1368630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能分析与调优: Linux 使用 iperf3 进行TCP网络吞吐量测试

目录 一、实验 1.环境 2.TCP网络吞吐量的微观基准测试 二、问题 1.iperf参数有哪些 2.iperf如何二进制安装 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系统 prometheus、node_exporter 192.168.204.18grafana监测…

BI工具调研

1、前言 目前公司使用Tableau作为BI工具&#xff0c;但是感觉不是很好用&#xff0c;且国内市场已经不维护了&#xff0c;所以打算换下BI工具&#xff0c;因此需要针对当前市场开源和商业的BI工具进行调研&#xff0c;看看是买商业的还是用开源的。 基于以下部分开源的做了一个…

深度学习——R-CNN目标检测原理

R-CNN系列算法需要先产生候选区域&#xff0c;再对候选区域做分类和位置坐标的预测&#xff0c;这类算法被称为两阶段目标检测算法。近几年&#xff0c;很多研究人员相继提出一系列单阶段的检测算法&#xff0c;只需要一个网络即可同时产生候选区域并预测出物体的类别和位置坐标…

Jmeter 性能压测 —— 常遇问题与解决技巧!

问题1&#xff1a;如何在大并发测试下&#xff0c;让登录或者后续接口只执行一次&#xff1f; 分析&#xff1a; 这个问题网上的答案其实很多&#xff0c;但是大多不靠谱。 比如推荐使用仅一次控制器&#xff0c;但是仅一次控制器对线程组无效&#xff1b; 比如推荐跨线程组…

OpenAI ChatGPT-4开发笔记2024-05:windows下anaconda中设置visual studio code workspace

这里写自定义目录标题 1 安装anaconda和vscode2 Create an Anaconda Environment3 select Python Interpreter4 Workspace5 Open Workspace With File6 开发文件夹加入workspace7 美化 1 安装anaconda和vscode 标配。 2 Create an Anaconda Environment conda create --name…

Python+Flask+MySQL的图书馆管理系统【附源码,运行简单】

PythonFlaskMySQL的图书馆管理系统【附源码&#xff0c;运行简单】 总览 1、《图书馆管理系统》1.1 方案设计说明书设计目标需求分析工具列表 2、详细设计2.1 登录2.2 注册2.3 程序主页面2.4 图书新增界面2.5 图书信息修改界面2.6 普通用户界面2.7 其他功能贴图 3、下载 总览 …

网站被挂黑链怎么办

网站被挂黑链这种事情总是防不胜防&#xff0c;且不说网站本身的安全防护做的是否到位&#xff0c;但只要被盯上了就难逃厄运。即使是企业机构的网站也难逃被黑的经历&#xff0c;更何况用户苦心经营的网站&#xff0c;因此首先需要正确看待挂黑链这个现象&#xff0c;网站被挂…

Java进击框架:Spring-Web(八)

Java进击框架&#xff1a;Spring-Web&#xff08;八&#xff09; 前言DispatcherServlet拦截器异常视图解析重定向转发 语言环境日志 过滤器带注释的控制器声明映射请求其它注解验证 功能性端点URI Links异步请求CORSHTTP缓存视图技术MVC配置其他Web框架 前言 Spring Web MVC是…

前端学习笔记 6:Pinia

前端学习笔记 6&#xff1a;Pinia Pinia 是 Vue 的一个官方库&#xff0c;用于状态管理。 1.安装 首先创建一个 Vue3 项目&#xff0c;具体方式可以参考这里。 安装 Pinia&#xff1a; npm install pinia创建一个 pinia 实例 (根 store) 并将其传递给应用&#xff1a; im…

金和OA C6 upload_json 任意文件上传漏洞

产品介绍 金和网络是专业信息化服务商,为城市监管部门提供了互联网监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 漏洞概述 金和 OA C6 upload_json接口处存在任意文件上传漏洞&#xff0c;攻击者可以通过构造特殊请求包上…

消息队列-RockMQ-Demo案例拓展输入输出渠道

基于Spirng Cloud Alibaba基础搭建 下面为一个Demo 生产者和消费者是一起的。 父工程pom <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.com…

如何使用TrafficWatch根据PCAP文件监控和分析网络流量

关于TrafficWatch TrafficWatch是一款功能强大的网络数据包嗅探和分析工具&#xff0c;该工具能够帮助我们通过PCAP文件监控和分析目标网络中的网络通信流量。除此之外&#xff0c;该工具还可以为广大研究人员提供针对各种网络协议的内部分析功能&#xff0c;并帮助解决各种网…

初始Linux(部署项目)

Linux学什么 作为一名主学Java的小白&#xff0c;主要学一下三个部分&#xff1a; 1.基础命令 使用图形命令是使用Linux的重要基础。并且有很多好处&#xff0c;如可以节省系统、网络资源&#xff0c;能够批量处理工作等等。 2.系统编程 & 网络编程 由于Java跨平台的特…

【unity小技巧】FPS游戏实现相机的偏移震动、武器射击后退和后坐力效果

最终效果 文章目录 最终效果前言相机偏移震动相机震动脚本换弹节点震动 武器射击后退效果武器后坐力效果完结 前言 关于后坐力之前其实已经分享了一个&#xff1a;FPS游戏后坐力制作思路 但是实现起来比较复杂&#xff0c;如果你只是想要简单的实现&#xff0c;可以看看这个&…

网络通信(12)-C#TCP客户端封装帮助类实例

本文使用Socket在C#语言环境下完成TCP客户端封装帮助类的实例。 实例完成的功能: 客户端与服务器连接,实现实时刷新状态。 客户端接收服务器的数据。 客户端发送给服务器的数据。 客户端实时判定状态,断开连接后自动重连。 客户端与服务器端发送心跳包。 在VS中创建C…

Mysql 恢复误删库表数据

一、前提 1、如果你的数据库有备份文件&#xff0c;自己还原即可。 2、如果没有备份文件&#xff0c;那首先检查下你的 binlog 是否开启。如果未开启&#xff0c;那你就不用往下看了。如果开启了&#xff0c;可以往下看看。 1.1 查看位置 可以通过以下的命令查看是否开启了 bi…

机器学习:手撕 AlphaGo(二)

计算机下围棋的问题描述请见上篇&#xff1a;机器学习&#xff1a;手撕 AlphaGo&#xff08;一&#xff09;-CSDN博客 3. MCTS 算法介绍 MCTS&#xff08;Monte Carlo Tree Search&#xff09; 算法的中文名称叫做蒙特卡洛树搜 索。第一次接触这个算法时&#xff0c;便惊叹于它…

使用echarts制作柱状图、折线图,并且下方带表格

实现效果: 调试地址: https://echarts.apache.org/examples/zh/editor.html?cline-simple 源码: option { title: { left: center, top: 0, text: 2022-05月 制造产量 达成情况(单位: 吨) (图1)\n\n集团目标产量: 106,675吨 集团实际产量: 2,636吨, text…

NVIDIA官网如何下载所有历史版本的驱动,包括上古化石版本?

NVIDIA官网如何下载所有历史版本的驱动&#xff0c;包括上古化石版本&#xff1f; 1.软件环境⚙️2.问题描述&#x1f50d;3.解决方法&#x1f421;4.结果预览&#x1f914; 1.软件环境⚙️ Windows10 教育版64位 GeForce GTX 1060 (Notebooks) Chrome 120.0.6099.199&#xff…

Linux限制用户可用硬盘空间

为了防止某个用户占用大量资源导致其他用户无法正常使用&#xff0c;一般会对单个用户可占用资源进行限制。就磁盘限额&#xff0c;XFS文件系统原生支持目录级别的限制。ext文件系统不支持目录限制&#xff0c;曲线方式是限制用户的总占用空间。 本文介绍使用quota程序限制用户…