第1章 JDBC的API
JDBC入门
1、搭建开发环境
2、编写程序,在程序中加载数据库驱动
3、建立连接
4、创建用于向数据库发送SQL的Statement对象
5、从代表结果集的ResultSet中取出数据
6、断开与数据库的连接,并释放相关资源
数据库:mysql
create database jdbctest;
use jdbctest;
create table user(
uid int primary key auto_increment,
username varchar(20),
password varchar(20),
name varchar(20)
);
insert into user values (null,'aaa','111','张三');
insert into user values (null,'bbb','222','李四');
insert into user values (null,'ccc','333','王五');
jar包:mysql-connector-java-8.0.16.jar
源码:
package com.imooc.jdbc.demo1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Logger;
import org.junit.Test;
import com.mysql.cj.jdbc.Driver;
public class JDBCDemo1 {
@Test
/**
* JDBC资源的释放
*/
public void demo2() {
Connection conn = null;
Statement stmt = null;
ResultSet resultset = null;
try {
// 1、加载驱动
// DriverManager.registerDriver(new Driver());//会导致驱动注册两次
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获得连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest ?serverTimezone=UTC", "root",
"zsn1003");
// 3、创建执行SQL语句的对象,并且执行SQL
// 3.1创建执行sql的对象
String sql = "select * from user";
stmt = conn.createStatement();
// 3.2执行sql
resultset = stmt.executeQuery(sql);
while (resultset.next()) {
int uid = resultset.getInt("uid");
String username = resultset.getString("username");
String password = resultset.getString("password");
String name = resultset.getString("name");
System.out.println(uid + " " + username + " " + password + " " + name);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 4、释放资源
if (resultset != null) {
try {
resultset.close();
} catch (SQLException sqlEx) {
}
resultset = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException sqlEx) {
}
conn = null;//垃圾回收机制要更早回收对象
}
}
}
}
DriverManager
DriverManager:驱动管理类
◆ 主要作用
◆ 一、注册驱动
◆ 实际开发中注册驱动会使用如下的方式:
class.forName("com.mysql.jdbc.Driver");
◆ 因为之前的方式会导致驱动注册两次
◆ 二、获得连接
◆ Connection getConnection(String url,String username,String password);
◆ url写法:jdbc:mysql://localhost:3306/jdbc
◆ jdbc:协议
◆ mysql:子协议
◆ localhost:主机名
◆ 3306:端口
◆ url简写:jdbc:mysql:///jdbc
Connection
Connection :连接对象
◆ 主要作用
◆ 一、创建执行SQL语句的对象
◆ Statement createStatement()
:执行SQL语句,有SQL注入的漏洞存在
◆ PreparedStatement PrepareStatement(String sql)
:预编译SQL语句,解决了SQL注入的漏洞
◆ CallableStatement PrepareCall(String sql)
:执行SQL中存储过程
◆ 二、进行事务管理
◆ setAutoCommit(boolean autoCommit)
:设置事务是否自动提交
◆ commit()
:事务提交
◆ rollback()
:事务回滚
Statement
Statement :执行SQL
◆ 主要作用
◆ 一、执行SQL语句
◆ boolean execute(String sql)
:执行SQL
◆ ResultSet execute(String sql)
:执行SQL中的select
◆ int executeUpdate(String sql)
:执行SQL中的insert/update/delete
◆ 二、执行批处理操作
◆ addBatch(String sql)
:添加到批处理
◆ executeBatch()
:执行批处理
◆ clearBatch()
:清空批处理
***ResultSet ***
ResultSet :结果集
◆ 结果集:其实就是查询语句(select)查询的结果的封装
◆ 主要作用
◆ 结果集获取查询到的结果的
◆ next()
◆ 针对不同的类型的数据可以使用getXXX()获取数据,通用获取数据的方法:getObject()
JDBC的资源释放
◆ Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResiltSet,Statement和Connection对象。
◆ 特别是Connection对象,它非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚的创建,尽量早的释放
第2章 JDBC的CRUD操作
保存代码的实现
1、向数据库中保存记录
2、修改数据库中的记录
3、删除数据库中的记录
4、查询数据库中的记录
package com.imooc.jdbc.demo1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
public class JDBCDemo2 {
@Test
/**
* 保存、修改和删除操作
*/
public void demo1() {
Connection conn = null;
Statement stmt = null;
try {
// 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获得连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest ?serverTimezone=UTC", "root",
"zsn1003");
// 获得执行SQL语句的对象
stmt = conn.createStatement();
// 编写SQL
//String sql = "insert into user values(null,'eee','123','张三')";//保存
//String sql = "update user set username='qqq',password='456',name='赵六' where uid=4";//修改
String sql = "delete from user where uid=4";//删除
// 执行SQL
int i = stmt.executeUpdate(sql);
if (i > 0) {
System.out.println("success!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
第3章 JDBC工具类的抽取
JDBC的工具类的抽取
为了简化JDBC的开发,可以将一些重复的代码进行提取。
package com.imooc.jdbc.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC的工具类
*
* @author Administrator
*
*/
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;
static {
driverClass = "com.mysql.cj.jdbc.Driver";
url = "jdbc:mysql://localhost:3306/jdbctest ?serverTimezone=UTC";
username = "root";
password = "zsn1003";
}
/**
* 注册驱动
*
* @throws ClassNotFoundException
*/
public static void loadDriver() throws ClassNotFoundException {
Class.forName(driverClass);
}
/**
* 获得连接的方法
*
* @throws Exception
*/
public static Connection getConnection() throws Exception {
loadDriver();
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
/**
* 资源释放
*/
public static void release(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
属性文件:jdbc.properties
driverClass = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/jdbctest?serverTimezone=UTC
username = root
password = zsn1003
static {
// driverClass = "com.mysql.cj.jdbc.Driver";
// url = "jdbc:mysql://localhost:3306/jdbctest ?serverTimezone=UTC";
// username = "root";
// password = "zsn1003";
// 加载属性文件并解析
Properties props = new Properties();
// 如何获得属性文件的输入流?
// 通常情况下使用类的加载器的方式进行获取
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driverClass = props.getProperty("driverClass");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
}
第4章 SQL注入漏洞
JDBC的SQL注入漏洞的演示
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
public class JDBCDemo4 {
@Test
/**
* 测试SQL注入漏洞的方法
*/
public void demo1() {
//boolean flag = JDBCDemo4.login("aaa'or'1=1", "qqqqqqqwewqe");
//boolean flag = JDBCDemo4.login("aaa' -- ", "qqqqqqqwewqe");
if (flag == true) {
System.out.println("ok");
} else {
System.out.println("no");
}
}
/**
* 演示JDBC的注入的漏洞
*
* @author Administrator
*
*/
public static boolean login(String username, String password) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
boolean flag = false;
try {
conn = JDBCUtils.getConnection();
stmt = conn.createStatement();
String sql = "select * from user where username='" + username + "' and password='" + password + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) {
flag = true;
} else {
flag = false;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(rs, stmt, conn);
}
return flag;
}
}
JDBC的SQL注入漏洞的解决
/**
* 避免JDBC的注入的漏洞
*/
public static boolean login2(String username, String password) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean flag = false;
try {
// 获得连接
conn = JDBCUtils.getConnection();
// 编写SQL
String sql = "select * from user where username= ? and password= ?";
// 预处理SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setString(1, username);
pstmt.setString(2, password);
// 执行SQL
rs = pstmt.executeQuery();
// 判断结果集
if (rs.next()) {
flag = true;
} else {
flag = false;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(rs, pstmt, conn);
}
return flag;
}
第5章 PreparedStatement的使用
PreparedStatement的使用:保存操作
package com.imooc.jdbc.demo2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.imooc.jdbc.utils.JDBCUtils;
/**
* PreparedStatement的使用
*
* @author Administrator
*
*/
public class JDBCDemo5 {
@Test
/**
* 保存数据
*/
public void demo1() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获得连接
conn = JDBCUtils.getConnection();
// 编写SQL
String sql = "insert into user values(null,?,?,?)";// 保存
// 预处理SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setString(1, "qqq");
pstmt.setString(2, "123");
pstmt.setString(3, "张五");
// 执行SQL
int i = pstmt.executeUpdate();
if (i > 0) {
System.out.println("yes");
} else {
System.out.println("no");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(pstmt, conn);
}
}
}
PreparedStatement的使用:修改操作
@Test
/**
* 修改数据
*/
public void demo2() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获得连接
conn = JDBCUtils.getConnection();
// 编写SQL
String sql = "update user set username= ?,password= ?,name= ? where uid= ?";// 修改
// 预处理SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setString(1, "qqq");
pstmt.setString(2, "123");
pstmt.setString(3, "张六");
pstmt.setInt(4, 6);
// 执行SQL
int i = pstmt.executeUpdate();
if (i > 0) {
System.out.println("yes");
} else {
System.out.println("no");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(pstmt, conn);
}
}
PreparedStatement的使用:删除操作
@Test
/**
* 删除数据
*/
public void demo3() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获得连接
conn = JDBCUtils.getConnection();
// 编写SQL
String sql = "delete from user where uid= ?";// 删除
// 预处理SQL
pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setInt(1, 6);
// 执行SQL
int i = pstmt.executeUpdate();
if (i > 0) {
System.out.println("yes");
} else {
System.out.println("no");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(pstmt, conn);
}
}
PreparedStatement的使用:查询操作
第6章 连接池C3P0
连接池的概述
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
C3P0连接池的使用
C3P0连接池的使用
jar包:c3p0-0.9.1.2.jar
手动设置连接池
@Test
/**
* 手动设置连接池
*/
public void demo1() {
// 创建连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获得连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 设置连接池的参数
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbctest?serverTimezone=UTC");
dataSource.setUser("root");
dataSource.setPassword("zsn1003");
dataSource.setMaxPoolSize(20);
dataSource.setInitialPoolSize(3);
// 获得连接
conn = dataSource.getConnection();
// 编写SQL
String sql = "select * from user";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
while (rs.next()) {
int uid = rs.getInt("uid");
String username = rs.getString("username");
String password = rs.getString("password");
String name = rs.getString("name");
System.out.println(uid + " " + username + " " + password + " " + name);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(rs, pstmt, conn);
}
}
使用配置文件
配置文件:c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbctest?serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">zsn1003</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
@Test
/**
* 使用配置文件的方式
*/
public void demo2() {
// 创建连接池
//ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获得连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获得连接
//conn = dataSource.getConnection();
conn = JDBCUtils2 .getConnection();
// 编写SQL
String sql = "select * from user";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 执行SQL
rs = pstmt.executeQuery();
while (rs.next()) {
int uid = rs.getInt("uid");
String username = rs.getString("username");
String password = rs.getString("password");
String name = rs.getString("name");
System.out.println(uid + " " + username + " " + password + " " + name);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(rs, pstmt, conn);
}
}
工具类修改
package com.imooc.jdbc.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* JDBC的工具类
*
* @author Administrator
*
*/
public class JDBCUtils2 {
private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();
/**
* 获得连接的方法
*
* @throws Exception
*/
public static Connection getConnection() throws Exception {
Connection conn = dataSource.getConnection();
return conn;
}
/**
* 资源释放
*/
public static void release(Statement stmt, Connection conn) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}