MySQL-JDBC

1. JDBC介绍

JDBC(Java Database Connectivity)是 Java 连接数据库的标准接口,它提供了一种与数据库交互的统一方式,使得 Java 程序能够通过标准 API 访问和操作各种关系型数据库。

2. JDBC使用步骤

第0步:导bao

第1步:注册驱动(仅需一次)

第2步:建立链接(Connection)

第3步:创建语句传输对象(Statement)

第4步:运行sql语句

第5步:处理运行结果(ResultSet)

第6步:释放资源

其中,如果是添加,删除,更新操作,可以没有第五步,查询肯定有第五步。

2.0 导包

下载相应版本的jar包(下载地址:Maven Repository: MySQL (mvnrepository.com)

创建Java项目 ------> 在项目下创建lib文件夹------> 将jar包复制到lib文件夹下------> 右键------> Build Path ------> Add to Build Path

2.1 注册驱动

创建java类 JDBC_00 (类名随意)

java 复制代码
        // 1. 注册驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
2.2 建立链接
java 复制代码
// 2. 创建链接对象
// 	  如果出现乱码等问题 可以在url后添加设置编码方式
// 	  url : jdbc:mysql://IP:端口/数据库?useUnicode=true&characterEncoding=utf-8
	  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/_day_02","root", "root");
2.3 创建语句传输对象
java 复制代码
// 3. 创建语句传输对象
		Statement statement = conn.createStatement();
		String sql = "select * from student";
2.4 运行语句
java 复制代码
// 4. 执行sql语句获取结果集
		ResultSet rs = statement.executeQuery(sql);
2.5 处理运行结果
java 复制代码
// 5. 处理结果集数据
		while (rs.next()) {
			// 根据列名获取数据
			int id = rs.getInt("id");
			// 根据列的索引获取数据,不建议使用,
			// int id = rs.getInt(1);
			String name = rs.getString("name");
			int tid = rs.getInt("teacher_id");
			double score = rs.getDouble("score");
			System.out.println(id + "--" + name + "--" + tid + "--" + score);
		}
2.6 释放资源
java 复制代码
		// 6. 关闭资源
		rs.close();
		statement.close();
		conn.close();

3.代码优化

添加try...catch...finally异常处理

java 复制代码
public class JDBC_00 {
	public static void main(String[] args) {
		Connection conn = null;
		Statement statement = null;
		ResultSet rs = null;
		try {
			// 1. 注册驱动
			Class.forName("com.mysql.cj.jdbc.Driver");
			// 2. 创建链接对象
			// 	  如果出现乱码等问题 可以在url后添加东西
			// 	  url : jdbc:mysql://IP:端口/数据库?useUnicode=true&characterEncoding=utf-8
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/_day_02","root", "abc280619SS");
			// 3. 创建语句传输对象
			statement = conn.createStatement();
			String sql = "select * from student";
			// 4. 执行sql语句获取结果集
			rs = statement.executeQuery(sql);
			// 5. 处理结果集数据
			while (rs.next()) {
				// 根据列名获取数据
				int id = rs.getInt("id");
				// 根据列的索引获取数据,不建议使用,
				// int id = rs.getInt(1);
				String name = rs.getString("name");
				int tid = rs.getInt("teacher_id");
				double score = rs.getDouble("score");
				System.out.println(id + "--" + name + "--" + tid + "--" + score);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				// 6. 关闭资源,先打开的后关闭
				rs.close();
				statement.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
		
	}
}

4. DML

Data Manipulation Language : 数据操作语言

涉及的关键字有 : delete,update,insert

和查询的操作几乎一样,就是把第4步和第5步更改一下

java 复制代码
public class JDBC_02 {
	public static void main(String[] args) {
		Connection conn = null;
		Statement statement = null;
		try {
			// 加载驱动
			Class.forName("com.mysql.cj.jdbc.Driver");
			// 创建链接对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/_day_02", "root", "abc280619SS");
			// 创建语句传输对象
			statement = conn.createStatement();
			// 编写sql语句
			// 添加
			String sql = "insert into teacher(id,`name`) values(3,'宋老师')"; 
			// 修改
			sql = "update teacher set `name` = '赵老师' where id = 3";
			// 删除
			sql = "delete from teacher where id = 3";
			// 执行sql语句,增删改使用executeUpdate()方法,查询使用executeQuery()方法
			int count = statement.executeUpdate(sql);
			System.out.println("成功,影响了"+ count + "行。" );
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			// 关闭资源
			try {
				statement.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}	
		}	
	}
}

5. PrepareStatement

添加或删除的时候,尽量使用PrepareStatement,而不是Statement

Statement和PrepareStatement的区别:

Statement 用于执行静态SQL语句,在执行的时候,必须指定一个事先准备好的SQL语句,并且相对不安全,会有SQL注入风险。

PrepareStatement 是预编译的SQL语句对象,SQL语句被预编译i并保存在对象中,被封装的SQL语句中,可以使用动态包含的参数?,在执行的时候可以为?传递参数。

使用PrepareStatement对象执行SQL语句的时候,sql被数据库进行预编译和预解析,然后被放到缓冲区中,每当执行一个PrepareStatement对象时,他就会被解析一次,但不会被再次编译,可以重复使用,减少编译次数,提高数据库性能。并且能够避免SQL注入,相对安全(把' 单引号 使用 \ 转义,避免SQL注入 )。

SQL注入:

SQL注入(SQL Injection)是一种常见的网络安全攻击技术,通过在应用程序中插入恶意的SQL查询语句,来利用程序缺陷或漏洞,从而对数据库进行非法操作或获取敏感信息。

SQL注入攻击通常发生在需要用户输入数据并将其嵌入到 SQL 查询语句中的地方,比如登录表单、搜索框、参数化查询等。攻击者利用这些地方未对用户输入进行有效验证和过滤,直接将恶意的SQL代码注入到查询中,从而执行恶意操作。

java 复制代码
/*
 * PrepareStament
 */
public class JDBC_05 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入用户名:");
		String username = scanner.nextLine();
		System.out.println("请输入密码:");
		String password = scanner.nextLine();
		// login(username, password);
		// updatePwd(username, password);
		loginUser(username, password);
		
	}
	
	// 用户登录方法
	public static boolean login(String username,String password) {
		Connection conn = null;
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			// 加载驱动
			conn = DBUtil.getConnection();
			// 编写sql语句
			String sql = "select count(*) from user where name = ? and password = ?";
			// 创建输出对象
			statement = conn.prepareStatement(sql);
			// 给问号赋值
			statement.setString(1, username);
			statement.setString(2, password);
			// 创建结果集,执行sql语句
			rs = statement.executeQuery();
			rs.next();
			// 返回结果
			int count = rs.getInt(1);
			if (count == 0) {
				System.out.println("登录失败");
				return false;
			}else {
				System.out.println("登录成功");
				return true;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			DBUtil.close(rs);
			DBUtil.close(statement);
			DBUtil.close(conn);
		}
		return false;
	}
	// 修改密码的方法
	public static void updatePwd(String username,String password) {
		Connection conn = null;
		PreparedStatement statement = null;
		try {
			// 加载驱动
			conn = DBUtil.getConnection();
			// 编写sql语句
			String sql = "update user set password = ? where name = ?";
			// 创建输出对象
			statement = conn.prepareStatement(sql);
			// 给问号赋值
			statement.setString(1, password);
			statement.setString(2, username);
			// 执行sql语句
			int count = statement.executeUpdate();
			System.out.println("修改了"+count+"条数据");

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			DBUtil.close(statement);
			DBUtil.close(conn);
		}
	}
	
	
	// 使用statement的登录方法,容易发生sql注入问题
	// 由于Statement在执行sql语句之前进行了字符串的拼接,所以如果username输入类似'or 1=1 or'格式
	// 即使用户不存在也能实现登录
	public static boolean loginUser(String username,String password) {
		Connection conn = null;
		Statement statement = null;
		ResultSet rs = null;
		try {
			// 加载驱动
			conn = DBUtil.getConnection();
			// 创建输出对象
			statement = conn.createStatement();
			// 编写sql语句
			String sql = "select count(*) from user where name = '"+username+"' and password = '"+password+"'";
			// 创建结果集,执行sql语句
			rs = statement.executeQuery(sql);
			rs.next();
			// 返回结果
			int count = rs.getInt(1);
			if (count == 0) {
				System.out.println("登录失败");
				return false;
			}else {
				System.out.println("登录成功");
				return true;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭资源
			DBUtil.close(rs);
			DBUtil.close(statement);
			DBUtil.close(conn);
		}
		return false;
	}		
}

6. 封装工具类

以上代码中创建链接和关闭资源操作都是相同的,因此可以把这一部分逻辑抽离出来,形成独立的类和方法,在实际应用中直接调用相应的类和方法即可。

创建JDBCUtil类,提供获取链接的方法和释放资源的方法

java 复制代码
public class DBUtil {
	
	// 封装方法加载驱动创建链接
	public static Connection getConnection() throws ClassNotFoundException, SQLException{
		Class.forName("com.mysql.cj.jdbc.Driver");
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/_day_02","root", "abc280619SS");
		return conn;
	}
	// 封装方法关闭资源
	public static void close(AutoCloseable obj) {
		if (obj != null) {
			try {
				obj.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

7. Batch 多语句操作

在一次任务中执行多条语句

java 复制代码
public class JDBC_Batch {
	public static void main(String[] args) {
		// testStatement();
		testPrepareStatement();
	}
	
	// 使用Statement添加多条数据
	public static void testStatement() {
		Connection conn = null;
		Statement statement = null;
		try {
			conn = DBUtil.getConnection();
			statement = conn.createStatement();
			
			statement.addBatch("insert into user(name,password,nickname) values('test1',111,'用户1')");
			statement.addBatch("insert into user(name,password,nickname) values('test2',222,'用户2')");
			statement.addBatch("insert into user(name,password,nickname) values('test3',333,'用户3')");
			statement.executeBatch();
			System.out.println("添加成功");
			
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtil.close(statement);
			DBUtil.close(conn);
		}
		
	}
	
	
	// 使用PrepareStatement添加多条数据
	public static void testPrepareStatement() {
		Connection conn = null;
		PreparedStatement preparedStatement = null;
		try {
			conn = DBUtil.getConnection();
			preparedStatement = conn.prepareStatement("insert into user(name,password,nickname) values(?,?,?)");
			preparedStatement.setString(1, "test1");
			preparedStatement.setInt(2, 111);
			preparedStatement.setString(3, "用户1");
			preparedStatement.addBatch();
			
			preparedStatement.setString(1, "test2");
			preparedStatement.setInt(2, 222);
			preparedStatement.setString(3, "用户2");
			preparedStatement.addBatch();
			
			preparedStatement.setString(1, "test3");
			preparedStatement.setInt(2, 333);
			preparedStatement.setString(3, "用户3");
			preparedStatement.addBatch();
			preparedStatement.executeBatch();
			System.out.println("添加成功");
			
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		} finally {
			DBUtil.close(preparedStatement);
			DBUtil.close(conn);
		}
		
	}
}
相关推荐
小猿姐19 小时前
实测对比:哪款开源 Kubernetes MySQL Operator 最值得用?(2026 深度评测)
数据库·mysql·云原生
一灯架构21 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
倔强的石头_21 小时前
从 “存得下” 到 “算得快”:工业物联网需要新一代时序数据平台
数据库
Y4090011 天前
【多线程】线程安全(1)
java·开发语言·jvm
TDengine (老段)1 天前
TDengine IDMP 可视化 —— 分享
大数据·数据库·人工智能·时序数据库·tdengine·涛思数据·时序数据
布局呆星1 天前
SpringBoot 基础入门
java·spring boot·spring
风吹迎面入袖凉1 天前
【Redis】Redisson的可重入锁原理
java·redis
GottdesKrieges1 天前
OceanBase数据库备份配置
数据库·oceanbase
w6100104661 天前
cka-2026-ConfigMap
java·linux·cka·configmap