1.JDBC是什么?

2.JDBC的本质是什么?


3.为什么要面向接口编程?
解耦和:提高程序的扩展力,降低程序耦合度。

思考: 为什么要制定一套JDBC接口呢?
因为每一个数据库的底层实现原理都不一样.
每一个数据库产品都有自己独特的实现原理.
- 解压的.jar包下的.class文件就是对SUN公司制定的接口java.sql包下那一套接口的实现类.
记住一个程序如果只有接口,没有接口的实现类,这个程序是无法运行的!

驱动就是对JDBC接口的实现。
JDBC的本质到底是什么?
- 一套接口.


4.JDBC的使用步骤
第一步:注册驱动 (作用: 告诉java程序即将连接的是哪个品牌的数据库)
第二步:获取连接 (作用: 表示JVM进程和数据库进程这两个进程间的通道打开了)
第三步:获取数据库操作对象 (作用: 通过数据库操作对象来操作数据库,编写sql语句)
第四步:编写语句 (用来编写DQL DML…等语句)
第五步:处理查询结果集 (只有第四步是DQL语句,才会有这一步)
第六步:释放资源 (使用完资源之后一定要关闭资源.java和数据库属于进程间的通信!)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
//jdbc的使用步骤
public class JdbcTestConnection {
public static void main(String[] args) throws Exception {
//0.导入jar包
//1.注册驱动(底层调用下面的代码,在jdk5以后也可以不写)
Class.forName("com.mysql.jdbc.Driver");
//两种写法一样
//DriverManager.registerDriver(new Driver());
//2.获取连接
String url = "jdbc:mysql://localhost:3306/test";
String username = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url,username, password);
//3.编写sql语句
String sql = "select * from user";
//4.获取执行sql语句的对象statement
Statement statement = connection.createStatement();
//5.执行sql语句
statement.executeQuery(sql);
//6.处理结果集,关闭资源
statement.close();
connection.close();
}
}

5.常用api详解
1.DriverManager类常用api详解
1.注册驱动
public static void registerDriver(Driver driver) throws SQLException
向 DriverManager注册给定驱动程序。
:::color4
Class.forName(“com.mysql.jdbc.Driver”);点开Driver
:::

底层调用的DriverManager.registerDriver(new Driver());
注册驱动
1.Driver接口的包名: java.sql.Driver
Driver接口的实现类包名: com.mysql.jdbc.Driver(在.jar包中的一个实现类,要求必须配置到classpath环境变量中)
2.涉及到的类
java.sql.DriverManager (一个管理类)
通过这个类的registerConnect(Driver 对象)来注册驱动!

java.sql.Driver是一个接口,com.mysql.jdbc.Driver是它的一个实现类。
2.获取连接
public static Connection getConnection(String url) throws SQLException :试图建立到给定数据库 URL 的连接。
- 如果是本机的localhost和默认的端口号,url可以简写成:jdbc:mysql:///数据库名称?键值对参数
- 运行出现警告:

可以在url后面加上useSSL=false

2.Connection接口
作用1:获取执行sql的对象
//Connection的api详解 : 获取执行sql的对象
public class ConnectionApiTest1 {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
//1.获取执行的sql对象
//1.获取普通的对象
Statement statement = connection.createStatement();
//2.获取可以防止sql注入的对象(后面详解)
}
}
作用2:可以管理事务
核心方法:
- connection.setAutoCommit(false);//设置自动提交事务为false
- connection.commit();//提交事务
- connection.rollback();//回滚事务
//Connection的api详解 : 管理事务
public class ConnectionApiTest2 {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
Statement statement = connection.createStatement();
//jdbc事务管理
String sql1 = "update user set name = '张三' where id = 1";
String sql2 = "update user set name = '李四' where id = 2";
//保证两个sql语句都执行成功,或者都执行失败
try {
//开始事务,设置事务不自动提交
connection.setAutoCommit(false);
int i1 = statement.executeUpdate(sql1);
System.out.println(i1);
//制造异常
int k = 1/0;
int i2 = statement.executeUpdate(sql2);
System.out.println(i2);
//提交事务
connection.commit();
}catch (Exception e) {
//回滚事务
connection.rollback();
}
}
}
3.Statement接口
statement用来执行sql语句
//statement 对象
public class StatementTest {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
Statement statement = connection.createStatement();
//执行DML,返回受影响的行数
String sql1 = "update user set name = 'aaa' where id = 1";
int i1 = statement.executeUpdate(sql1);
if (i1 > 0){
System.out.println("更新成功");
}else {
System.out.println("更新失败");
}
//执行DDL,执行成功返回的可能是零
String sql2 = "create database test2";
int i2 = statement.executeUpdate(sql2);
//不能使用上面的方式判断是不是成功,一般不报异常就是成功了
//String sql2 = "drop database test2";
//执行删除,返回的是0,但是删除成功了
}
}
注意:不能根据DDL语句返回值大于零判断是不是操作成功了。
4.ResuleSet返回结果
封装了DQL语句的查询结果

//ResultSet返回结果
public class ResultSet {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
Statement statement = connection.createStatement();
//执行DQL语句
String sql3 = "select * from user";
java.sql.ResultSet resultSet = statement.executeQuery(sql3);
while (resultSet.next()){
//分别获取第一列、第二列和第三列的值
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
String email = resultSet.getString(3);
System.out.println(id + " " + name + " " + email);
}
}
}
5.PreparedStatement
1.什么是sql注入?
是通过操作输入来修改预先定义好的sql语句,用以达到对服务器进行攻击的方法。例如输入一个 ’ or ‘1’ = ‘1,导致’123’='‘or’1’='1’改变了判定条件。
//sql注入演示
public class PreparedStatementTest {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
Statement statement = connection.createStatement();
String name = "fdsfsadf";
String email = "' or '1' = '1";
//定义sql语句
String sql = "select * from user where name = '" + name + "' and email = '" + email + "'";
//打印sql语句
System.out.println(sql);
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()){
System.out.println("验证成功!");
}else {
System.out.println("验证失败!");
}
statement.close();
connection.close();
resultSet.close();
}
}
//输出
select * from user where name = 'fdsfsadf' and email = ' ' or '1' = '1'
验证成功!
2.解决办法
使用PreparedStatement把参数用?代替,作为占位符,底层是将sql语句用转义符进行转义。
比如:select * from user where name = 'fdsfsadf' and email = ' ' or '1' = '1'
转义后就是 select * from user where name = 'fdsfsadf' and email = ' \' or \'1\' = \'1'
将用户输入的内容作为一个文本。
import java.sql.*;
import java.sql.ResultSet;
//sql注入解决办法
public class PreparedStatementSolve {
public static void main(String[] args) throws SQLException {
Connection connection = DriverManager.getConnection("jdbc:mysql:///test", "root", "123456");
String name = "fdsfsadf";
String email = " ' or '1' = '1";
//1.定义sql语句
String sql = "select * from user where name = ? and email = ?";
//2.获取执行sql语句的对象(在这一步就进行预编译了)
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.设置参数,从1开始
preparedStatement.setString(1, name);
preparedStatement.setString(2, email);
//4.执行sql语句,不用传递sql语句了
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("验证成功!");
} else {
System.out.println("验证失败!");
}
preparedStatement.close();
connection.close();
resultSet.close();
}
}
输出结果 :验证失败!
3.PreparedStatement原理
首先明确一般的sql执行过程(使用Statement)
检查sql语法->编译->执行,前两部分耗时一般较长。
当创建一个 PreparedStatement 对象,并为它传入sql语句时,SQL 语句就会进行预编译。后续执行时,只需要传递参数值,而不需要重新编译 SQL 语句,只需要预编译一次。
开启预编译:在url后面加上 useServerPrepStmts=true,默认是关闭的。
4.优点
- 可以预编译sql,性能更高。
- 可以防止sql注入,将敏感字符进行转义
6.数据库连接池
1.概念
避免连接遗漏:某个用户占用connection资源但是处于空闲状态,导致新的用户没有connection可用,数据库连接池就会对该connection进行回收,避免连接遗漏。
2使用步骤
- 导入jar包
- 定义配置文件
- 加载配置文件
- 获取连接池对象
- 获取数据库连接
//druid的使用步骤
public class DruidTest {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件,在src目录下创建druid.properties文件
//3.加载配置文件(E:/review-code/jdbc-learning/src/druid.properties)绝对路径
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-learning/src/druid.properties"));
//4.获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//进行sql操作
//注意报错:找不到路径,通过下面的代码去更改路径
System.out.println(System.getProperty("user.dir"));//E:\review-code
}
}
190

被折叠的 条评论
为什么被折叠?



