JDBC——什么是JDBC一文中我们已经介绍了JDBC的基本原理。

这篇文章我们聊聊如何使用JDBC连接MySQL数据库。

一、基本操作

首先我们需要一个数据库和一张表:

CREATE DATABASE `test`;
USE `test`;
CREATE TABLE `user` (
`id` INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL,
`password` VARCHAR(20) NOT NULL
);

然后我们导入驱动jar包mysql-connector-java-8.0.20.jar 导入jar包或者使用maven依赖

至于如何导入jar包或者使用maven依赖,这里不做赘述。


基本步骤:

  1. 注册驱动
  2. 获取连接对象
  3. 创建SQL语句
  4. 创建执行SQL语句的Statement对象
  5. 执行SQL语句
  6. 释放资源

1. 增、删、改

public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false", "root", "123456");
//创建SQL语句
String sql = "insert into user values (null, '行小观', '1234')";
//创建Statement对象
stmt = conn.createStatement();
//执行SQL语句
int i = stmt.executeUpdate(sql);
System.out.println(i);
} 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();
}
}
}
}

DML语句的代码相同

2. 查询

public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false", "root", "123456");
//创建SQL语句
String username = "行小观";
String password = "1234";
String sql = "select * from user where username = '" + username + "' and password = '" + password + "'";//拼接字符串
//创建Statement对象
stmt = conn.createStatement();
//执行SQL语句
rs = stmt.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
float money = rs.getFloat("money");
System.out.println(id + "--" + name + "--" + money);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException 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 {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

二、类的解释

1. DriverManager

(1) 通过DriverManager注册驱动

Class.forName("com.mysql.cj.jdbc.Driver")将Driver类加载进内存。

我们翻看Driver类的源码发现静态代码块:

static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}

该静态代码块随着类被加载而执行,一旦执行,便通过DriverManager.registerDriver(new Driver())注册驱动。

(2) 通过DriverManager获取Connection对象

DriverManager.getConnection(url, username, password)

我们只需提供三个参数:数据库的url,用户名,密码。

注意:url中需要加时区。

2. Connection

conn.createStatement()

通过Connection对象创建Statement对象

3. Statement

该对象能够执行静态SQL语句并返回执行结果。

4. ResultSet

表示数据库结果集的数据表,通常由执行查询数据库的语句生成。

可以使用next()方法遍历结果集

三、SQL注入

上面的例子中有一个很严重的问题就是我们写的SQL语句都是静态的,换句话说,就是SQL语句是使用字符串拼接起来的。比如说:

String username = "行小观";
String password = "1234";
String sql = "select * from user where username = '" + username + "' and password = '" + password + "'";

我们将变量代入后的效果是:

select * from user where username = '行小观' and password = '1234'

这样执行是没问题的。

但是现在情况变了:

String username = "行小观";
String password = "1' or '1' = '1";

我们将变量代入后的效果是:

select * from user where username = '行小观' and password = '1' or '1' = '1'

因为or '1'='1'的原因,导致SQL语句的where子句为true,等价于

select * from user

所以会将整张表给查询出来。

以上便是SQL注入。

四、使用PreparedStatement防止SQL注入

使用Statement对象执行静态SQL语句,如果执行了特殊构造的语句,会导致SQL注入,出现安全漏洞。

使用PreparedStatement对象能避免上述问题。

PreparedStatement对象是预编译的SQL语句的对象,继承自Statement。

什么是预编译的SQL语句?

静态SQL语句

String sql = "select * from user where username = '" + username + "' and password = ' " + password + "'";

改为预编译的SQL语句:

String sql = "select * from user where username = ? and password = ? ";

编写SQL语句时,不使用字符串进行拼接,而是使用问号?占位符代替变量。

使用JDBC的步骤有所变化:

  1. 注册驱动
  2. 获取连接对象
  3. 创建SQL语句
  4. 创建执行SQL语句的PreparedStatement对象
  5. 给?赋值
  6. 执行SQL语句
  7. 释放资源
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接对象
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false", "root", "123456");
//创建SQL语句
String username = "行小观";
String password = "1234";
String sql = "select * from user where username = ? and password = ?";
//创建PreparedStatement对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1, username);
pstmt.setString(2, password);
//执行SQL语句
rs = pstmt.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
String unm = rs.getString("username");
String pwd = rs.getString("password");
System.out.println(id + "--"+ unm + "--" + pwd);
} } catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException 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 (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

五、进一步封装

上面的例子,有几点缺点:

  1. 有大量重复代码。
  2. 驱动类的全限定类名、数据库的url、username、password写在代码中,如果更改这些值还需要修改代码。

首先我们将Driver的全限定类名、数据库的信息写在配置文件database.properties中,通过读取配置文件获取这些值,当我们需要更改信息时,不用修改代码,直接在配置文件中修改信息即可。

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false
username=root
password=123456

然后我们将注册驱动类、获取连接、释放资源这些操作封装到工具类JdbcUtil中。

public class JdbcUtil {
private static String driver;
private static String url;
private static String username;
private static String password; static {
try {
Properties pro = new Properties();
ClassLoader classLoader = JdbcUtil.class.getClassLoader();
URL resourceURL = classLoader.getResource("database.properties");
String path = resourceURL.getPath();
pro.load(new FileReader(path));
driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} public static Connection getConnection() {
try {
return DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
} public static void close(Statement stmt, Connection conn) {
if (stmt != null) {//避免空指针异常
try {
stmt.close();//释放资源
} catch (SQLException e) {
e.printStackTrace();
}
} if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} public static void close(ResultSet rs, Statement stmt, Connection conn) {
close(stmt, conn); if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} }

我们再使用JDBC时,就可以使用工具类简化代码了。

public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
//获取连接
conn = JdbcUtil.getConnection();
//创建SQL语句
String username = "行小观";
String password = "1234";
String sql = "select * from user where username = ? and password = ?";
//创建PreparedStatement对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setString(1, username);
pstmt.setString(2, password);
//执行SQL语句
rs = pstmt.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
String unm = rs.getString("username");
String pwd = rs.getString("password");
System.out.println(id + "--"+ unm + "--" + pwd);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.close(rs, pstmt, conn);
}
}

如有错误,还请指正


文章首发于公众号『行人观学』。


JDBC——使用JDBC连接MySQL数据库的更多相关文章

  1. 【JDBC】java连接MySQL数据库步骤

    java连接数据库步骤 1. 加载驱动 Class.forName("com.mysql.java.Driver"); 或: registerDriver(new com.mysq ...

  2. jdbc java远程连接mysql数据库服务器

    首先,需要注意以下几点: 1.手机需要获得可以访问网络的权限: 2.导入的jdbc驱动的版本需要与mysql服务器的版本相近: 3.mysql默认的访客是只允许本机(localhost),不允许其他主 ...

  3. java 通过jdbc连接MySQL数据库

    先了解下JDBC的常用接口 1.驱动程序接口Driver 每种数据库的驱动程序都应该提供一个实现java.sql.Driver接口的类,简称Driver类.通常情况下,通过java.lang.Clas ...

  4. JDBC连接MySQL数据库代码模板

    下面这个例子是最简单的JDBC连接MySQL数据库的例子. 一般步骤: 1.注册驱动: 2.建立连接: 3.创建语句: 4.处理结果: 5.释放资源. 注意: 1.软件开发环境:MyEclipse 8 ...

  5. java jdbc 连接mysql数据库 实现增删改查

    好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...

  6. Ubuntu jsp平台使用JDBC来连接MySQL数据库

    Ubuntu 7.04 搭建Ubuntu jsp平台开发环境MySQL+tomcat+apache+j2sdk1.6在所有安装开始前先在Terminal中输入 rpm -q -a查看是否安装过rpm ...

  7. Java使用JDBC连接MySQL数据库

    1.引用 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写 ...

  8. Crystal Reports 2008(水晶报表) JDBC连接mysql数据库

    在本blog中,主要介绍的是Crystal Reports 2008使用JDBC连接mysql数据库. 在连接之间,首先要确认你电脑上面都安装了mysql数据库. 其次,就是jdbc连接数据时候所使用 ...

  9. JDBC连接MySQL数据库及演示样例

    JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术. 一.JDBC基础知识         JDBC(Java Data Base Connectivity,java数据库连接)是一种用 ...

  10. JDBC连接MySQL数据库及示例

      JDBC是Sun公司制定的一个可以用Java语言连接数据库的技术. 一.JDBC基础知识         JDBC(Java Data Base Connectivity,java数据库连接)是一 ...

随机推荐

  1. idea打印中文乱码

    一.问题情况: IntelliJ IDEA 控制台输出中文乱码部分如图所示: 二.解决方法: 1.打开tomcat配置页面,Edit Configurations. 2.选择项目部署的tomcat,在 ...

  2. 重磅!阿里P8费心整理Netty实战+指南+项目白皮书PDF,总计1.08G

    前言 Netty是一款用于快速开发高性能的网络应用程序的Java框架.它封装了网络编程的复杂性,使网络编程和Web技术的最新进展能够被比以往更广泛的开发人员接触到. Netty不只是一个接口和类的集合 ...

  3. [SD心灵鸡汤]001.每月一则 - 2015.05

    1.既然我的父母不能带给我荣耀,那我要做的就只是带给我的子女荣耀,而不是无聊的嫉妒眼红别人. 2.就人生游戏讲,男人是女人的玩物,女人是魔鬼的玩物.就爱情而言,女人是专业的,男人是业余的. 3.快乐使 ...

  4. 选择器&隔行换色

    选择器的使用理解为:执行jQuery核心函数,传入选择器的字符串    $( ... ) 基本选择器 <!DOCTYPE html> <html> <head> & ...

  5. centos7 docker安装mongo遇到的问题

    问题一 docker search error 描述:使用docker 搜索镜像时出现错误,错误信息如下: [root@ ~]# docker search mongo Error response ...

  6. burpsuite 关于部分https抓包失败原因

    没导入证书 burpsuite生成证书 der格式,名字随便取,一路next  firefox浏览器导入 导入,勾选信任证书ok,重启浏览器  还有你要勾选这里,确保所有流量都走你的代理 ps:遇到浏 ...

  7. 以太坊智能合约开发框架Truffle

    前言 部署智能合约有多种方式,命令行的浏览器的渠道都有,但往往跟我们程序员的风格不太相符,因为我们习惯了在IDE里写了代码然后打包运行看效果. 虽然现在IDE中已经存在了Solidity插件,可以编写 ...

  8. Java实现 LeetCode 733 图像渲染(DFS)

    733. 图像渲染 有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间. 给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的 ...

  9. Java实现 蓝桥杯VIP 算法训练 数的统计

    问题描述 在一个有限的正整数序列中,有些数会多次重复出现在这个序列中. 如序列:3,1,2,1,5,1,2.其中1就出现3次,2出现2次,3出现1 次,5出现1次. 你的任务是对于给定的正整数序列,从 ...

  10. Java实现 神犇的悲惨一生

    [问题描述] 传说中有位神犇,因其一贯低调,所以人们连他活了多少岁都不知道. 好在XXXX文献上有段关于他生平细节的文字:神犇一生中, 幼年占了1/6,又过了1/12的青春期,又谈了1/6的恋爱后结婚 ...