JDBC知识点
😍 为爱发癫的每一天…
JDBC概念
- JDBC:是使用Java语言操作关系型数据库的一套API
- 全称:(Java DataBase Connectivity)Java数据库连接
JDBC本质
- 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口(即:写实现类),提供数据库驱动jar包(驱动 == 实现类)
- 我们可以使用这套接口(JDBC)编程,真正执行代码的驱动jar包中的实现类
JDBC好处
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层的数据库,访问数据库的Java代码基本不变
![image-20230705102350497](https://i-blog.csdnimg.cn/blog_migrate/d66d8e6ce5ef193d14d1a24ac082eac3.png)
JDBC快速入门
-
创建工程,导入驱动jar包(即引入数据库厂商的对JDBC接口实现类 == 驱动)
-
注册驱动
Class.forName("com.mysql.jdbc.Driver");//此处引入的是MYSQL的驱动包
-
获取连接
Connection conn = DriverManager.getConnection(url,username,password);
-
定义SQL语句
String sql = "update...";
-
获取执行SQL语句的对象
Statement stmt = conn.createStatement();
-
执行SQL语句
stmt.executeUpdate(sql);
-
处理返回结果
-
释放资源
stmt.close(); conn.close();
知识点补充
标准的SQL只包含 9 种语句
数据查询:select
数据定义:create、drop、delete
数据操控:insert、update、delete
数据控制:grant、revoke
连接数据库
首先加载数据库驱动程序,然后每次访问数据库就创建一个connection对象,接着执行SQL语句,最后完成数据库操作后关闭connection对象,释放与数据库的连接
-
加载驱动:Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”)
-
获取连接:Connection con = DriverManager.getConnection(String url,String username,String password)
-
创建会话:Statment st = con.createStatment()
statment 是一个有关建立对话的接口,因此不能产生对象,只能通过连接类来创建对象
-
处理查询结果集
有了 Statment 对象就可以调用相应方法实现对数据库的增删改查
并将结果保存在ResultSet 类对象中
例如:
String sql = "select * from student"; Resuleset result = st.executeQuery(sql);
JDBC 高级
事务管理(要么别干,要干就干到底)
数据库的所有操作都是建立在Connection连接类基础上的,那事务管理也是在其上进行的,若要管理一个事务可在数据库操作动作之前,将数据库自动提交设置为false,即 con.setAutoCommit(false) 在数据库操作没有任何异常下再将事务提交 con.commit,提交完毕后将事务管理控制权还给数据库 con.setAutoCommit(true)
发生错误时可用con.rollback()函数进行回滚
JDBC程序编写步骤
- 导入 java.sql 包
- JDBC_ODBC桥方式:建立数据源(ODBC)
- 纯Java驱动方式:附加相应产商提供的驱动
- 加载并注册驱动程序
- 创建
Connnection
对象 - 创建
Statement
对象 - 执行SQL语句
- 使用
ResultSet
对象 - 关闭ResultSet对象
- 关闭Statement对象
- 关闭Connection对象
首先第一步创建工程的时候需要导入 相应数据库的jar包
导入jar包的同时还需要使包工作,add library
第二步:注册驱动 Class.forName(“com.mysql.cj.jdbc.Driver”);
第三步:获取连接 $Connection conn = DriverManager.getConnection ( url,username,password ) $;
第四步:定义 sql 语句
第五步:获取执行 SQL的对象 S t a t e m e n t s t m t = c o n n . c r e a t e S t a t e m e n t ( ) ; Statement stmt = conn.createStatement(); Statementstmt=conn.createStatement();
第六步:执行 sql 语句 s t m t . e x e c u t e U p d a t e ( s q l ) stmt.executeUpdate(sql) stmt.executeUpdate(sql)
package com.itheima.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/*
* JDBC 的快速入门
*/
public class JDBCDemo {
public static void main(String[] args) throws Exception{
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db1";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url,username,password);
//3. 定义sql语句
String sql = "update student set score = 77 where id = 8";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//5.执行sql语句
int count = stmt.executeUpdate(sql); //返回值为受影响的行数
//6.处理结果
System.out.print(count);
//7. 释放资源
stmt.close();
conn.close();
}
}
- 有时候在操作数据库的时候当某些连续操作中间出现了异常就会出现异常发生前的sql语句执行了而异常之后的sql语句不会执行,启用JDBC事务管理即可避免,并且产生事务回滚
String url = "jdbc:mysql://127.0.0.1:3306/db1";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url,username,password);
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
//5.执行sql语句
try{
conn.setAutoCommit(false);
/*
* 此处为连续执行的sql操作,
* 若在此过程中出现了错误
* 则所有sql回滚到执行之前的状态
*/
conn.commit();
}catch (Exception throwables){
conn.rollback(); //捕获到异常的时候自动回滚事务
throwables.printStackTrace();
}
- 事务管理:
-
- 开启事务:setAutocommit(boolean autoCommt):true 为自动提交事务,false为手动提交事务
- 提交事务:commit()
- 回滚事务:rollback()
ResultSet 结果集处理
-
ResultSet (结果集对象)作用:
- 封装了DQL的查询语句结果
ResultSet stmt.executeQuery(sql); //执行DQL语句,返回ResultSet对象
-
获取查询结果:
Boolean next():(1)将光标从当前位置向前移动一行 (2)判断当前行是否为有效行
返回值:
true:有效行,当前行有数据
false:无效行,当前行无数据
xxx getXxx(参数): 获取数据
xxx: 数据类型; 如: int getInt(参数);String getString(参数)
参数: //此处的参数是getXxx中的参数,可以选择输入列号或者键值 作为参数
int:列的编号,从1开始
String:列的位置
示例:
ResultSet resultset = stmt.executeQuery(sql3);
//创建结果集
while(resultset.next()){
//以下get中的参数为sql中列的标记index
int int_value = resultset.getInt(1);
String string_value = resultset.getString(2);
String a = resultset.getString(3);
String b = resultset.getString(4);
System.out.println(int_value+string_value+a+b);
}
API【DriverManager】
-
DriverManager(驱动管理类)作用:
-
注册驱动
-
获取数据库连接
返回值 方法 static Connection
getConnection(String url,String username,String password)
-
参数:
-
url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1 & 参数键值对2…
示例:jdbc:mysql://127.0.0.1:3306/db1
细节:
- 如果连接的是本机mysql的服务器,并且mysql服务器默认端口是3306,则url可以简写为:
jdbc:mysql:///数据库名称?参数键值对 - 配置useSSL = false 参数,禁用安全连接的方式,解决警告提示
- 如果连接的是本机mysql的服务器,并且mysql服务器默认端口是3306,则url可以简写为:
-
user:用户名
-
password:密码
-
-
API【Connection】
-
Connection(数据库连接对象)作用:
-
获取执行SQL的对象
- 普通执行SQL对象
Statement createStatment()
- 预编译SQL的执行的SQL对象:防止SQL注入
PrepareStatement prepareStatement(sql)
- 执行存储过程的对象
CallableStatement prepareCall(sql)
-
管理事务
- MYSQL事务管理
开启事务:BEGIN/START TRANSACTION 提交事务:COMMIT 回滚事务:ROLLBACK MYSQL默认自动提交事务
- JDBC事务管理:Connection接口定义了三个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务 提交事务:commit() 回滚事务:rollback()
-
API【Statement】
-
Statement作用:
- 执行SQL语句
-
执行SQL语句
int executeUpdate(sql):执行DML、DDL语句 返回值:(1)DML语句影响的行数(2)DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(sql):执行DQL语句 返回值:ResultSet结果集对象
API【ResultSet】
-
ResultSet(结果集对象)作用:
- 封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet对象
-
获取查询结果
boolean next():(1)将光标从当前位置向前移动一行.(2)判断当前行是否为有效行 返回值: true:有效行,当前行有数据 false:无效行,当前行无数据
xxx getXxx(参数):获取数据 xxx:数据类型;如:int getInt(参数);String getString(参数) 参数: int:列的编号,【从1开始】 String:列的名称
-
使用步骤:
- 游标向下移动一行,并判断该行是否有数据:next()
- 获取数据:getXxx(参数)
//循环判断游标是否是最后一行末尾 while(rs.next()){ //获取数据 rs.getXxx(参数); }
API【PrepareStatement 】
PrepareStatement优点:
- 预编译SQL,性能更高
- 防止SQL注入:将敏感字符转义
PrepareStatement
预编译功能开启:useServerPreStmts=true
String url = "jdbc:mysql://127.0.0.1:3306/db1&useServerPreStmts=true";
PrepareStatement原理:
- 在获取PrepareStatement对象时,将sql语句发送到mysql服务器进行检查,编译(步骤耗时)。
- 编译之后,再多次执行相同语句的时候就不用再次检查编译,速度提高。
- 如果sql模板一样,只需要进行一次检查,编译。
防止SQL注入
- PrepareStatement 的作用:
- 预编译SQL并执行SQL语句
- 获取 PrepareStatement 对象
//SQL语句中的参数值,使用?当做占位符代替
String sql = "select * from user where username = ? and password = ?";
//通过Connection对象获取,并传入对应的sql语句
PrepareStatement pstmt = conn.prepareStatement(sql);
- 设置参数值:
PrepareStatement 对象:setXxx(参数1,参数2)
Xxx: 数据类型; 如setInt(参数1,参数2)
参数:
参数1: ?的位置编号,默认从1开始
参数2: ?的值
举个例子
String name = "zhangsan";
String pwd = "10086"
// 定义SQL语句
String sql = "select * from tb_user where username = ? and password = ?";
// 获取pstmt对象
PrepareStatement pstmt = conn.prepareStatement(sql);
// 设置 ?的值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
// 执行SQL语句
ResultSet rs = pstmt.executeQuery();
- 执行SQL
executeUpdate(); / executeQuery(); //不需要再次传递sql
5. 数据库连接池
5.1 数据库连接池简介:
- 数据库连接池是个容器,负责分配,管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
5.2 优点:
- 资源重复利用
- 提升系统响应速度
- 避免数据库连接遗漏
5.3 数据库连接池实现
-
标准接口:DataSource
- 官方(SUN)提供的数据库连接池的标准接口,由第三方组织实现此接口
- 功能:获取连接
Connection getConnection()
-
常见的数据库连接池:
- DBCP
- C3P0
- Druid
5.4 druid数据库连接池实例
public static void main(String[] args) throws Exception {
//1.导入jar包:下载并且安装jar包并且导入到lib库在添加到模板库
//2.定义配置文件:在同级目录下创建一个druid.properties的文件
//3. 加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5.获取数据库连接 Connection
Connection connection = dataSource.getConnection();
}
//以下为配置文件 druid.properties 中设置的内容
driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1/db1?useSSL=false&useServerPrepStmts=true
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
6. 查询操作
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection connection = dataSource.getConnection();
String sql = "select * from tb_brand";
PreparedStatement pstmt = connection.prepareStatement(sql);
ResultSet resultSet = pstmt.executeQuery();
Brand brand = null;
List<Brand> brands = new ArrayList<Brand>();
while(resultSet.next()){
Integer Id = resultSet.getInt("id");
String bname = resultSet.getString("brand_name");
String cname = resultSet.getString("company_name");
Integer ord = resultSet.getInt("ordered");
String desc = resultSet.getString("description");
Integer sta = resultSet.getInt("status");
brand = new Brand();
brand.setId(Id);
brand.setBrandName(bname);;
brand.setCompanyName(cname);
brand.setDescription(desc);
brand.setStatus(sta);
brand.setOrdered(ord);
System.out.println(brand);
}
resultSet.close();
pstmt.close();
connection.close();
}
7. 插入操作
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection connection = dataSource.getConnection();
//现在先自定义数据模拟用户输入
String brandName = "分支名";
String companyName = "公司昵称";
int ordered = 1;
String desc = "文本描述";
int status = 1;
String sql2 = "insert into tb_brand(brand_name,company_name,ordered,description,status) value(?,?,?,?,?)";
PreparedStatement pstmt = connection.prepareStatement(sql2);
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,ordered);
pstmt.setString(4,desc);
pstmt.setInt(5,status);
int count = pstmt.executeUpdate();
if(count==1)System.out.println("插入成功啦...");
pstmt.close();
connection.close();
}
8. 修改操作
String brandName = "分支名";
String companyName = "公司昵称";
int ordered = 1;
String desc = "一些文本描述";
int status = 1;
int Id = 4;//修改ID = 4的用户信息
String sql3 = "update tb_brand set brand_name=?,company_name=?,ordered=?,description=?,status=? where id = ?";
PreparedStatement pstmt = connection.prepareStatement(sql3);
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,ordered);
pstmt.setString(4,desc);
pstmt.setInt(5,status);
pstmt.setInt(6,Id);
int count = pstmt.executeUpdate();
if(count==1)System.out.println("修改成功啦...");
9. 修改操作
String sql3 = "delete from tb_brand where id = 4";
PreparedStatement pstmt = connection.prepareStatement(sql3);
int count = pstmt.executeUpdate();
if(count==1)System.out.println("删除成功啦...");
pstmt.close();
connection.close();