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. Kubernetes 基础资料

    概述 这篇文章用来记录Kubernetes 的基础资料,整体以最新官方文档为准. 因为k8s整体比较偏运维,作为研发可先大致了解其概念及初级使用方式,后面重点学习点会放在service mesh is ...

  2. 自定义cursor鼠标 图片

    1.CSS3自定义鼠标样式 最近想要使用自定义鼠标样式,看了cursor的样式不好看,就想到cursor属性能不能自定义图片,翻看了下CSS3文档,发现是可以的 格式为:cursor:url('图片u ...

  3. [工具推荐]005.Axure RP Pro 7.0模拟C#TAB控件

    有一次,主管安排我写一个项目的原型,但是项目中涉及到了Tab控件,在Axure中的控件中找了一番,没有找着Tab控件.那么我们只能换种法子来实现它了,我们用到了Dynamic Panel来模拟. 1. ...

  4. idea 开发 webpack项目时,只要已加入SVN 版本控制 一直 updating 问题解决

    场景描述,这是一个困扰我很久的一个问题,一直百度,都解决不了,今天自己通过设置终于解决了,慢慢的都是辛酸泪,赶快写个笔记记录一下. 对于idea 开发 vue-cli+webpack 项目,idea  ...

  5. 【图机器学习】cs224w Lecture 15 - 网络演变

    目录 Macroscopic Forest Fire Model Microscopic Temporal Network Temporal PageRank Mesoscopic 转自本人:http ...

  6. Entity FrameWork操作数据库完成登陆、列表显示+验证码

    登陆页面 登陆页面的页面结构比较简单,没有写样式. image标签的作用是用来显示验证码. 一般处理程序代码展示 using System; using System.Collections.Gene ...

  7. (Java实现) 洛谷 P1036 选数

    输入输出格式 输入格式: 键盘输入,格式为: n,k x1,x2,x3-xn 输出格式: 屏幕输出,格式为: 11个整数(满足条件的种数). 输入输出样例 输入样例#1: 4 3 3 7 12 19 ...

  8. Java实现 LeetCode 714 买卖股票的最佳时机含手续费(动态规划 || 迭代法)

    714. 买卖股票的最佳时机含手续费 给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 :非负整数 fee 代表了交易股票的手续费用. 你可以无限次地完成交易,但是你每次交 ...

  9. (Java实现) 工作分配问题

    工作分配问题 时间限制: 1 Sec 内存限制: 128 MB [提交][状态][讨论版] 题目描述 设有n件工作分配给n个人.为第i个人分配工作j所需的费用为c[i][j] .试设计一个算法,计算最 ...

  10. Java实现 蓝桥杯 算法提高 01背包

    算法提高 01背包 时间限制:1.0s 内存限制:256.0MB 问题描述 给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个. 输入 ...