一,JDBC概述
JDBC 全称 java DataBase Connectivity,java 数据操作。
-
JDBC 就是 java 语言操作关系型数据库的一套 API。
-
JDBC 的目的是用同一套 java 代表,操作不同的关系型数据库。
-
JDBC 本质是 Sun 公司定义的一套操作所有关系型数据库的规则,即接口。
各个数据库厂商去实现这套接口,提供数据库驱动 jar 包,我们可以使用这套接口 JDBC 编程,真正执行的代码是驱动 jar 包中的实现类
好处:java 代表不需要针对不同的数据库分别开发 jdbc,可以随时替换底层数据库而代码不需要改变。
注意:所有 Java ORM 框架,本质上都是在 JDBC 上「套娃」!
-
MyBatis、Hibernate、JPA、Spring Data JDBCTemplate... 全都是 JDBC 的高级包装。
-
从底层到上层:数据库访问的「套娃」结构
业务代码 ↓ ORM框架(MyBatis、Hibernate) ← 你写的代码 ↓ JDBCTemplate、MyBatis Executor ← 框架核心 ↓ JDBC Driver(mysql-connector-java) ← 数据库驱动 ↓ MySQL协议(TCP Socket通信) ← 网络协议 ↓ MySQL数据库服务器
二,快速入门
以 MYSQL 为例,先导入mysql-connercot-java这个 jar 包到项目中。
-
注册驱动
Class.forName("com.mysql.jdbc.Driver");//mysql5.0之后的写法 Class.forName("com.mysql.cj.jdbc.Driver");//mysql8.0之后的写法 -
获取连接
String url = "jdbc:mysql://127.0.0.1:3306/wdadwa?&useSSL=false&serverTimezone=UTC"; String username="root"; String password="123456"; Connection conn = DriverManager.getConnection(url, username, password); -
定义 SQL 语句
String sql="select * from student"; -
获取执行 SQL 的对象
Statement stmt = conn.createStatement(); -
执行 SQL
ResultSet resultSet = stmt.executeQuery(sql); -
处理返回结果
-
释放资源
stmt.close(); conn.close();
三,API详解
3.1 DriverManger
作用:
- 注册驱动
- 获取数据库连接
两个重要的方法
DriverManager.registerDriver(new Driver());//注册驱动
Connection conn = DriverManager.getConnection(url, username, password);//建立连接对象
第一个注册驱动在 Mysql5.0 之后就不需要写了,Class.forName(""com.mysql.jdbc.Driver"") 在底层也是通过这个方式注册的驱动.
DriverManger 建立连接对象三个参数详解:
-
第一个参数:
语法:
jdbc:mysql://ip地址(域名):端口号/数据库名名?参数键值对1&参数键值对2...举例:
jdbc:mysql://127.0.0.1:3306/db1如果连接的是本机 mysql, 默认端口 3306,url 可以简写为:
jdbc:mysql////数据库名?参数键值对1&参数键值对2...参数键值对有:
useSSL=false禁用安全连接方式,解决警告提示.useServerPrepStmts=true打开SQL预编译功能
-
第二个参数:用户名
-
第三个参数:密码
3.2 Connection
作用:
- 获取执行SQL的对象
- 管理事务
利用 Connection 获取执行 SQL 的对象分为:
-
普通执行 SQL 对象
Statement stmt = conn.createStatement(); -
预编译 SQL 的执行对象 (防止 SQL 注入)
PreparedStatement preparedStatement = conn.prepareStatement(sql); -
执行存储过程的对象(存储过程不常用 )
CallableStatement callableStatement = conn.prepareCall();
利用 Connection 进行事务管理
//开启事务
setAutoCommit(boolean autoCommit);//true自动提交事务,false手动提交事务
conn.commit();//提交事务
conn.setAutoCommit(false);//关闭事务的自动提交
conn.rollback();//回滚事务
一般在 java 中使用 try catch 包围起来,当出现异常就回滚事务。
3.3 Statement
作用:执行 SQL 语句。
Statement 提供了三种方法来执行 SQL
-
executeQuery用来执行 DQL 语句String sql="select * from student where name='"+name+"'and password='"+pwd+"'"; //即通过 '"字符串"'这种形式把字符串包围起来 ResultSet resultSet = stmt.executeQuery(sql); -
executeUpdate用来执行 DDL,DML 语句String sql="update student set age=10 where age=21"; int i = stmt.executeUpdate(sql); //执行DDL语句返回的可能是0,执行DML语句返回的是被影响的行数 -
execute可以执行任意 sql 查询boolean execute = stmt.execute(sql); //如果查询结果时ResultSet,这个方法就会返回true,如果不是ResultSet,比如insert或者update,就会返回false。
3.4 ResultSet
作用:封装了 DQL 查询语句的结果集合。
使用 ResultSet 中方法获取查询结果:
boolean next();
//将光标从当前位置向下移动一行,并判断当前行是否为有效行(移动后)
//返回值true,有效行
//返回值false,无效行
//默认从数据行的上一行作为起始位置

xxx getXXX(参数);//获取数据
//xxx代表数据类型,如int getInt(参数),String getString(参数)
//参数:有两种重载形式
//int:根据列的编号获取元素,从1开始
//String:根据列的名字获取元素
//举例:
ResultSet res = stmt.executeQuery(sql);
res.getInt(1);//获取id
res.getInt("id");//获取id
while(res.next()){
int anInt = res.getInt(4);
System.out.println(anInt);
}
res.close();//写完后记得释放资源
3.5 PreparedStatement
PreparedStatement 是 Statement 的子类。
作用:与变量 SQL 并执行,预防 SQL 注入问题。
SQL 注入:通过操作输入来修改事先定义好的 SQL 语句,用来达到执行代码对服务器进行攻击的方法。
SQL 注入产生的原因:字符串拼接产生的问题
String name="wdadwa";
String pwd="' or '1'='1";
String sql="select * from tb_user where username='"+name+"' and password='"+pwd+"' ";
System.out.println(sql);//select * from tb_user where username='wdadwa' and password='' or '1'='1'
//这样的SQL语句会导致查询返回结果为整张表,因为1=1是个恒等式,这个SQL等同于select * from tb_user
PreparedStatement 使用
-
获取 PreparedStatement 对象
String sql="select * from student where name=? and age=?";//用占位符?代替变量 PreparedStatement pstmt=conn.prepareStatement(sql); -
设置参数值
//PreparedStatement对象:setXxx(参数1,参数2):给?赋值 //Xxx:数据类型,比如setInt(参数1,参数2); //参数1:?占位符的编号,从1开始 //参数2:?的值 pstmt.setString(1,"张三"); pstmt.setInt(2,10); -
执行 SQL
ResultSet resultSet1 = pstmt.execute();//执行SQL语句 ResultSet resultSet2= pstmt.executeQuery();//executeQuery执行DQL语句 ResultSet resultSet3 = pstmt.executeUpdate();//executeUpdate用来执行DDL,DML语句底层原理:将
"' or '1'='1"中的单引号作为文本使用转义字符反斜杠转义了,从而区分了 sql 语句的单引号和文本的单引号实际传入的是
select * from tb_user where username='wdadwa' and password='\' or \'1\'=\'1'
PreparedStatement 预编译:
- 在获取PreparedStatement对象时,将SQL语句发送给MYSQL服务器进行检查,编译(这些步骤很耗时)
- 执行时就不需要再进行这些步骤了
- 如果sql模板一样,只需进行一次检查和编译即可。
预编译功能需要在建立连接对象的时候传入参数useServerPreStmts=true
四,数据库连接池
数据库连接池简介:
-
数据库连接池是个容器,负责分配,管理数据库连接
-
允许应用程序重复使用一个现有的数据库连接,而不是重新再建一个。
-
释放空闲时间超过最大空闲时间的数据库连接,避免因为没有释放数据库连接导致的数据库连接遗漏
好处:
- 资源重用
- 提高系统响应效率
- 避免数据库连接遗漏
数据库连接池实现
-
标准接口:
DataSource官方提供的数据库连接池标准接口,由第三方组织实现此接口。
功能:获取连接
Connection getConnection() -
常见的数据库连接池:
- DBCP
- C3P0
- Druid
-
Druid:
Druid 连接池是阿里巴巴开源的数据库连接池项目,是 java 语言最好的数据库连接池之一。
使用方法:
-
导入 jar 包
-
定义配置文件
druip.properties模板:
#驱动类名,固定模板 driverClassName=com.mysql.cj.jdbc.Driver #url url=jdbc:mysql://localhost:3306/test?useUnicode=true& #字符编码 等配置 characterEncoding=utf-8&useSSL=false&serverTimezone =Asia/Shanghai #数据库的账号密码 username=root password=123456 #初始化连接数 initialSize=10 #最大连接数 maxActive=100 #最大等待时间(毫秒 maxWait=3000 -
加载配置文件
Properties prop=new Properties(); prop.load(new FileInputStream("src/druid.properties"));//配置文件路径 -
获取数据库连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop); -
获取连接
Connection connection = dataSource.getConnection();