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);
		}
		
	}
}
相关推荐
陈大爷(有低保)23 分钟前
UDP Socket聊天室(Java)
java·网络协议·udp
阿华的代码王国34 分钟前
MySQL ------- 索引(B树B+树)
数据库·mysql
kinlon.liu37 分钟前
零信任安全架构--持续验证
java·安全·安全架构·mfa·持续验证
王哲晓1 小时前
Linux通过yum安装Docker
java·linux·docker
Hello.Reader1 小时前
StarRocks实时分析数据库的基础与应用
大数据·数据库
java6666688881 小时前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言
Violet永存1 小时前
源码分析:LinkedList
java·开发语言
执键行天涯1 小时前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
liupenglove1 小时前
golang操作mysql利器-gorm
mysql·golang
yanglamei19621 小时前
基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue
前端·数据库·flask