MySQL-JDBC

news2024/10/2 14:22:19

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 (类名随意)

        // 1. 注册驱动
		Class.forName("com.mysql.cj.jdbc.Driver");
          2.2 建立链接
// 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 创建语句传输对象
// 3. 创建语句传输对象
		Statement statement = conn.createStatement();
		String sql = "select * from student";
        2.4 运行语句
// 4. 执行sql语句获取结果集
		ResultSet rs = statement.executeQuery(sql);
        2.5 处理运行结果
// 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 释放资源
		// 6. 关闭资源
		rs.close();
		statement.close();
		conn.close();

3.代码优化

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

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步更改一下

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代码注入到查询中,从而执行恶意操作。

        


/*
 * 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类,提供获取链接的方法和释放资源的方法

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 多语句操作

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

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);
		}
		
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1471945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TensorRT推理时,如何比对中间层的误差

TensorRT推理时,如何比对中间层的误差 有二种方案第二种方案的实现1.运行环境的搭建2.实现代码(compare_trt_onnxrt.py)3.运行4.输出 本文演示了TensorRT推理时,如何比对中间层的误差。 在做TensorRT推理加速时,可能会遇到精度问题,希望定位到是哪一个节点引起的误差,还是累计误…

10.vue学习笔记(组件数据传递-props回调函数子传父+透传Attributes+插槽slot)

文章目录 1.组件数据传递2.透传Attributes(了解)禁用Attributes继承 3.插槽slot3.1.插槽作用域3.2.默认内容3.3.具名插槽3.4.插槽中的数据传递3.5.具名插槽传递数据 1.组件数据传递 我们之前讲解过了组件之间的数据传递,props 和 自定义事件…

【IDEA】java 项目启动偶现Kotlin 版本问题 error:Kotlin:module was

一、问题描述: error:Kotlin:module was compiled with an incompatible version of kotlin the binary version of its metadata is二、问题原因: jar包版本冲突 三、解决方式: 1、Rebuild Project(推荐☆) 重新构…

小迪安全30WEB 攻防-通用漏洞SQL 注入CTF二次堆叠DNS 带外

#知识点: 1、数据库堆叠注入 根据数据库类型决定是否支持多条语句执行 2、数据库二次注入 应用功能逻辑涉及上导致的先写入后组合的注入 3、数据库 Dnslog 注入 解决不回显(反向连接),SQL 注入,命令执行,SSRF 等 4、黑盒模式分析以上 二次注入&…

2024.2.21 模拟实现 RabbitMQ —— 实现转发规则

目录 需求分析 直接交换机(Direct ) 主题交换机(Topic ) 扇出交换机(Fanout ) Topic 交换机转发规则 routingKey 组成 bindingKey 组成 匹配规则 情况一 情况二 情况三 实现 Router 类 校验 b…

【AIGC大模型】跑通wonder3D (windows)

论文链接:https://arxiv.org/pdf/2310.15008.pdf windows10系统 显卡:NVIDIA rtx 2060 一、安装anaconda 二、安装CUDA 11.7 (CUDA Toolkit 11.7 Downloads | NVIDIA Developer) 和 cudnn 8.9.7(cuDNN Archive | NVIDIA Developer)库 CUDA选择自定…

【Android】坐标系

Android 系统中有两种坐标系,分别为 Android 坐标系和 View 坐标系。了解这两种坐标系能够帮助我们实现 View 的各种操作,比如我们要实现 View 的滑动,你连这个 View 的位置都不知道,那如何去操作呢? 一、Android 坐标…

【Spring Cloud】高并发带来的问题及常见容错方案

文章目录 高并发带来的问题编写代码修改配置压力测试修改配置,并启动软件添加线程组配置线程并发数添加Http取样配置取样,并启动测试访问message方法观察效果 服务雪崩效应常见容错方案常见的容错思路常见的容错组件 总结 欢迎来到阿Q社区 https://bbs.c…

《极简C++学习专栏》之结束语

朋友们,经过这么长的时间,《极简C学习专栏》的文章创作就要结束了,感谢你们一路陪伴! 也希望你们能支持我接下来的其他专栏的创作! 专栏的初衷 《极简C学习》专栏的初衷源自于我个人的学习笔记,记录下自己…

【刷题】牛客 JZ64 求1+2+3+...+n

刷题 题目描述思路一 (暴力递归版)思路二 (妙用内存版)思路三 (快速乘法版)思路四 (构造巧解版)Thanks♪(・ω・)ノ谢谢阅读!&#xff01…

Java 面向对象进阶 18 JDK8、9开始新增的方法;接口的应用;适配器设计模式;内部类(黑马)

一、JDK8开始新增的方法 默认方法不是抽象方法,所以不强制被重写: 但是如果被重写,就要去掉default关键字: public可以省略,但是default不可以省略: public是灰色的,代表可以省略 但是default是…

怎么把pdf转换成word?

怎么把pdf转换成word?Pdf和word在电脑上的使用非常广泛,pdf和word分别是由 Adobe和Microsoft 分别开发的电脑文件格式。PDF 文件可以在不同操作系统和设备上保持一致的显示效果,无论是在 Windows、Mac 还是移动设备上查看,都能保持…

使用Docker部署MinIO并结合内网穿透实现远程访问本地数据

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器,可以在各种环境中运行,例如本地、Docker容器、Kubernetes集群等。它兼…

《绝地求生》提示msvcp140.dll丢失如何修复?分享5种靠谱的解决方法

在玩绝地求生(PUBG)游戏过程中,如果遇到系统弹出“提示请重新安装软件msvcp140.dll”的信息,这究竟是什么原因导致的呢?msvcp140.dll这个文件是Microsoft Visual C Redistributable Package的一部分,是许多…

服务器系统安全,10招教你维护服务器的安全

网络逐渐成为了我们生活中一部分。有人说,断WIFI是最厉害的一种惩罚手段,但是其实不然,最狠的莫过于网站的服务器遭受攻击,直接访问不了网页了,这时候就算有wifi我们也无能为力。服务器系统安全一直是管理者最关注的事…

这个元宵节,被云开发者安排了

元宵节快乐,同学们!今天吃的汤圆都是什么馅儿的? 都说过了元宵,这个年才算是正式过完,2024年就算是正式开启。学堂君这里也准备了一份专属于开发者的小礼物,作为一点心意。 欢迎私信,发送暗号…

Ubuntu 某软件导致卡机如何 kill 掉进程

输入 top 查看现在系统的进程,记下该进程第一列的 pid 编号 kill [pid] 可以杀掉此进程 参考: Ubuntu下查看进程pid及结束无响应程序_终止3分钟内无响应的所有pid-CSDN博客

【OneAPI】节假日查询API

OneAPI新接口发布:节假日查询API 可查询指定月份、年份法定节假日及调休情况。 API地址:https://oneapi.coderbox.cn/openapi/public/holiday 请求参数 URL参数 参数名类型必须含义说明datestring否要查询的日期可按年或月查询,支持前缀…

Coursera吴恩达机器学习专项课程02:Advanced Learning Algorithms 笔记 Week01

Advanced Learning Algorithms Week 01 笔者在2022年7月份取得这门课的证书,现在(2024年2月25日)才想起来将笔记发布到博客上。 Website: https://www.coursera.org/learn/advanced-learning-algorithms?specializationmachine-learning-in…

如何使用Lychee+cpolar搭建本地私人图床并实现远程访问存储图片

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 图床作为图片集中存放的服务网站,可以看做是云存储的一部分,既可…