05:JDBC的开发步骤,及其抽取的JDBCUtils工具类

1.1、JDBC是什么?

JDBC是一种用于执行SQL语句的Java API。(Java Data Base Connectivity,java数据库连接),是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问,它由一组用Java语言编写的接口和类组成。

1.2、JDBC原理是什么?

驱动(实现类)用于连接和操作数据库,实现JDBC(接口规范),

Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。

JDBC的7个步骤:注册驱动,创建连接,创建statement对象,执行sql语句,处理结果集,释放资源,关闭连接。

1.3、JDBC的应用场景举例

现在市面上都在研发无人驾驶汽车.假如Google研发了自己的无人驾驶汽车,百度也研发了自己的无人驾驶汽车. 而且这些汽车对外都提供了一些函数,让程序员可以控制自己的汽车.

Oracle(Java语言的研发者)发现无人驾驶汽车很火,那么自己就指定了一组接口,约定:不论以后哪家公司研发无人驾驶汽车,必须遵循我的这组接口.否则是无法接入我们的JAVA生态圈的. 那么Oracle指定的这组驱动就相当于JDBC.

class  GoogleCar  implement  ICar{
   Public void start(){
       调用谷歌Car对外提供的函数start
   }
   Public void run(){
       调用谷歌Car对外提供的函数run
   }
   Public void stop(){
       调用谷歌Car对外提供的函数 stop
   }
}

class  BaiDuCar  implement  ICar{
   Public void start(){
       调用百度Car对外提供的函数start
   }
   Public void run(){
       调用百度Car对外提供的函数run
   }
   Public void stop(){
       调用百度Car对外提供的函数 stop
   }
}


ICar car=new GoogleCar();
car.start();
car.run();
car.stop();

ICar car=new BaiDuCar();
car.start();
car.run();
car.stop();
//JDBC就是SUN早期设计的一组接口和部分类,这组接口主要约定了用JAVA语言操作各个不同数据仓库的规范.

1.4、JDBC对数据库增删改查操作举例

1.4.1、准备数据

#创建数据库
create database mydb;
#使用数据库
use mydb;
###创建分类表
create table category(
  cid int PRIMARY KEY AUTO_INCREMENT  ,
  cname varchar(100)
);
#初始化数据
insert into category (cname) values('家电');
insert into category (cname) values('服饰');
insert into category (cname) values('化妆品');

1.4.2、导入驱动jar包

创建lib目录,用于存放当前项目需要的所有jar包,选择jar包,右键执行build path / Add to Build Path

1.4.3、JDBC的7个开发步骤

1.注册驱动.
2.获得连接.
3.创建发送命令的Statement对象
4.执行sql语句
5.处理结果集
6.释放资源.
7.关闭连接

1.4.4、JDBC的实例代码

@Test
public void demo01() throws Exception{
	
	// 查询所有的分类信息
	// 注意:使用JDBC规范,采用都是 java.sql包下的内容
	
	//1 注册驱动
	Class.forName("com.mysql.jdbc.Driver");
//JDBC规范定义驱动接口:java.sql.Driver,MySql驱动包提供了实现类:com.mysql.jdbc.Driver
	
	//2 获得连接
	String url = "jdbc:mysql://localhost:3306/mydb";
//jdbc是固定的,其后是mysql数据库,ip地址、端口号、要连接的是哪个数据库名称
	Connection conn = DriverManager.getConnection(url, "root", "123456");
//连接数据库的url地址、用户名和密码
	
	//3创建语句执行者,也就是创建一个Statement对象,用来执行sql语句。
	Statement st = conn.createStatement();
	
	//4执行SQL语句,此处是查询语句
	ResultSet rs = st.executeQuery("select * from category");
/*
int executeUpdate(String sql); --执行insert delete update 语句,用于增删改操作.
ResultSet executeQuery(String sql); --执行select语句.用于查询操作
boolean execute(String sql); --执行select返回true 执行其他的语句返回false.用于判断操作。
*/
	
	//5处理结果集
	while(rs.next()){
		// 依次获得每一行数据
		
		Integer cid = rs.getInt("cid");//获得cid字段列数据
		String cname = rs.getString("cname");//获得cname字段列数据
		
		System.out.println(cid + " , " + cname);
	}
	//6释放资源
	rs.close();
	st.close();
    //7关闭连接
	conn.close();
//与io流一样,关闭的顺序是先得到的后关闭
	
}

效果:
1...家电
2...服饰
3...化妆品

 

2.1、抽取的JDBCUtils工具类

“获得数据库连接”操作,将在以后的增删改查所有功能中都存在,所以可以封装为工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。

JdbcUtils 

package com.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*jdbc开发步骤:
 * 注册驱动
 * 创建连接
 * 创建statement
 * 执行sql语句
 * 处理结果集
 * 释放资源
 * 关闭连接
 */

//JdbcUtils是由jdbc的7个步骤封装而成的工具类
//抽取出了注册驱动、创建连接、释放资源、关闭连接


public class JdbcUtils {
	private static String driver="com.mysql.jdbc.Driver";
	private static String url="jdbc:mysql://localhost:3306/mydb";
	private static String username="root";
	private static String password="123456";
	
	static{
		try {
			//注册驱动
			Class.forName(driver);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	//创建连接
	public static Connection getConnection() throws Exception {
		Connection conn = DriverManager.getConnection(url,username,password);
		return conn;
	}
	
	//释放资源
	public static void closeResource(Connection conn,Statement st,ResultSet rs) {
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(st != null){
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
			
}

增删改查测试类

package com.jdbc;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;
//JdbcUtils是由jdbc的7个步骤封装而成的工具类
//抽取出了注册驱动、创建连接、释放资源、关闭连接
//直接调用即可
public class demo2 {
	
	//插入数据
	@Test
	public void demo01() {
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		
		try {
			//获取连接
			conn=JdbcUtils.getConnection(); 
			st = conn.createStatement();
			//插入数据
			int r=st.executeUpdate("insert into category(cname) values('测试')");
			//处理结果
			System.out.println(r);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, st, rs);
		}
	}
	
	//修改数据
	@Test
	public void demo02() {
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		
		//获取连接
		try {
			conn=JdbcUtils.getConnection(); 
			st = conn.createStatement();
			//插入数据
			int r=st.executeUpdate("update category set cname='测试2' where cid=4");
			//处理结果
			System.out.println(r);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, st, rs);
		}
	}
	
	//删除数据
	@Test
	public void demo03() {
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		
		//获取连接
		try {
			conn=JdbcUtils.getConnection(); 
			st = conn.createStatement();
			//插入数据
			int r=st.executeUpdate("delete from category where cid=5");
			//处理结果
			System.out.println(r);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, st, rs);
		}
	}
	
	//查询所有
	@Test
	public void demo04() {
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		
		//获取连接
		try {
			conn=JdbcUtils.getConnection(); 
			st = conn.createStatement();
			//查询所有
			rs=st.executeQuery("select * from category");
			//处理结果集
			while(rs.next()){
				Integer cid = rs.getInt("cid");
				String cname = rs.getString("cname");
				System.out.println(cid+"..."+cname);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, st, rs);
		}
	}
	
	//通过id查询一条数据
	@Test
	public void demo05() {
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		
		//获取连接
		try {
			conn=JdbcUtils.getConnection(); 
			st = conn.createStatement();
			//查询所有
			rs=st.executeQuery("select * from category where cid=30");
			//处理结果集
			if(rs.next()){
				Integer cid = rs.getInt("cid");
				String cname = rs.getString("cname");
				System.out.println(cid+"..."+cname);
			}else{
				System.out.println("没有数据!");
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, st, rs);
		}
	}
}

​​​​SQL注入问题:

SQL注入:用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义。

假设有登录案例SQL语句如下:

SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;

此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX  OR a=a时,则真正执行的代码变为:

SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。为此,我们使用PreparedStatement来解决对应的问题。

预处理对象​​​​​​​API详解:

PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符?替换。

String sql = "select * from user where username = ? and password = ?";

PreparedStatement使用,需要通过以下3步骤完成:

  1. PreparedStatement预处理对象代码:

#获得预处理对象,需要提供已经使用占位符处理后的SQL语句

PreparedStatement psmt = conn.prepareStatement(sql)

  1. 设置实际参数

void setXxx(int index, Xxx xx) 将指定参数设置指定类型的值

参数1:index 实际参数序列号,从1开始。

参数2:xxx 实际参数值,xxx表示具体的类型。

例如:

setString(2, "1234") 把SQL语句中第2个位置的占位符?替换成实际参数 "1234"

  1. 执行SQL语句:
int executeUpdate(); --执行insert update delete语句.

ResultSet executeQuery(); --执行select语句.

boolean execute(); --执行select返回true 执行其他的语句返回false.
package com.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import org.junit.Test;
/*为了预防sql注入问题:
 * 	SELECT * FROM 用户表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;
 * PreparedStatement预处理对象,处理的每条sql语句中所有的实际参数,都必须使用占位符?替换。
 * String sql = "select * from user where username = ? and password = ?";
 * 1、PreparedStatement psmt = conn.prepareStatement(sql);
 * 2、setString(2, "1234") 把SQL语句中第2个位置的占位符?替换成实际参数 "1234"
 * 3、执行sql语句
 * 	int executeUpdate(); --执行insert update delete语句.
 * 	ResultSet executeQuery(); --执行select语句.
 * 	boolean execute(); --执行select返回true 执行其他的语句返回false.
 */
public class demo3 {
	
	//插入数据
	@Test
	public void demo01() {
		Connection conn=null;
		PreparedStatement psmt=null;
		ResultSet rs=null;
		
		try {
			//1、获取连接
			conn=JdbcUtils.getConnection(); 
			//2、处理sql语句
			String sql="insert into category(cname) values(?)";
			//3、获得预处理对象
			psmt=conn.prepareStatement(sql);
			//4、设置实际参数
			psmt.setString(1, "预处理");
			//5、执行sql语句
			int r = psmt.executeUpdate(sql);
			System.out.println(r);
			//处理结果
			System.out.println(r);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//无论如何都要释放资源、关闭连接
			JdbcUtils.closeResource(conn, psmt, rs);
		}
	}
	
	//修改数据
	@Test
	public void demo02(){
		//修改
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		
		try {
			conn = JdbcUtils.getConnection();
			
			//1 sql语句
			String sql = "update category set cname = ? where cid = ?";
			//2 获得预处理对象
			psmt = conn.prepareStatement(sql);
			//3设置实际参数
			psmt.setString(1, "测试数据");
			psmt.setInt(2, 4);
			//4执行
			int r = psmt.executeUpdate();
			System.out.println(r);
			
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally{
			JdbcUtils.closeResource(conn, psmt, rs);
		}
	}
	
	//删除数据
	@Test
	public void demo03(){
		//删除
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		
		try {
			conn = JdbcUtils.getConnection();
			
			//1 sql语句
			String sql = "delete from category where cid = ?";
			//2 获得预处理对象
			psmt = conn.prepareStatement(sql);
			//3设置实际参数
			psmt.setInt(1, 4);
			//4执行
			int r = psmt.executeUpdate();
			System.out.println(r);
			
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally{
			JdbcUtils.closeResource(conn, psmt, rs);
		}
	}
	
	//查询所有
	@Test
	public void demo04(){
		//查询所有
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		
		try {
			conn = JdbcUtils.getConnection();
			
			String sql = "select * from category";
			psmt = conn.prepareStatement(sql);
			rs = psmt.executeQuery();
			while(rs.next()){
				String cname = rs.getString("cname");
				System.out.println(cname);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally{
			JdbcUtils.closeResource(conn, psmt, rs);
		}
	}
	
	//通过id查询一条数据
	@Test
	public void demo05(){
		//通过id查询
		Connection conn = null;
		PreparedStatement psmt = null;
		ResultSet rs = null;
		
		try {
			conn = JdbcUtils.getConnection();
			
			String sql = "select * from category where cid = ?";
			psmt = conn.prepareStatement(sql);
			psmt.setInt(1, 2);
			rs = psmt.executeQuery();
			if(rs.next()){
				System.out.println("查询到");
			} else {
				System.out.println("查询不到");
			}
			
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally{
			JdbcUtils.closeResource(conn, psmt, rs);
		}
	}
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值