Java入门系列-26-JDBC

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

认识 JDBC

JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库。

Sun 公司提供了 JDBC API ,供程序员调用接口和类,集成在 java.sqljavax.sql 包中。

Sun 公司还提供了 DriverManager 类用来管理各种不同的JDBC驱动。

不同数据库厂商提供各自的JDBC驱动,所以我们想要连接数据库除了要了解 JDBC API 还需要下载各数据库厂商的驱动 jar 包。

JDBC API

JDBC API主要用于与数据库建立连接、执行SQL语句、处理结果,其中核心类和接口如下:

  • DriverManager:依据数据库的不同,管理JDBC驱动
  • Connection:负责连接数据库并担任传送数据的任务
  • Statement:由 Connection 产生、负责执行SQL语句
  • ResultSet:负责保存 Statement 执行后所产生的查询结果

JDBC 编码模板

1、与数据库建立连接并获取连接

Connection connection=DriverManager.getConnection(URL,数据库用户名,密码);

2、发送SQL语句,得到执行结果

Statement stmt=connection.createStatement();
ResultSet rs=stmt.executeQuery(SQL语句);

3、处理返回结果

while(rs.next()){
    int a=rs.getInt("a");
    String b=rs.getString("b");
    Date d=rs.getDate("d");
    ……
}

4、释放资源

rs.close();
stmt.close();
connection.close();

使用 JDBC 连接到 MySQL 数据库

本例适合已经会使用 MySQL 数据库的同学,首先我们下载 JDBC 的驱动 jar 包。这个网址提供了 MySQL 各种语言连接数据库的驱动 https://www.mysql.com/products/connector/,MySQL Connector / J 8.0与从MySQL 5.5开始的所有MySQL版本兼容。
8.0下载地址
下载完成后解压,后将jar添加依赖到项目中。

连接到MySQL数据库

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

public class DemoConnectMySQL {
    public static void main(String[] args) {
        //连接MySQL的URL
        String url="jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        //MySQL数据库用户名
        String user="root";
        //MySQL数据库的密码
        String password="1234";
        Connection connection=null;
        try {
            connection=DriverManager.getConnection(url, user, password);
            System.out.println("连接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
                System.out.println("连接关闭");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

url指定数据库的连接字符串,格式为:

jdbc:数据库://ip或域名:端口号?参数&参数……
这里的参数 useUnicode=true 使用Unicode字符,characterEncoding=utf8 设置编码防止中文乱码,serverTimezone=UTC 设置时区,useSSL=false 不使用SSL

jdbc4.0不需要加载驱动

PreparedStatement 增删改

PreparedStatement 继承了 Statement 接口,表示预编译的 SQL 语句对象,SQL 语句被预编译并存储在 PreparedStatement 对象中,可以使用此对象多次高效地执行该语句。(还避免了 SQL 注入的隐患)

先准备好数据库 books

表 book

字段 类型 属性
id 整数 主键,自增
bName 字符串 非空
price 小数 非空

脚本也准备好了

#创建数据库
CREATE DATABASE books;
USE books;
#创建表
CREATE TABLE book ( 
    id INT primary key    auto_increment, 
    bName VARCHAR ( 255 ) NOT NULL, 
    price FLOAT NOT NULL 
);

PreparedStatement添加数据

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

public class TestInsert {

    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement pstmt=null;
        String url="jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        String user="root";
        String password="1234";
        try {
            connection=DriverManager.getConnection(url,user,password);
            //sql语句
            String sql="insert into book(bName,price) values (?,?)";
            pstmt=connection.prepareStatement(sql);
            //传入参数
            pstmt.setString(1, "《java入门到改行》");
            pstmt.setFloat(2, 11.11f);
            int result=pstmt.executeUpdate();
            System.out.println("受影响行数:"+result);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (pstmt!=null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

说明:

1、连接字符串要修改数据库名字为 books

String url="jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";

2、插入数据库的数据不能拼接而是要用 ? 代替

String sql="insert into book(bName,price) values (?,?)";

3、? 代替的参数要通过 set类型(位置,值) 传入

pstmt.setString(1, "《java入门到改行》");
pstmt.setFloat(2, 11.11f);

pstmt.setXxx()的位置从 1 开始!

4、增删改的SQL语句都使用这个方法,返回受影响行数

int result=pstmt.executeUpdate();

删除数据

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

public class TestDelete {

    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement pstmt=null;
        String url="jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        String user="root";
        String password="1234";
        try {
            connection=DriverManager.getConnection(url,user,password);
            //sql语句
            String sql="delete from book where id=?";
            pstmt=connection.prepareStatement(sql);
            //传入参数 要删除id
            pstmt.setInt(1, 1);
            int result=pstmt.executeUpdate();
            System.out.println("受影响行数:"+result);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (pstmt!=null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

修改数据

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

public class TestUpdate {

    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement pstmt=null;
        String url="jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        String user="root";
        String password="1234";
        try {
            connection=DriverManager.getConnection(url,user,password);
            //sql语句
            String sql="update book set bName=?,price=? where id=?";
            pstmt=connection.prepareStatement(sql);
            //传入参数 要删除id
            pstmt.setString(1, "《MySQL从删库到跑路》");
            pstmt.setFloat(2, 16.66f);
            pstmt.setInt(3, 2);
            int result=pstmt.executeUpdate();
            System.out.println("受影响行数:"+result);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if (pstmt!=null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

增、删、改操作的写法都一样,都调用 executeUpdate() 方法返回一个受影响行数,唯一不同的 SQL语句。

PreparedStatement 查询数据

查询数据需要用到 ResultSet 类保存返回的结果集,我们获取数据要操作 ResultSet 获取。

ResultSet 常用方法

方法名 说明
boolean next() 将游标从当前位置向下移动一行
void close() 关闭 ResultSet 对象
int getInt(int colIndex) 以int形式获取结果集当前行指定列号值
int getInt(String colLabel) 以int形式获取结果集当前行指定列名值
float getFloat(String colLabel) 以float形式获取结果集当前行指定列名值
String getString(String colLabel) 以 String 形式获取结果集当前行指定列名值
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {

    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement pstmt=null;
        ResultSet rs=null;
        String url="jdbc:mysql://localhost:3306/books?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false";
        String user="root";
        String password="1234";
        try {
            connection=DriverManager.getConnection(url,user,password);
            //sql语句
            String sql="select bName,price,id from book where id=?";
            pstmt=connection.prepareStatement(sql);
            //传入查询条件
            pstmt.setInt(1, 2);
            rs=pstmt.executeQuery();
            while(rs.next()) {
                //通过列名获取列的值
                int id=rs.getInt("id");
                //通过位置获取列的值
                String bName=rs.getString(1);
                float price=rs.getFloat("price");
                System.out.println(id+" "+bName+" "+price);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(rs!=null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (pstmt!=null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

关闭对象时注意关闭的顺序,后使用的先关闭:rs.close()->pstmt.close()->connection.close()

ResultSet 对象存在一个光标,光标所指行为当前行。想要获取列的数据需要先指向一行,所以要先指定 next() 方法用于指向一行,如果没有数据next()方法返回false,有数据返回true。

使用 getXxx() 方法获取列的数据时建议写列名,这样好识别

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
39 3
|
5天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
11天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
17天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
55 5
|
14天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
29 1
|
20天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3
|
22天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
24天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第19天】本文介绍了Java编程中重要的数据结构——Map,通过问答形式讲解了Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的使用和性能优化技巧,适合初学者和进阶者学习。
41 4
|
23天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
19 1
|
24天前
|
SQL IDE Java
入门Cloud Toolkit:简化你的Java应用开发与部署流程
【10月更文挑战第19天】作为一名长期从事Java开发的程序员,我一直致力于寻找能够简化日常开发工作的工具。在众多工具中,阿里巴巴推出的Cloud Toolkit引起了我的注意。这款免费的插件旨在帮助开发者更轻松地进行开发、测试及部署工作,尤其是在与云服务交互时表现尤为出色。本文将从个人的角度出发,介绍Cloud Toolkit的基本功能及其使用技巧,希望能帮助初学者快速上手这款实用工具。
18 1