目录
一、JDBC快速入门
二、JDBC API详解
(一)DriverManager
(二)Connection
(三)Statement
(四)ResultSet
(五)PreparedStatement
三、数据库连接池
(一)数据库连接池简介
(二)数据库连接池实现
(三)Driud使用
笔记跟课:黑马程序员
https://www.bilibili.com/video/BV1Qf4y1T7Hx?p=30&vd_source=0e0517ebadf244dd640ab0b61dd700c5
一、JDBC快速入门
1.创建工程,导入驱动 jar 包
2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
3.获取连接
Connection conn = DriverManager.getConnection(url, username, password);
4.定义SQL语句
String sql = "update…";
5.获取执行SQL对象
Statement stmt = conn.createStatement();
6.执行SQL
stmt.executeUpdate(sql);
7.处理返回结果
8.释放资源
【全部代码】:
public class JDBCDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url="jdbc:mysql://127.0.0.1:3306/test";
String user="root";
String password="✅✅✅";
Connection conn=DriverManager.getConnection(url,user,password);
//3.定义sql
String sql = "update stu set Class = '软件133' where S_ID = '123456'";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//5. 执行sql
int count = stmt.executeUpdate(sql);//受影响的行数
//6. 处理结果
System.out.println(count);
//7. 释放资源
stmt.close();
conn.close();
}
}
二、JDBC API详解
(一)DriverManager
- 注册驱动
MySQL 5之后的驱动包,可以省略注册驱动( Class.forName )的步骤,会自动加载jar 包中 META-INF/services/java.sql.Driver 文件中的驱动类 -
获取连接
DriverManager.getConnection(url, user, password);
1.参数url: jdbc:mysql://ip地址 ( 域名 ): 端口号 / 数据库名称 ? 参数键值对1&参数键值对2…
示例: jdbc:mysql://127.0.0.1:3306/db1
2.如果连接的是本机mysql服务,且mysql服务默认端口是3306,则可以简写成jdbc:mysql:///db1
(二)Connection
- 获取执行对象
- 普通执行SQL对象:
Statement createStatement()
- 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
-
执行存储过程的对象
CallableStatement prepareCall(sql)
- 普通执行SQL对象:
- 事务管理
- MySQL事务管理的操作:
开启事务 : BEGIN; 或者 START TRANSACTION;提交事务 : COMMIT;回滚事务 : ROLLBACK;MySQL 默认是自动提交事务
-
Connection接 口中定义了 3 个对应的方法:开启事务:setAutoCommit(boolean autoCommit);
true为自动提交事务;false为手动提交事务,即为开启事务提交事务:commit()回滚事务:rollback()
- MySQL事务管理的操作:
Connection 全部代码
package com.itheima.jdbc_demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo_Connection {
public static void main(String[] args) throws Exception {
//1. 注册驱动
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1? useSSL=false";
String username = "root";
String password = "✅✅✅";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql1 = "update account set money = 3000 where id = 1";
String sql2 = "update account set money = 3000 where id = 2";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
try {
// ============开启事务==========
conn.setAutoCommit(false);
//5. 执行sql
int count1 = stmt.executeUpdate(sql1);//受影响的行数
//6. 处理结果
System.out.println(count1);
int i = 3 / 0;
//5. 执行sql
int count2 = stmt.executeUpdate(sql2);//受影响的行数
//6. 处理结果
System.out.println(count2);
// ============提交事务==========
//程序运行到此处,说明没有出现任何问题,则需求提交事务
conn.commit();
} catch (Exception e) {
// ============回滚事务==========
//程序在出现异常时会执行到这个地方,此时就需要回滚事务
conn.rollback();
e.printStackTrace();
}
//7. 释放资源
stmt.close();
conn.close();
}
}
(三)Statement
- 执行 sql 语句
- 执行DML(数据操纵语言)、DDL(数据定义语言)语句
返回值:(1)DML语句影响的行数 (2)DDL语句执行成功也可能返回0int count = stmt.executeUpdate(sql);
- 执行DQL(数据查询语言)语句
ResultSet rs = stmt.executeQuery(sql);
返回值:ResultSet结果集对象
- 执行DML(数据操纵语言)、DDL(数据定义语言)语句
(四)ResultSet
- 封装DQL查询语句的结果——ResultSet stmt.executeQuery(sql)【返回ResultSet对象】
- 获取查询结果
1.boolean next():
(1)将光标从当前位置向前移动一行(2)判断当前行是否为有效行
● ● ● ↪️返回值:true : 有效航,当前行有数据false : 无效行,当前行没有数据2.
xxx getXxx(参数):获取数据
● ● ● xxx : 数据类型;如: int getInt(参数) ;String getString(参数)
● ● ● 参数:int类型的参数:列的编号,从1开始;String类型的参数: 列的名称 - 使用步骤
1.游标向下移动一行,并判断该行是否有数据:next()
2.获取数据:getXxx(参数)//循环判断游标是否是最后一行末尾 while (rs.next()){ //获取数据 rs.getXxx(参数); }
- 获取查询结果
ResultSet全部代码
/**
* JDBC API 详解:ResultSet
*/
public class JDBCDemo_ResultSet {
/**
* 执行DQL
* @throws Exception
*/
@Test
public void testResultSet() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1";
String username = "root";
String password = "✅✅✅";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "select * from account";
//4. 获取statement对象
Statement stmt = conn.createStatement();
//5. 执行sql
ResultSet rs = stmt.executeQuery(sql);
//6. 处理结果, 遍历rs中的所有数据
// 6.1 光标向下移动一行,并且判断当前行是否有数据
while (rs.next()){
//6.2 获取数据 getXxx()
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
System.out.println(id);
System.out.println(name);
System.out.println(money);
System.out.println("--------------");
}
//7. 释放资源
rs.close();
stmt.close();
conn.close();
}
/**
* 查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中
* 1. 定义实体类Account
* 2. 查询数据,封装到Account对象中
* 3. 将Account对象存入ArrayList集合中
*
*
* @throws Exception
*/
@Test
public void testResultSet2() throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "✅✅✅";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql = "select * from account";
//4. 获取statement对象
Statement stmt = conn.createStatement();
//5. 执行sql
ResultSet rs = stmt.executeQuery(sql);
// 创建集合
List<Account> list = new ArrayList<>();
// 6.1 光标向下移动一行,并且判断当前行是否有数据
while (rs.next()){
Account account = new Account();
//6.2 获取数据 getXxx()
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
//赋值
account.setId(id);
account.setName(name);
account.setMoney(money);
// 存入集合
list.add(account);
}
System.out.println(list);
//7. 释放资源
rs.close();
stmt.close();
conn.close();
}
}
(五)PreparedStatement
- 预编译SQL语句并执行,预防SQL注入问题
SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
1.获取PreparedStatement对象// SQL语句中的参数值,使用?占位符替代String sql = "select * from user where username = ? and password = ?" ;// 通过Connection对象获取,并传入对应的sql语句PreparedStatement pstmt = conn . prepareStatement ( sql );2.设置参数值
PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值● ● ● Xxx:数据类型 ; 如 setInt (参数1 ,参数 2)● ● ● 参数:参数1 : ?的位置编号,从 1 开始参数2 : ?的值3.执行SQL
executeUpdate(); 执行DDL语句和DML语句executeQuery(); 执行DQL语句● ● ● 调用这两个方法时不需要传递 SQL 语句,因为获取 SQL 语 句执行对象时已经对 SQL 语句进行预编译了
PreparedStatement全部代码
/**
* API详解:PreparedStatement
*/
public class JDBCDemo_PreparedStatement {
@Test
public void testPreparedStatement() throws Exception {
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true";
String username = "root";
String password = "✅✅✅";
Connection conn = DriverManager.getConnection(url, username, password);
// 接收用户输入 用户名和密码
String name = "zhangsan";
String pwd = "' or '1' = '1";
// 定义sql
String sql = "select * from tb_user where username = ? and password = ?";
// 获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
// 执行sql
ResultSet rs = pstmt.executeQuery();
// 判断登录是否成功
if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
}
//7. 释放资源
rs.close();
pstmt.close();
conn.close();
}
}
注意:需要使用 useServerPrepStmts=true 才能开启预编译功能,否则只是解决了SQL注入问题,预编译性能更高。
三、数据库连接池
(一)数据库连接池简介
-
数据库连接池是个容器,负责分配、管理数据库连接 (Connection)
-
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一 个
-
释放空闲时间超过最大空闲时间的数据库连接,避免因为没有释放数据库连接而引起的数据库连接遗漏
数据库使用了数据库连接池后,就能达到Connection
对象的复用,如下图
连接池是在一开始就创建好了一些连接(Connection
)对象存储起来。用户需要连接数据库时,不需要自己创建连接,而只需要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池;这样就可以起到资源重用,也节省了频繁创建连接销毁连接所花费的时间,从而提升了系统响应的速度。
(二)数据库连接池实现
标准接口:DataSource
|
- 常见的数据库连接池
- DBCP
- C3P0
- Druid
我们现在使用更多的是Druid,它的性能比其他两个会好一些
-
Druid (德鲁伊)Druid 连接池是阿里巴巴开源的数据库连接池项目,功能强大,性能优秀,是Java 语言最好的数据库连接池之一
(三)Driud使用
-
导入jar包 druid-1.1.12.jar
导入后选择 Add as Library
-
定义配置文件——druid.properties配置文件代码:
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true username=root password=✅✅✅ # 初始化连接数量 initialSize=5 # 最大连接数 maxActive=10 # 最大等待时间 maxWait=3000
-
加载配置文件
-
获取数据库连接池对象
-
获取连接
Druid使用全部代码
/**
* Druid数据库连接池演示
*/
class DruidDemo {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3. 加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("JDBC(itheima)/src/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5. 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection);
//System.out.println(System.getProperty("user.dir"));
}
}