JDBC的概述
JDBC的全称是:Java DataBase Connectivity(Java数据库连接)
是一种用于执行sql语句的Java API,可以为多种关系型数据库提供统一的访问。
没有JDBC之前,Java操作数据库需要通过不同的驱动。
有了JDBC之后,Java操作数据库只需通过统一的JDBC标准即可。
使用JDBC前的准备工作:
第一步:右击项目名称,New/Directory/lib
第二步:在lib文件中存放mysql的连接文件(下载地址如下)
https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.11
第三步:关联mysql的连接文件到项目中
在IntelliJ IDEA 中选择File->Project Structure->Modules->Dependencies 点击下面的小加号,选择JARs or directories选择你要添加的外部jar包。
JDBC的API
模板案例
package com.song.jdbc;
import org.junit.Test;
import java.sql.*;
public class Demo1 {
@Test
public void test() {
try {
// 1. 注册驱动
// DriverManager.registerDriver(new Driver());
// 结果:不建议使用
// 理由:因为在加载Driver类的时候就会注册驱动,如果再手动注册一遍,会造成重复注册
Class.forName("com.mysql.cj.jdbc.Driver");
// 结果:建议使用
// 理由:意思是根据类名加载类的实例对象,不会造成重复注册
// 2. 获得连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "???");
// url说明:jdbc(协议) mysql(子协议) localhost(主机名) 3306(端口号)
// url简写:jdbc:mysql///jdbc <= 仅限于本地sql
// 3.1 创建执行sql的对象
Statement statement = connection.createStatement();
// 3.2 执行sql
String sql = "select * from user";
ResultSet resultSet = statement.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);
}
// 释放资源
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
DriverManager
驱动管理类
作用一:注册驱动
实际开发中注册驱动会使用如下方式,因为之前的方式会导致驱动注册两次
Class.forName("com.mysql.cj.jdbc.Driver");
作用二:获得连接
url说明:jdbc(协议) mysql(子协议) localhost(主机名) 3306(端口号)
url简写:jdbc:mysql///jdbc <= 仅限于本地sql
Connection connection = DriverManager.getConnection(String url, String username, String password)
Connection
连接对象类
作用一:创建执行sql语句的对象
Statement createStatement() : 执行sql语句,有sql注入的漏洞存在
PreparedStatement preparedStatement(String sql) : 预编译sql语句,解决sql注入的漏洞
callableStatement prepareCall(String sql) : 执行sql存储过程
作用二:进行事务的管理
setAutoCommit(boolean autoCommit) : 设置事务是否自动提交
commit() : 事务提交
rollback() : 事务回滚
Statement
sql执行类
作用一:执行sql语句
boolean execute(String sql) : 执行sql,执行select返回true,否则返回false
ResultSet executeQuery(String sql) : 执行sql中的select语句
int executeUpdate(String sql) : 执行sql中的insert/update/delete语句
作用二:执行批处理操作
addBatch(String sql) : 添加到批处理
executeBatch() : 执行批处理
clearBatch() : 清空批处理
ResultSet
结果集类,其实就是查询语句(select)的执行结果的封装
主要作用:获取查询结果
next() : 向前移动一行光标,并判断是否有数据
getXXX() : 针对不同类型获取数据
资源释放
JDBC程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet,Statement和Connection对象。
特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时,正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,早释放。
MySQL5中文参考手册.chm/26.连接器/26.3 之 finally部分
package com.song.jdbc;
import org.junit.Test;
import java.sql.*;
public class Demo1 {
@Test
public void test() {
ResultSet resultSet = null;
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "select * from user";
resultSet = statement.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) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
JDBC的增删改查操作
增删改用executeUpdate,查询用executeQuery
新增记录
package com.song.jdbc;
import org.junit.Test;
import java.sql.*;
public class Demo2 {
@Test
public void test() {
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "insert into user values (null, 'ccc', '333', '王五')";
int i = statement.executeUpdate(sql);
if (i > 0) {
System.out.println("保存成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
修改记录
package com.song.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo3 {
@Test
public void test() {
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "update user set username = 'ddd', password='444',name='赵六' where uid = 3";
int i = statement.executeUpdate(sql);
if (i > 0) {
System.out.println("修改成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
删除记录
package com.song.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo4 {
@Test
public void test() {
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "delete from user where uid = 3";
int i = statement.executeUpdate(sql);
if (i > 0) {
System.out.println("删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
查询记录
package com.song.jdbc;
import org.junit.Test;
import java.sql.*;
public class Demo5 {
@Test
public void test() {
ResultSet resultSet = null;
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "select * from user";
resultSet = statement.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) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
package com.song.jdbc;
import org.junit.Test;
import java.sql.*;
public class Demo5 {
@Test
public void test() {
ResultSet resultSet = null;
Statement statement = null;
Connection connection = null;
try {
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获得连接
connection = DriverManager.getConnection("jdbc:mysql:///jdbctest", "root", "???");
// 3.1 创建执行sql的对象
statement = connection.createStatement();
// 3.2 执行sql
String sql = "select * from user where uid = 2";
resultSet = statement.executeQuery(sql);
if (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) {
e.printStackTrace();
} finally {
// 4. 释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
JDBC的工具类
src/jdbc.properties
#右击src文件夹,New/file/jdbc.properties
driverClass = com.mysql.cj.jdbc.Driver
url = jdbc:mysql:///jdbctest
username = root;
password = ???
src/com.song.jdbc.utils
package com.song.jdbc.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;
static {
// 加载属性文件并解析
Properties props = new Properties();
// 如何获得属性文件的输入流?
// 通常情况下使用类的加载器的方式进行获取
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
driverClass = props.getProperty("driverClass");
url = props.getProperty("url");
username = props.getProperty("username");
password = props.getProperty("password");
}
// 注册驱动的方法
public static void loadDriver() throws ClassNotFoundException {
Class.forName(driverClass);
}
// 获得连接的方法
public static Connection getConnection() throws Exception {
loadDriver();
Connection connection = DriverManager.getConnection(url, username, password);
return connection;
}
// 资源释放
public static void release(Statement statement, Connection connection) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
src/com.song.jdbc.demo
package com.song.jdbc.demo;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.*;
public class Demo6 {
@Test
public void test() {
ResultSet resultSet = null;
Statement statement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 创建执行sql的对象
statement = connection.createStatement();
// 执行sql
String sql = "select * from user where uid = 2";
resultSet = statement.executeQuery(sql);
if (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) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, statement, connection);
}
}
}
JDBC的SQL注入防御
PreparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatenebt(sql)方法获得,相对于Statement对象而言:
- PreparedStatement可以避免SQL注入的问题
- Statement会使数据库频繁变异SQL,可能造成数据库缓存区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率
- 并且PreparedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写
public static void login(String username, String password) {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 编写sql
String sql = "select * from user where username = ? and password = ?";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1, username);
preparedStatement.setString(1, password);
// 执行sql
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, preparedStatement, connection);
}
}
PreparedStatement
新增记录
package com.song.jdbc.demo;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Demo8 {
@Test
public void test() {
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 编写sql
String sql = "insert into user values (null, ?, ?, ?)";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1, "ccc");
preparedStatement.setString(2, "333");
preparedStatement.setString(3, "王五");
// 执行sql
int num = preparedStatement.executeUpdate();
if (num >0) {
System.out.println("新增成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(preparedStatement, connection);
}
}
}
修改记录
package com.song.jdbc.demo;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Demo8 {
@Test
public void test() {
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 编写sql
String sql = "update user set username = ?, password = ?, name = ? where uid =?";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1, "ddd");
preparedStatement.setString(2, "444");
preparedStatement.setString(3, "赵六");
preparedStatement.setString(4, "4");
// 执行sql
int num = preparedStatement.executeUpdate();
if (num >0) {
System.out.println("修改成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(preparedStatement, connection);
}
}
}
删除记录
package com.song.jdbc.demo;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class Demo9 {
@Test
public void test() {
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 编写sql
String sql = "delete from user where uid = ?";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1, "4");
// 执行sql
int num = preparedStatement.executeUpdate();
if (num >0) {
System.out.println("删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(preparedStatement, connection);
}
}
}
查询记录
package com.song.jdbc.demo;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.*;
public class Demo7 {
@Test
public void test() {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils.getConnection();
// 编写sql
String sql = "select * from user where uid = ?";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 设置参数
preparedStatement.setString(1, "2");
// 执行sql
resultSet = preparedStatement.executeQuery();
if (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) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, preparedStatement, connection);
}
}
}
连接池C3P0
连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。
第一步:在lib文件中存放C3P0的jar包(以下网页的资料里有)
https://class.imooc.com/course/721
第二步:引入C3P0连接池到项目中
在IntelliJ IDEA 中选择File->Project Structure->Modules->Dependencies 点击下面的小加号,选择JARs or directories选择你要添加的外部jar包。
使用1:
#以下代码有个问题,每次执行Demo10的时候,就会创建一个连接池对象,这样是很浪费的。应该抽取出连接方法成static,这样就将只会创建一个连接池对象了,请看使用2。
package com.song.jdbc.demo;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.song.jdbc.utils.JDBCUtils;
import org.junit.Test;
import java.sql.*;
public class Demo10 {
@Test
public void test() {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 创建连接池
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
// 设置连接池的参数
comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
comboPooledDataSource.setJdbcUrl("jdbc:mysql:///jdbctest");
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("???");
comboPooledDataSource.setMaxPoolSize(20);
comboPooledDataSource.setInitialPoolSize(3);
// 获得连接
connection = comboPooledDataSource.getConnection();
// 编写sql
String sql = "select * from user";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 执行sql
resultSet = preparedStatement.executeQuery();
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) {
e.printStackTrace();
} finally {
JDBCUtils.release(resultSet, preparedStatement, connection);
}
}
}
使用2:配置化
package com.song.jdbc.demo;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.song.jdbc.utils.JDBCUtils2;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Demo11 {
@Test
public void test() {
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
Connection connection = null;
try {
// 获得连接
connection = JDBCUtils2.getConnection();
// 编写sql
String sql = "select * from user";
// 预处理sql
preparedStatement = connection.prepareStatement(sql);
// 执行sql
resultSet = preparedStatement.executeQuery();
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) {
e.printStackTrace();
} finally {
JDBCUtils2.release(resultSet, preparedStatement, connection);
}
}
}
配置文件:src/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:///jdbctest</property>
<property name="user">root</property>
<property name="password">???</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
</c3p0-config>
工具类:src/com.song.jdbc/utils/JDBCUtils2:
package com.song.jdbc.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.*;
public class JDBCUtils2 {
private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 获得连接的方法
public static Connection getConnection() throws Exception {
Connection connection = dataSource.getConnection();
return connection;
}
// 资源释放
public static void release(Statement statement, Connection connection) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
public static void release(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}