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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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 {@Testpublic 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 执行sqlString 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.Driverurl = jdbc:mysql:///jdbctestusername = 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 {@Testpublic void test() {ResultSet resultSet = null;Statement statement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils.getConnection();// 创建执行sql的对象statement = connection.createStatement();// 执行sqlString 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();// 编写sqlString sql = "select * from user where username = ? and password = ?";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 设置参数preparedStatement.setString(1, username);preparedStatement.setString(1, password);// 执行sqlresultSet = 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 {@Testpublic void test() {PreparedStatement preparedStatement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils.getConnection();// 编写sqlString sql = "insert into user values (null, ?, ?, ?)";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 设置参数preparedStatement.setString(1, "ccc");preparedStatement.setString(2, "333");preparedStatement.setString(3, "王五");// 执行sqlint 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 {@Testpublic void test() {PreparedStatement preparedStatement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils.getConnection();// 编写sqlString sql = "update user set username = ?, password = ?, name = ? where uid =?";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 设置参数preparedStatement.setString(1, "ddd");preparedStatement.setString(2, "444");preparedStatement.setString(3, "赵六");preparedStatement.setString(4, "4");// 执行sqlint 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 {@Testpublic void test() {PreparedStatement preparedStatement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils.getConnection();// 编写sqlString sql = "delete from user where uid = ?";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 设置参数preparedStatement.setString(1, "4");// 执行sqlint 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 {@Testpublic void test() {ResultSet resultSet = null;PreparedStatement preparedStatement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils.getConnection();// 编写sqlString sql = "select * from user where uid = ?";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 设置参数preparedStatement.setString(1, "2");// 执行sqlresultSet = 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 {@Testpublic 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();// 编写sqlString sql = "select * from user";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 执行sqlresultSet = 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 {@Testpublic void test() {ResultSet resultSet = null;PreparedStatement preparedStatement = null;Connection connection = null;try {// 获得连接connection = JDBCUtils2.getConnection();// 编写sqlString sql = "select * from user";// 预处理sqlpreparedStatement = connection.prepareStatement(sql);// 执行sqlresultSet = 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;}}}
