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步骤完成:
- PreparedStatement预处理对象代码:
#获得预处理对象,需要提供已经使用占位符处理后的SQL语句
PreparedStatement psmt = conn.prepareStatement(sql)
- 设置实际参数
void setXxx(int index, Xxx xx) 将指定参数设置指定类型的值
参数1:index 实际参数序列号,从1开始。
参数2:xxx 实际参数值,xxx表示具体的类型。
例如:
setString(2, "1234") 把SQL语句中第2个位置的占位符?替换成实际参数 "1234"
- 执行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);
}
}
}