JDBC常用操作
JDBC
// JDBC连接mysql的一般步骤
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取连接
String url = "jdbc:mysql://127.0.0.1:3306/db1"; // 连接mysql下的db1数据库
String user = "用户名";
String password = "你的密码";
Connection conn = DriverManager.getConnection(url, user, password);
// 3. 定义SQL
String sql = "update account set money = 9888 where id = 1;";
// 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详解
Overview (Java SE 11 & JDK 11 ) (oracle.com)
DriverManager
- 注册驱动
Class.forName("com.mysql.jdbc.Driver");
- 提示:MySQL 5 之后的驱动包,可以省略注册驱动的步骤。
- 获取连接
static Connection getConnection(String url, String user, password)
// url是连接路径
// 语法
jdbc:mysql://ip地址:端口号/数据库名称?参数1&参数2...
// 示例:
jdbc:mysql://127.0.0.1:3306/db1
细节:
- 如果连接的是本机mysql服务器且默认端口是3306,则url简写为jdbc:mysql:///数据库名称?参数键值对
- 配置useSSL = false 参数,禁用安全连接方式,解决安全警告。
user和password分别是用户名和密码。
Connection
- 获取执行SQL的对象
- 普通执行SQL对象
Statement createStatement()
Statement对象执行的方法:
int executeUpdate(sql) // 执行DML、DDL语句
// 返回值
// 1. DML语句影响的行数
// 2. DDL语句执行后,执行成功也可能返回0,一般来说不发生异常即成功
ResultSet executeQuery(sql) // 执行DQL语句
// 返回值: ResultSet结果集对象
ResultSet对象
结果集对象:封装了DQL语句的结果
- 获取查询结果
boolean next() // 1. 将光标从当前位置向前移动一行
// 2. 判断当前行是否为有效行
// 返回值 true表示有效行, 当前行有数据; false表示无效行, 无数据
xxx getXxx() // 获取数据
// xxx表示数据类型; 如 int getInt(参数); String getString(参数)
// 参数:
// int: 列的编号,从1开始 (columnID)
// String: 列的名称 (columnLabel)
while(rs.next()) { // 判断是否有数据
rs.getXxx(参数); // 获取数据
}
// 记得最后rs.close()释放资源
- 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
PreparedStatement
SQL注入
比如在登录界面,攻击者利用sql注入使得通过特殊密码就可以登录成功。如下:
String sql = "select * from tb_user where username = '" + name + "' and password = '" + pwd + "'";
// 在输入密码的过程中使用sql注入
password = "' or '1' = '1";
输出该sql语句
select * from tb_user where username = '张飒' and password = '' or '1' = '1'
发现where字段永远为true, 这导致查询到数据库tb_user中的所有信息,由于信息存在,程序误认为用户身份合法,登陆成功,造成不必要损失。
预防SQL注入
使用PreparedStatement,好处:预编译SQL性能更高;通过将敏感字符转义的方式防止SQL注入
// 获取PreparedStatement对象
String sql = "select * from user where username = ? and password = ?"; // 参数位置用?代替
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置参数值, 问号索引从1开始 setXxx()
pstmt.setString(1, name);
pstmt.setString(2, pwd);
// 执行SQL, 不需要填sql语句
pstmt.executeUpdate(); 或者 pstmt.executeQuery();
原理:将参数中的敏感字符进行转义
如之前的sql注入,PreparedStatement会将原密码原封不动的保留,即对'
字符进行了转义。
预编译性能要更高,减少了编译次数。
预编译功能的开启:在url的参数中添加useServerPrepstmts=true
。
- 执行存储过程的对象
CallableStatement prepareCall(sql)
- 事务管理
- MySQL事务管理
开启事务: BEGIN; 或者 START TRANSACTION;
提交事务: COMMIT;
回滚事务: ROLLBACK;
- JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务: void setAutoCommit(boolean autoCommit)
当参数为true时自动提交, false为手动提交, 即开启事务。
提交事务: void commit()
回滚事务: void rollback()
// 事务练习
// 使用idea可以用快捷键ctrl+alt+t使得代码块被语句包裹
// 使用try catch 来处理异常
try {
// 开启事务
conn.setAutoCommit(false);
// 3. 定义SQL
String sql1 = "update account set money = 9888 where id = 1;";
String sql2 = "update account set money = 888 where id = 2;";
// 4. 获取执行sql的对象statement
stmt = conn.createStatement();
// 5. 执行sql
int count1 = stmt.executeUpdate(sql1); // 返回受影响行数
int exception = 3 / 0; // 除0异常
int count2 = stmt.executeUpdate(sql2); // 返回受影响行数
// 6. 处理结果
System.out.println(count1);
System.out.println(count2);
// 提交事务
conn.commit();
} catch (Exception e) {
System.out.println("出现异常....");
conn.rollback(); // 如果出现异常, 回滚事务
}
// 7. 释放资源
stmt.close();
conn.close();
数据库连接池
- 数据库连接池是一个容器,负责分配、管理数据库连接
- 允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 好处:资源重用;提升系统响应速度;避免数据库连接遗漏
连接池实现
-
标准接口:DataSource
- 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口;
- 功能:获取连接
Connection getConnection()
-
常见的数据库连接池
- DBCP
- C3P0
- Druid
-
Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一
Druid连接池的使用
- 导入jar包
地址:Central Repository: com/alibaba/druid/1.2.9 (maven.org)
- 定义配置文件
src目录下创建properties类型文件命名为druid
driverClassName=com.mysql.cj.Driver
url=jdbc:mysql:///db1?useServerPrepstmts=true
username=用户名
password=密码
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
# 更多详细配置可阅读官方文档
DruidDataSource配置属性列表 · alibaba/druid Wiki (github.com)
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
//1. 导入jar包
//2. 定义配置文件
//3. 加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("src/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5. 获取数据库连接Connection
Connection conn = dataSource.getConnection();
System.out.println(conn);
细节
idea快捷键:
ctrl + r 替换
alt + 鼠标左键 列调整
ctrl + alt + l 格式化代码
alt + insert 调用generate生成代码
alt + enter 快速修复
int有默认值0,如果与项目中值冲突,可以采用包装类Integer,采用对象传输。