博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
👉​​​点击跳转到网站​

一、Jdbc原理示意图

Java Jdbc的详解_mysql


二、Jdbc的概述

Java Jdbc的详解_java_02


Java Jdbc的详解_操作数据库_03


三、JDBC的快速入门

代码如下,具体讲解在注释中已经说明

public class Jdbc01 {
public static void main(String[] args) throws SQLException {
//前置工作:在项目下创建一个文件夹比如libs
//将mysql.jar拷贝到该目录下,点击add to project ..加入到项目

//1.注册驱动
Driver driver = new Driver();//创建Driver对象

//2.得到连接
//解读
//1.jdbc:mysql:// 规定好的协议,通过jdbc的方式连接mysql
//2.localhost 主机,可以是ip地址
//3.3306 表示sql监听的端口
//4.db_ly 连接到mysql dbms的哪个数据库
//5.mysql的连接本质就是socket连接
String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

//将用户名和密码放入到Properties对象
Properties properties = new Properties();
//说明 user 和 password 是规定好的,后面的值根据实际情况写
properties.setProperty("user", "root");//用户
properties.setProperty("password", "123456");//密码

Connection connect = driver.connect(url, properties);

//3.执行sql
// String sql = "insert into actor values(null,'刘德华','男','1970-01-01','110')" +
// ",(null,'周星驰','男','1980-01-03','123456789')";
String sql = "update actor set name='王宝强' where id = 3";
// String sql = "delete from actor where id =1";
//statement:用于执行静态的sql语句并返回其生成的结果对象
Statement statement = connect.createStatement();
//如果是dml语句,返回的就是影响行数
int rows = statement.executeUpdate(sql);
System.out.println(rows);

System.out.println(rows > 0 ? "成功" : "失败");

//4.关闭连接资源
statement.close();
connect.close();
}
}

输出结果如下

成功

四、Java操作数据库需要获得Connection连接,获取Connection连接的五种方式如下

public class JdbcConn {
//方式1
@Test
public void connect01() throws SQLException {
//1.注册驱动
Driver driver = new Driver();//创建Driver对象

String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

//将用户名和密码放入到Properties对象
Properties properties = new Properties();
//说明 user 和 password 是规定好的,后面的值根据实际情况写
properties.setProperty("user", "root");//用户
properties.setProperty("password", "123456");//密码

Connection connect = driver.connect(url, properties);
System.out.println(connect);
}

//方式2
@Test
public void connect02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
//使用反射获取Driver类,动态加载,更加的灵活,减少依赖性
Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";

//将用户名和密码放入到Properties对象
Properties properties = new Properties();
//说明 user 和 password 是规定好的,后面的值根据实际情况写
properties.setProperty("user", "root");//用户
properties.setProperty("password", "123456");//密码

Connection connect = driver.connect(url, properties);
System.out.println(connect);
}

//方法3 使用DriverManager 替代driver 进行统一管理
@Test
public void connect03() throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException {
Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();

//创建url和user的password
String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";
String user = "root";
String password = "123456";

//注册driver驱动
DriverManager.registerDriver(driver);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第三种方式:" + connection);
}

//方式4:使用Class.forName() 自动完成注册驱动,简化代码
//这种方式获取连接是使用的最多的,推荐使用
@Test
public void connect04() throws ClassNotFoundException, SQLException {
//使用反射加载了Driver类
//在加载Driver类时,完成注册
/*
源码:1.静态代码块,在类加载时,会执行一次
2. DriverManager.registerDriver(new Driver());
3.因此注册driver的工作已经完成
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
*/
Class.forName("com.mysql.cj.jdbc.Driver");
//创建url和user的password
String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT";
String user = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第四种方式:" + connection);
}

//方式5:在方式4的基础上改进,增加配置文件,让连接mysql更加灵活
@Test
public void connect05() throws IOException, ClassNotFoundException, SQLException {
//通过Properties,获取相关配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");

Class.forName(driver);
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("第五种方式:" + connection);
}
}

输出结果

com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
第三种方式:com.mysql.cj.jdbc.ConnectionImpl@7f77e91b
第四种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
第五种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b

四、ResultSet的详解

Java Jdbc的详解_连接数据库_04


对应的代码如下

@SuppressWarnings({"all"})
public class ResultSet_ {
public static void main(String[] args) throws Exception {
//通过Properties配置相关信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
//1.注册驱动
Class.forName(driver);
//建立与给定数据库的url连接
//2.建立连接
Connection connection = DriverManager.getConnection(url, user, password);

//3.得到Statement
Statement statement = connection.createStatement();
//4.组织sql
String sql = "SELECT id,name,sex,borndate,phone FROM ACTOR";

//执行给定的SQL语句,该语句返回单个 ResultSet对象。
/*

+----+--------+-----+---------------------+-----------+
| id | NAME | sex | borndate | phone |
+----+--------+-----+---------------------+-----------+
| 1 | 刘德华 | 男 | 1970-01-01 00:00:00 | 110 |
| 2 | 王宝强 | 男 | 1980-01-03 00:00:00 | 123456789 |
+----+--------+-----+---------------------+-----------+
*/
/*
resultSet对象的结构,debug进行阅读

查询到的数据,底层使用byte[] 数组存的,比如id =1 存放的1对应的ASCII码49
*/
ResultSet resultSet = statement.executeQuery(sql);

//5.使用while取出数据
while (resultSet.next()) {//让光标向后移动,如果没有更多行,则返回false
// int id = resultSet.getInt(1);//获取该行的第一列数据
int id = resultSet.getInt("id");//通过列名来获取值,推荐使用
String name = resultSet.getString(2);//获取该行第二列
String sex = resultSet.getString(3);//获取该行第三列
Date date = resultSet.getDate(4);//获取该行第四列
String phone = resultSet.getString(5);//获取该行第五列
System.out.println(id + "\t" + name + "\t" + sex + "\t" + date + "\t" + phone);
}

//6.关闭连接
resultSet.close();
statement.close();
connection.close();
}
}

输出结果

1 刘德华 男 1970-01-01  110
2 王宝强 男 1980-01-03 123456789

resultSet对象的结构如下

Java Jdbc的详解_连接数据库_05


Statement的介绍

Java Jdbc的详解_jdbc_06


使用Statement会存在SQL注入的风险,所以开发中一般使用PreparedStatement。

SQL注入演示:

CREATE TABLE ADMIN(
NAME VARCHAR(32) NOT NULL UNIQUE,
pwd VARCHAR(32) NOT NULL DEFAULT ''
);
INSERT INTO ADMIN VALUES('jack','123456');


SELECT * FROM ADMIN WHERE NAME='jack' AND pwd = '12456';

-- name 输入 1'or
-- pwd 输入or '1'='1
-- 条件'1'='1' 永远成立 能查到数据库中的数据,JAVA程序在拼接的时候就发生了SQL注入
SELECT * FROM ADMIN
WHERE NAME='1'or' AND pwd = 'or '1'='1';

下面演示使用Statement会发生SQL注入的风险

public class Statement_ {
public static void main(String[] args) throws Exception {

Scanner scanner = new Scanner(System.in);
//让用户输入管理员名和密码
System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束
String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
System.out.println("请输入管理员的密码:");
String admin_pwd = scanner.nextLine();

//通过Properties配置相关信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
//1.注册驱动
Class.forName(driver);
//建立与给定数据库的url连接
//2.建立连接
Connection connection = DriverManager.getConnection(url, user, password);

//3.得到Statement
Statement statement = connection.createStatement();
//4.组织sql
String sql = "SELECT NAME,pwd FROM ADMIN WHERE NAME='" + admin_name + "' AND pwd= '" + admin_pwd + "'";

ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {//如果查询到一条记录,则说明该管理存在
System.out.println("恭喜登录成功!");
} else {
System.out.println("登录失败!");
}

//关闭连接
resultSet.close();
statement.close();
connection.close();
}
}

输出结果如下

请输入管理员的名字:
1'or
请输入管理员的密码:
or '1'='1
恭喜登录成功!

五、PrepareStatement的介绍与使用

Java Jdbc的详解_jdbc_07


PrepareStatement的好处

Java Jdbc的详解_java_08


1、下面是演示代码,解决了SQL注入的问题

public class PrepareStatement_ {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
//让用户输入管理员名和密码
System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束
String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
System.out.println("请输入管理员的密码:");
String admin_pwd = scanner.nextLine();

//通过Properties配置相关信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
//1.注册驱动
Class.forName(driver);
//建立与给定数据库的url连接
//2.建立连接
Connection connection = DriverManager.getConnection(url, user, password);

//3.组织sql语句,sql语句的? 就相当于占位符
String sql = "SELECT name,pwd FROM ADMIN WHERE name=? AND pwd=?";
//4.得到preparedStatement
//preparedStatement对象是实现了PreparedStatement接口的实现类对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);

//给?赋值
preparedStatement.setString(1, admin_name);
preparedStatement.setString(2, admin_pwd);

//执行select语句,使用executeQuery()
//如果执行的是dml(update,insert,delete) 使用executeUpdate()
//这里执行executeQuery,不要写sql
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {//如果查询到一条记录,则说明该管理存在
System.out.println("登录成功!");
} else {
System.out.println("登录失败!");
}

//关闭连接
resultSet.close();
preparedStatement.close();
connection.close();
}
}

输出结果

请输入管理员的名字:
1 'or
请输入管理员的密码:
or '1'='1
登录失败!

2、使用PrepareStatement进行DML操作

public class PrepareStatement_DML {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
//让用户输入管理员名和密码
System.out.println("请输入要删除的管理员的名字:");//next():当接收到空格或者 '就是表示结束
String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束
// System.out.println("请输入管理员的密码:");
// String admin_pwd = scanner.nextLine();

//通过Properties配置相关信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
//1.注册驱动
Class.forName(driver);
//建立与给定数据库的url连接
//2.建立连接
Connection connection = DriverManager.getConnection(url, user, password);

//3.组织sql语句,sql语句的? 就相当于占位符
//添加记录
// String sql = "insert into admin values(?,?)";

//修改记录
// String sql = "update admin set name=? where pwd=?";

//删除记录
String sql = "delete from admin where name=?";

//4.得到preparedStatement
//preparedStatement对象是实现了PreparedStatement接口的实现类对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);

//给?赋值
preparedStatement.setString(1, admin_name);
// preparedStatement.setString(2, admin_pwd);

//如果执行的是dml(update,insert,delete) 使用executeUpdate()
int rows = preparedStatement.executeUpdate();
System.out.println(rows > 0 ? "执行成功" : "执行失败");

//关闭连接
preparedStatement.close();
connection.close();
}
}

输出结果

请输入要删除的管理员的名字:
smith
执行成功