(jdbc 连接,操作数据库)2020.11.18

JDBC简介

JDBC定义

概述:JDBC通俗来讲就是使用java代码去操作数据库。
 JDBC本质上是一个接口、接口中封装了操作数据库的方法、具体实现接口的类被我们成为数据库驱动类、
 也就意味着我们将来要操作mysql数据库需要导入mysql的驱动包、操作oracle数据库需要导入oracle驱动包
 驱动:指的就是实现jdbc接口规范实现类
在这里插入图片描述

JDBC常见接口和类

接口(类)名描述作用
DriverManager驱动管理类注册驱动 明确要访问数据类型
Conncation连接对象与mysql 建立起通讯的桥梁
Statemnt可执行对象创建推送sql到数据库服务器中载体
ResultSet结果集对象执行sql数据库返回结果内容

JDBC快速入门

下载JDBC驱动

本门课我们以MySQL数据库为例,所以我们需要下载MySQL的JDBC驱动程序。
下载地址:https://dev.mysql.com/downloads/connector/j/5.1.html
目前常用的MySQL驱动有5.* 版本和 8.*版本,二者在使用时配置上略有不同,大家可以选择其中任意一个版本使用。

JDBC连接数据步骤

准备工作:创建项目并导入jar包

(1)在项目的根目录下创建一个Folder,通常用lib命名,将解压后的jar文件复制到该文件夹下。
(2)在Java项目中导入jar包,即构建jar文件路径。
方法一:
在这里插入图片描述
方法二:
在这里插入图片描述

编写代码

步骤:
 1、注册驱动
 2、获取连接
 3、获取可执行对象
 4、执行并获取结果
 5、关闭资源
 完整案例代码:

/*
 * jdbc的入门案例
 *    向user表中添加一条数据
 *     全限定类名 = 包名+类名
 */
public class Jdbc_Demo01 {
	
	public static void main(String[] args) throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/day08","root","root");
		//3、获取可执行对象
		Statement st = con.createStatement();
		//4、执行并得到结果
		String sql ="insert into user values(1,'张三',18)";
		int row = st.executeUpdate(sql);
		if(row>0) {
			System.out.println("插入成功");
		}else {
			System.out.println("插入失败");
		}
		//5、关闭资源
		st.close();
		con.close();
	}
}

JDBC的详解

注册驱动

Class.forName(“com.mysql.jdbc.Drvier”) 5.x 相当于明确了要连接数据库的类型
Class.forName(“com.mysql.cj.jdbc.Drvier”) 8.x

创建连接对象

Connaction con =DriverManger.getConnation(url,user,password);
1.参数url:要连接的数据库的地址
 语法 协议:子协议://ip+端口/数据库名称
   jdbc:mysql://localhost:3306/day08
   
 1.如果我们连接的本地数据库、并且端口号是默认的3306那么 ip+端口可以省略
   jdbc:mysql:///day08
 2.假如你用驱动包是8.x版本 我们需要加入一段内容
  jdbc:mysql:///day08?serverTimezone=utc
           serverTimezone:utc 表示我们使用世界标准日期(以美国时间为准)
 3.如果将来你使用jdbc插入数据数据出现乱码的时候这个时候你可以尝试这么设置
  jdbc:mysql:///day08?unicode=true&characterEncoding=utf-8
  
2.参数user:访问数据库的用户名
3.参数password:访问数据的密码
4.建立与mysql数据库通话的桥梁

创建SQL编译器

Statement st =con.createStatement() 创建推送sql到数据库服务器的载体

执行SQL语句并返回结果

增删改 int executeUpdate(sql);   返回值表示受影响的行数
查询 ResultSet executeQuery(sql);  返回值查询到的内容
ResultSet中api
next() 判断当前行是否有数据如果有返回true,如果没有返回false
    如果返回true我们就可以获取当前行的数据
get类型(索引) 通过索引指定列的值
get类型(列名) 通过列名称获取指定名称上列的值

释放资源

增删改关闭2个
  可执行对象 statement.close()
  连接对象 connaction.close()
查询关闭3个
  结果集 ResultSet.close()
  可执行对象 statement.close()
  连接对象 connaction.close()

查询案例

在这里插入图片描述

单元测试

概述:单元测试指的是我们可以在不依靠main方法的程序单独让某个方法进行直接运行
@Test 测试方法
 注意事项
  1、要求方法没有返回值
  2、要求方法没有参数
  3、要求方法不能使用静态修饰
  4、要求方法权限修饰符必须是public
@before 前置方法 在测试方法执行前先执行的方法
@after 后置方法 在测试方法执行后再执行的方法
代码示例
在这里插入图片描述

JDBC实现CRUD操作

package com.offcn.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
/*
 * JDBC  增删改查
 */
public class Jdbc_Demo03 {
	/*
	 * 添加数据
	 */
	@Test
	public void insertUser() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		Statement st = con.createStatement();
		//4、执行并获取结果
		String sql ="insert into user values(4,'白百何',18)";
		int row = st.executeUpdate(sql);
		if(row>0) {
			System.out.println("插入成功");
		}else {
			System.out.println("插入失败");
		}
		//5、关闭资源
		st.close();
		con.close();
	}
	/*
	 * 修改数据
	 */
	@Test
	public void updateUser() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接  ctrl+1
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		Statement st = con.createStatement();
		//4、执行并获取结果
		String sql="update user set name='马保国',age=60 where uid =4";
		int row = st.executeUpdate(sql);
		if(row>0) {
			System.out.println("更新成功");
		}else {
			System.out.println("更新失败");
		}
		//5、关闭资源
		st.close();
		con.close();
	}
	
	/*
	 * 删除数据
	 */
	@Test
	public void deleteUser() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		Statement st = con.createStatement();
		//4、执行并获取结果
		String sql  ="delete from user where uid = 1";
		int row = st.executeUpdate(sql);
		if(row>0) {
			System.out.println("删除成功");
		}else {
			System.out.println("删除失败");
		}
		//5、关闭资源
		st.close();
		con.close();
	}
	
	/*
	 * 查询所有
	 */
	@Test
	public void findAll() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		Statement st = con.createStatement();
		//4、执行并获取结果
		String sql ="select * from user";
		ResultSet rs = st.executeQuery(sql);
		
		while(rs.next()) {
			//获取当前行内容
			int uid = rs.getInt(1);
			String name = rs.getString(2);
			int age = rs.getInt(3);
			System.out.println(uid+"\t"+name+"\t"+age);
		}
		//5、关闭资源
		rs.close();
		st.close();
		con.close();
		
	}
	
	/*
	 * 查询一个用户
	 */
	@Test
	public void findUser() throws Exception {
		// 1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		// 2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08", "root", "root");
		// 3、获取可执行对象
		Statement st = con.createStatement();
		// 4、执行并获取结果
		String sql ="select * from user where uid =2";
		ResultSet rs = st.executeQuery(sql);
		
		while(rs.next()) {
			int uid = rs.getInt("uid");
			String name = rs.getString("name");
			int age = rs.getInt("age");
			System.out.println(uid+"\t"+name+"\t"+age);
		}
		//5、关闭资源
		rs.close();
		st.close();
		con.close();
		
	}
	
}

PreparedStatement

登录功能SQL注入问题

概述:sql注入是一种常见网络攻击手段之一、它可以实现对于用户输入项的侵入、达到无密码跳过校验进行操作系统。
在这里插入图片描述
在这里插入图片描述
PreparedStatement是Statement的直接子接口,支持预编译技术,可以解决sql注入
原理 : 采用?占位符的方式对参数进行站位、将sql提前编译好、无论页面传递任何的内容、我们都认为传递是参数而不是作为sql关键字进行解析。就不会改变原有的sql结构

PreparedStatement 解决SQL注入问题

/*
 * sql 注入的解决
 */
public class Jdbc_Demo05 {
	public static void main(String[] args) throws Exception {
		Scanner sc = new Scanner(System.in);
		System.out.println("老弟请输入你的用户名");
		String username = sc.nextLine();
		System.out.println("老弟请输入你的密码");
		String password = sc.nextLine();
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		String sql ="select * from user1 where username =? and password =? ";
		//获取可执行对象
		PreparedStatement ps = con.prepareStatement(sql);
		//给?号占位符赋值
		ps.setString(1, username);
		ps.setString(2, password);
		//执行并获取结果
		ResultSet rs = ps.executeQuery();
		if(rs.next()) {
			System.out.println("登录成功");
		}else {
			System.out.println("登录失败");
		}
		//关闭资源
		rs.close();
		ps.close();
		con.close();
	}
}

PreparedStatement与Statement的对比
  1、PreparedStatement写法比较优雅、更加符合人们的开发思想、可读性非常好
  2、PreparedStatement拥有预编译的能力
  3、PreparedStatement执行效率要高于Statement

PreparedStatement的CRUD操作

package com.offcn.prepared;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
public class Prepared_Demo01 {
	/*
	 * 添加用户
	 */
	@Test
	public void insertUser() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		String sql="insert into user values(?,?,?)";
		PreparedStatement ps = con.prepareStatement(sql);
		//给?占位符赋值
		ps.setInt(1, 5);
		ps.setString(2, "罗志祥");
		ps.setInt(3, 18);
		//4、执行并获取结果
		int row = ps.executeUpdate();
		if(row>0) {
			System.out.println("添加成功");
		}else {
			System.out.println("添加失败");
		}
		//5、关闭资源
		ps.close();
		con.close();
	}
	
	/*
	 * 修改用户
	 */
	@Test
	public void updateUser() throws Exception {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//获取可执行对象
		String sql="update user set name=?,age=? where uid=?";
		PreparedStatement ps = con.prepareStatement(sql);
		//给?号赋值
		ps.setString(1, "孙悟空");
		ps.setInt(2, 500);
		ps.setInt(3, 2);
		//执行并获取结果
		int row = ps.executeUpdate();
		if(row>0) {
			System.out.println("修改成功");
		}else {
			System.out.println("修改失败");
		}
		//关闭资源
		ps.close();
		con.close();
		
	}
	
	/*
	 * 删除用户
	 */
	@Test
	public void deleteUser() throws Exception {
		
		Class.forName("com.mysql.jdbc.Driver");
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		String sql="delete from user where uid =?";
		PreparedStatement ps = con.prepareStatement(sql);
		ps.setInt(1, 3);
		int row = ps.executeUpdate();
		if(row>0) {
			System.out.println("删除成功");
		}else {
			System.out.println("删除失败");
		}
		ps.close();
		con.close();
		
	}
	
	/*
	 * 查询所有
	 */
	@Test
	public void findAll() throws Exception {
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2、获取连接
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		//3、获取可执行对象
		String sql="select * from user";
		PreparedStatement ps = con.prepareStatement(sql);
		//4、执行并获取结果
		ResultSet rs = ps.executeQuery();
		
		while(rs.next()) {
			int uid = rs.getInt(1);
			String name = rs.getString(2);
			int age = rs.getInt(3);
			System.out.println(uid+"\t"+name+"\t"+age);
		}
		//5、关闭资源
		rs.close();
		ps.close();
		con.close();
		
	}
	
	/*
	 * 查询一条数据
	 */
	@Test
	public void findUser() throws Exception {
		
		Class.forName("com.mysql.jdbc.Driver");
		Connection con = DriverManager.getConnection("jdbc:mysql:///day08","root","root");
		String sql="select * from user where uid =?";
		PreparedStatement ps = con.prepareStatement(sql);
		ps.setInt(1, 4);
		ResultSet rs = ps.executeQuery();
		while(rs.next()) {
			int uid = rs.getInt("uid");
			String name = rs.getString("name");
			int age = rs.getInt("age");
			System.out.println(uid+"\t"+name+"\t"+age);
		}
		rs.close();
		ps.close();
		con.close();
	}
	
}

JDBC工具类封装

工具类:简化 jdbc 操作、抽取重复性很高的代码到方法中达到方法的复用
  1、获取连接方法
  2、释放资源的方法
  3、硬编码的解决 配置文件(在src创建db.properties)
在这里插入图片描述

Driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///day08
user=root
password=root
/*
 * JDBC工具类
 */
public class JDBCUtils2 {
	private static String Driver;
	private static String url;
	private static String user;
	private static String password;
	//1、在整个类初始化过程中只会执行一次  2、优先级最高
	static {
		try {
			//持久化属性集  key-value的集合 
			Properties pro = new Properties();//{}
			//最终目标{Driver=com.mysql.jdbc.Driver,url=jdbc:mysql:///day08,user=root,password=root}
			pro.load(new FileInputStream("src/db.properties"));
			
			//根据key获取value
			Driver = pro.getProperty("Driver");
			url = pro.getProperty("url");
			user = pro.getProperty("user");
			password = pro.getProperty("password");
			
			//注册驱动
			Class.forName(Driver);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/*
	 * 获取连接的方法
	 */
	public static Connection getConncation() throws SQLException {
		
		return DriverManager.getConnection(url,user,password);
		
	}
	
	/*
	 * 关闭资源的方法
	 */
	public static void closeResource(ResultSet rs,Statement st,Connection con) {
		if(rs!=null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(st!=null) {
			try {
				st.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if(con!=null) {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值