一.JDBC简介
1.JDBC概念(一套标准接口)
JDB 就是使用JAVA 语言操作关系型数据库的一套API,全称:(Java DataBase Connectivity)Java数据库连接。
2.JDBC本质
- 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套接口编程,真正执行的代码是驱动jar包中的实现类
3.JDBC好处
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的java代码基本不变
二.操作实例
1.步骤
创建工程,导入驱动jar包
1.注册驱动
Class.forName(“com.mysql.jdbc.Driver”);
2.获取连接
Connection conn = DriverManager.getConnection(url,usename,password);
3.定义sql语句
String sql = “update…”;
4.获取执行SQL对象
Statement stmt = coon.createStatement();
5.执行SQL语句
stmt.executeUpdate(sql);
6.处理返回结果
7.释放资源
2.实例
package com.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBC {
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/test";
String username = "root";
String password = "**********";
Connection conn = DriverManager.getConnection(url,username,password);
//3.定义sql
String sql = "update student set no = 2022012020 where id = 1";
//4.获取执行SQL对象
Statement stmt = conn.createStatement();
//5.执行sql
int count = stmt.executeUpdate(sql);
//6.处理结果
System.out.println(count);
//7.释放资源
stmt.close();
conn.close();
}
}
三.JDBCAPI
1.DriverManager(驱动管理类)
- 注册驱动
Class.forName(“com.mysql.jdbc.Driver”);
Driver类源码
package com.mysql.cj.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
- 获取数据库连接
Connection conn = DriverManager.getConnection(url,usename,password);
- 参数
1.url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
示例:jdbc:mysql://127.0.0.1:3306/db1
2.user:用户名
3.password:密码
//1.注册驱动
//Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
String url = "jdbc:mysql:///test?useSSL=false";
2.Connection(数据库连接对象)
- 作用
1.获取执行SQL的对象
普通执行SQL对象
Statement createStatement()
预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
执行存储过程的对象
CallableStatement prepareCall(sql)
2.管理事务
- MySQL事务管理
- JDBC事务管理
//3.定义sql
String sql = "update student set no = 2022012020 where id = 1";
String sql1 = "update student set no = 2022012021 where id = 2";
//4.获取执行SQL对象
Statement stmt = conn.createStatement();
try {
//开启事务
conn.setAutoCommit(false);
//5.执行sql
int count = stmt.executeUpdate(sql);
//6.处理结果
System.out.println(count);
//5.执行sql
int count1 = stmt.executeUpdate(sql1);
//6.处理结果
System.out.println(count1);
//提交事务
conn.commit();
} catch (Exception e) {
//回滚事务
conn.rollback();
throw new RuntimeException(e);
}
//7.释放资源
stmt.close();
conn.close();
}
}
3.Statement
- 作用
1.执行SQL语句
int executeUpdate(sql):执行DML、DDL语句
返回值:(1)DML语句影响的行数 (2)DDL语句执行后,执行成功也可能返回0
package com.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JDBCAPIStatement {
public static void main(String[] args) throws Exception {
//1.注册驱动
//Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
String url = "jdbc:mysql:///test?useSSL=false";
String username = "root";
String password = "**********";
Connection conn = DriverManager.getConnection(url,username,password);
//3.定义sql
String sql = "update student set no = 2022012020 where id = 1";
//4.获取执行SQL对象
Statement stmt = conn.createStatement();
//5.执行sql
int count = stmt.executeUpdate(sql);
//6.处理结果
System.out.println(count);
if(count > 0){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
//7.释放资源
stmt.close();
conn.close();
}
}
ResultSet executeQuery(sql):执行DQL语句
返回值:ResultSet 结果集对象
4.ResultSe(结果集对象)
- 作用
1.封装了DQL查询语句的结果 ResultSet stmt.executeQuery(sql):执行DQL语句,返回ResultSet 对象
- 获取查询结果
boolean next(): (1)将光标从当前位置向前移动一行 (2)判断当前行是否为有效行
返回值:true:有效行,当前行有数据 false:无效行,当前行没有数据
xxx getXxx(参数):获取数据
xxx: 数据类型;如:int getInt(参数);String getString(参数)
参数:int:列的编号,从1开始 String:列的名称
package com.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCAPIResult {
public static void main(String[] args) throws Exception {
//1.注册驱动
//Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
String url = "jdbc:mysql:///test?useSSL=false";
String username = "root";
String password = "zhuxinyue99";
Connection conn = DriverManager.getConnection(url,username,password);
//3.定义sql
String sql = "select * from student";
//4.获取执行SQL对象
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);
//6.处理结果
//6.1光标向下移动一行,并且判断当前行是否有数据
while (rs.next()){
//6.2获取数据 getXxx
int id = rs.getInt(1);
String name = rs.getString(2);
double money = rs.getDouble(3);
System.out.println(id);
System.out.println(name);
System.out.println(money);
}
//7.释放资
rs.close();
stmt.close();
conn.close();
}
}
5.PrepareStatement
- 作用
预编译SQL语句并执行:性能更高
预防SQL注入问题:将敏感字符进行转译
SQL注入
SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
举例
用户登录密码,sql语句通过and相连接,输入密码时可以通过字符串拼接拆解and,借此返回ture,使sql语句有效
获取PreparedStatement对象
//SQL语句中的参数值,使用?占位符替代
String sql = “select * from user where usename = ?and password = ?”;
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
设置参数值
PrepareStatement对象:setXxx(参数1,参数2):给?赋值
Xxx:数据类型;如setInt(参数1,参数2)
参数:
参数1:?的位置编号,从1开始
参数2:?的值
执行SQL
executeUpdate(); : 不需要再传递sql
package com.jdbc;
import java.sql.*;
public class JDBCAPIPreparedStatement {
public static void main(String[] args) throws Exception {
//1.注册驱动
//Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接:如果连接的是本机mysql并且端口是默认的3306 可以简化书写
String url = "jdbc:mysql:///test?useSSL=false";
String username = "root";
String password = "zhuxinyue99";
Connection conn = DriverManager.getConnection(url,username,password);
String name = "zhangsan";
String paw = "' or '1' = '1";
//定义sql
String sql = "select * from user where username = ? and password = ?";
//获取执行SQL对象
PreparedStatement pstmt = conn.prepareStatement(sql);
//设置问号的值
pstmt.setString(1,name);
pstmt.setString(2,paw);
//执行sql
ResultSet rs = pstmt.executeQuery();
//判断是否登陆成功
if(rs.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
//释放资源
rs.close();
pstmt.close();
conn.close();
}
}
- 原理
< PrepareStatement 预编译功能开启:useServerPrepStmts=ture
< 配置MySQL执行日志(重启MySQL服务后生效)
log-output=FILE
general_log_file=“D:\mysql.log”
slow-query-log=1
slow_query_log_file=“D:\mysql_slow.log”
long_query_time=2
PreparedStatement 原理
- 1.在获取PreparedStatement 对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
- 2.执行时就不用再进行这些步骤了,速度很快
- 3.如果sql模板一样,则只需要进行一次检查编译
四.数据库连接池
1.数据库连接池简介
- 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
2.数据库连接池好处
- 资源重用
- 提升系统响应谏度
- 避免数据库连接溃漏
3.数据库连接池实现
-
标准接口:DataSource
•官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。
•功能:获取连接Connection getConnection()
-
常见的数据库连接池:
• DBCP
• СЗРО
• Druid -
Druid(德鲁伊)
• Druid连接池是阿里巴巴开源的数据库连接池项目
•功能强大,性能优秀,是Java语言最好的数据库连接池之一
Driud使用步骤
- 导入jar包driud-1.1.12jar
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
package com.jdbc.druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
public class Druiddemo {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3.加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-test/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"));
}
}