一、概述
JDBC( 为访问不同的数据库提供了统一的接口 , 为使用者屏蔽了细节问题 。
Java 程序员使用 JDBC, 可以连接任何提供了JDBC( 驱动程序的数据库系统 , 从而完成对数据库的各种操作 。
1.JDBC的基本原理图 [重要]

JDBC接口:
| |
| |
| |
| |
| |
| public interface JdbcInterface { |
| |
| |
| |
| |
| |
| Object getConnection(); |
| |
| |
| |
| |
| void crud(); |
| |
| |
| |
| |
| void close(); |
| } |
实现类:
| |
| |
| |
| |
| |
| public class MysqlJdbcImpl implements JdbcInterface { |
| |
| |
| |
| |
| |
| @Override |
| public Object getConnection() { |
| return "得到Mysql连接"; |
| } |
| |
| |
| |
| |
| @Override |
| public void crud() { |
| System.out.println("实现数据的增删改查"); |
| } |
| |
| |
| |
| |
| @Override |
| public void close() { |
| System.out.println("关闭连接"); |
| } |
| } |
测试:
| public class Test { |
| public static void main(String[] args) { |
| |
| JdbcInterface jdbcInterface = new MysqlJdbcImpl(); |
| |
| jdbcInterface.getConnection(); |
| |
| jdbcInterface.crud(); |
| |
| jdbcInterface.close(); |
| } |
| } |
2.JDBC带来的好处
JDBC是Java提供一套用于数据库操作的接口 API,Java程序员只需要面向这套接口编程即可。 不同的数据库厂商 , 需要针对这套接口 , 提供不同实现 。
3.JDBC API


二、JDBC快速入门
1.使用步骤
| # 注册驱动 - 加载Driver 类 |
| # 获取连接 - 得到 Connection |
| # 执行增删改查 - 发送SQL给mysql 执行 |
| # 释放资源 - 关闭相关连接 |
2.模拟 JDBC

完整代码:
| |
| |
| |
| |
| |
| public class Test { |
| public static void main(String[] args) throws SQLException { |
| |
| |
| |
| |
| |
| |
| Driver driver = new Driver(); |
| |
| |
| String url = "jdbc:mysql://localhost:3306/hsp_jdbc"; |
| |
| Properties properties = new Properties(); |
| |
| |
| |
| |
| |
| properties.setProperty("user", "root"); |
| |
| properties.setProperty("password", "123456"); |
| |
| Connection connection = driver.connect(url, properties); |
| |
| |
| String sql = "insert into actor values(null,'张三','男','2000-09-07','110')"; |
| |
| Statement statement = connection.createStatement(); |
| |
| int rows = statement.executeUpdate(sql); |
| System.out.println(rows > 0 ? "sql执行成功" : "sql执行失败"); |
| |
| statement.close(); |
| connection.close(); |
| } |
| } |
3.获取数据库连接的 5 种方式
3-1.方式一,使用Driver对象
| |
| |
| |
| |
| |
| public class Manner1 { |
| public static void main(String[] args) throws SQLException { |
| |
| Driver driver = new Driver(); |
| |
| String url="jdbc:mysql://localhost:3306/hsp_jdbc"; |
| |
| Properties properties = new Properties(); |
| |
| properties.setProperty("user","root"); |
| |
| properties.setProperty("password","123456"); |
| |
| Connection connect = driver.connect(url, properties); |
| } |
| } |
缺点:
- 会直接使用com.mysql.jdbc.Driver(),属于静态加载,灵活性差,依赖强
3-2.方式二,减少依赖增强灵活性
| |
| |
| |
| |
| |
| public class Manner2 { |
| public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { |
| |
| Class<?> aClass = Class.forName("com.mysql.jdbc.Driver"); |
| Driver driver = (Driver) aClass.newInstance(); |
| |
| String url = "jdbc:mysql://localhost:3306/hsp_jdbc"; |
| |
| Properties properties = new Properties(); |
| |
| properties.setProperty("user", "root"); |
| |
| properties.setProperty("password", "123456"); |
| |
| Connection connect = driver.connect(url, properties); |
| } |
| } |
3-3.方式三,使用DriverManager替代Driver进行统一管理
| |
| |
| |
| |
| |
| public class Manner3 { |
| public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { |
| |
| Class<?> aClass = Class.forName("com.mysql.jdbc.Driver"); |
| Driver driver = (Driver) aClass.newInstance(); |
| |
| String url = "jdbc:mysql://localhost:3306/hsp_jdbc"; |
| String user = "root"; |
| String password = "123456"; |
| |
| DriverManager.registerDriver(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| } |
| } |
缺点:
3-4.使用Class.forName自动完成注册驱动,简化代码(推荐使用)
| |
| |
| |
| |
| |
| public class Manner4 { |
| public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { |
| |
| Class.forName("com.mysql.jdbc.Driver"); |
| |
| String url = "jdbc:mysql://localhost:3306/hsp_jdbc"; |
| String user = "root"; |
| String password = "123456"; |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| } |
| } |
补充:
| - mysqL 驱动5.1.6以后可以无需 CLass.forName("com.mysql.jdbc.Driver"); |
| - 从 jdk1.5以后使用了 jdbc4,不再需要显示调用 class.forName() 注册驱动而是自动调用驱动jar包下 META-INF\services\java.sql.Driver 文本中的类名称去注册 |
# 建议还是写上 CLass.forName("com.mysql.jdbc.Driver"), 更加明确
3-5.使用配置文件,连接数据库更灵活
jdbc.properties:
| url=jdbc:mysql://localhost:3306/hsp_jdbc |
| user=root |
| password=123456 |
| driver=com.mysql.jdbc.Driver |
Manner5:
| |
| |
| |
| |
| |
| public class Manner5 { |
| public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { |
| |
| Properties properties = new Properties(); |
| |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| |
| String user = properties.getProperty("user"); |
| |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| String url = properties.getProperty("url"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| } |
| } |
4.创建、插入、修改、删除(练习)
题目:

| |
| |
| |
| |
| |
| public class Manner5 { |
| public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { |
| |
| Properties properties = new Properties(); |
| |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| |
| String user = properties.getProperty("user"); |
| |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| String url = properties.getProperty("url"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| |
| |
| String createSql = "create table news (id int not null primary key auto_increment," + |
| "content varchar(100)" + |
| ")"; |
| |
| String insertSql = "insert into news values(null,'dyt')," + |
| "(null,'det')," + |
| "(null,'dst')," + |
| "(null,'dsit')," + |
| "(null,'dwt')"; |
| |
| String updateSql = "update news set content='news' where id=1"; |
| |
| String deleteSql = "delete from news where id=3"; |
| |
| Statement statement = connection.createStatement(); |
| |
| statement.executeUpdate(createSql); |
| int insert = statement.executeUpdate(insertSql); |
| System.out.println(insert > 0 ? "sql执行成功" : "sql执行失败"); |
| int update = statement.executeUpdate(updateSql); |
| System.out.println(update > 0 ? "sql执行成功" : "sql执行失败"); |
| int delete = statement.executeUpdate(deleteSql); |
| System.out.println(delete > 0 ? "sql执行成功" : "sql执行失败"); |
| |
| statement.close(); |
| connection.close(); |
| } |
| } |
三、ResultSet[结果集]
1.基本介绍
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
ResultSet 对象保持一个光标指向其当前的数据行 。 最初,光标位于第一行之前
next() 方法将光标移动到下一行 , 并且由于在 ResultSet 对象中没有更多行时返回false ,因此可以在 while 循环中使用循环来遍历结果集


2.应用实例:

| |
| |
| |
| |
| |
| public class Result { |
| public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException { |
| |
| Properties properties = new Properties(); |
| |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| |
| String user = properties.getProperty("user"); |
| |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| String url = properties.getProperty("url"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| |
| Statement statement = connection.createStatement(); |
| |
| |
| String selectSql = "select id,name,sex,borndate from actor"; |
| |
| ResultSet resultSet = statement.executeQuery(selectSql); |
| |
| while (resultSet.next()) { |
| |
| int id = resultSet.getInt(1); |
| String name = resultSet.getString(2); |
| String sex = resultSet.getString(3); |
| Date borndate = resultSet.getDate(4); |
| System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate); |
| } |
| |
| resultSet.close(); |
| statement.close(); |
| connection.close(); |
| } |
| } |
四、Statement
1.基本介绍
Statement 对象用于执行静态 SQL 语句并返回其生成的结果的对象
在连接建立后 , 需要对数据库进行访问 , 执行 命名或是 SQL 语句,可以通过
| - Statement [ 存在 SQL 注入 ] |
| - PreparedStatement [ 预处理 ] |
| - CaIIabIeStatement [ 存储过程 ] |
Statement 对象执行 SQL 语句 ,存在 SQL 注入风险

例:
| select * from admin where `name`='1' or 'and pwd=' or '1'='1'; |
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查 , 而在用户输
入数据中注入非法的 SQL 语句段或命令 , 恶意攻击数据库 。
要防范 SQL 注入 , 只要用 PreparedStatement( 从 Statement 扩展而来 ) 取
代 Statement 就可以了
2.java程序模拟SQL注入:
| |
| |
| |
| |
| |
| public class Statement { |
| public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException { |
| Scanner input = new Scanner(System.in); |
| System.out.print("请输入用户名:"); |
| |
| |
| String name = input.nextLine(); |
| System.out.print("请输入密码:"); |
| String pwd = input.nextLine(); |
| |
| Properties properties = new Properties(); |
| |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| |
| String user = properties.getProperty("user"); |
| |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| String url = properties.getProperty("url"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| |
| java.sql.Statement statement = connection.createStatement(); |
| |
| |
| String selectSql = "select name,pwd from admin where name='" + name + "'and pwd='" + pwd + "'"; |
| |
| ResultSet resultSet = statement.executeQuery(selectSql); |
| if (resultSet.next()) { |
| System.out.println("登录成功!"); |
| } else { |
| System.out.println("登录失败!"); |
| } |
| |
| resultSet.close(); |
| statement.close(); |
| connection.close(); |
| } |
| } |
终端:
| 请输入用户名:1' or |
| 请输入密码: or '1'='1 |
五、PreparedStatement
1.基本介绍
PreparedStatement 执行的 SQL 语句中的参数用问号 (?)来表示 ,调用PreparedStatement 对象的 setXxx()方法来设置这些参数.setXxx()方法有两个参数 ,第一个参数是要设置的 SQL 语句中的参数的索引( 从 1 开始 ), 第二个是设置的 SQL 语句中的参数的值
调用 executeQuery() , 返回 ResuItSet 对象
调用 executeUpdate() :执行更新 ,包括增 、删 、修改
2.预处理的好处
| * 不再使用 + 拼接 sql 语句 , 减少语法错误 |
| * 有效的解决了 sql 注入问题 ! |
| * 大大减少了编译次数 , 效率较高 |
3.应用实例:
| |
| |
| |
| |
| |
| public class PerparStatement { |
| public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException { |
| Scanner input = new Scanner(System.in); |
| System.out.print("请输入用户名:"); |
| |
| |
| String name = input.nextLine(); |
| System.out.print("请输入密码:"); |
| String pwd = input.nextLine(); |
| |
| Properties properties = new Properties(); |
| |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| |
| String user = properties.getProperty("user"); |
| |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| String url = properties.getProperty("url"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| |
| |
| String selectSql = "select name,pwd from admin where name=? and pwd=?"; |
| |
| PreparedStatement preparedStatement = connection.prepareStatement(selectSql); |
| |
| preparedStatement.setString(1, name); |
| preparedStatement.setString(2, pwd); |
| |
| |
| |
| |
| |
| |
| ResultSet resultSet = preparedStatement.executeQuery(); |
| if (resultSet.next()) { |
| System.out.println("登录成功!"); |
| } else { |
| System.out.println("登录失败!"); |
| } |
| |
| resultSet.close(); |
| preparedStatement.close(); |
| connection.close(); |
| } |
| } |
4.使用PerparedStatement创建、插入、修改、删除、查询(练习)
题目:

| |
| |
| |
| |
| |
| public class PerparedStatementDml { |
| public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { |
| Scanner scanner = new Scanner(System.in); |
| |
| Properties properties = new Properties(); |
| properties.load(new FileInputStream("src/com/hspedu/myjdbc/demo3/resource/jdbc.properties")); |
| String url = properties.getProperty("url"); |
| String user = properties.getProperty("user"); |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| |
| Class.forName(driver); |
| |
| Connection connection = DriverManager.getConnection(url, user, password); |
| |
| |
| String createSql = "create table admin (id int not null primary key auto_increment,username varchar(10),pwd varchar(10))"; |
| int createTable = connection.prepareStatement(createSql).executeUpdate(); |
| |
| String insertSql = "insert into admin values(null,?,?)"; |
| System.out.print("请输入用户名:"); |
| String username = scanner.nextLine(); |
| System.out.print("请输入密码:"); |
| String pwd = scanner.nextLine(); |
| PreparedStatement insPs = connection.prepareStatement(insertSql); |
| insPs.setString(1, username); |
| insPs.setString(2, pwd); |
| int insertData = insPs.executeUpdate(); |
| System.out.println(insertData > 0 ? "插入数据成功" : "执行失败!"); |
| |
| String updateSql = "update admin set username=? where username=?"; |
| System.out.print("请输入需要修改的用户名:"); |
| String oldname = scanner.nextLine(); |
| System.out.print("请输入新的用户名:"); |
| String newname = scanner.nextLine(); |
| PreparedStatement updPs = connection.prepareStatement(updateSql); |
| updPs.setString(1, newname); |
| updPs.setString(2, oldname); |
| int updateData = updPs.executeUpdate(); |
| System.out.println(updateData > 0 ? "更新数据成功" : "执行失败!"); |
| |
| String deleteSql = "delete from admin where id=?"; |
| System.out.print("请输入需要删除的id:"); |
| int id = scanner.nextInt(); |
| PreparedStatement delPs = connection.prepareStatement(deleteSql); |
| delPs.setInt(1, id); |
| int deleteData = delPs.executeUpdate(); |
| System.out.println(deleteData > 0 ? "删除记录成功" : "执行失败!"); |
| |
| String selectSql = "select id,username,pwd from admin"; |
| ResultSet resultSet = connection.prepareStatement(selectSql).executeQuery(); |
| while (resultSet.next()) { |
| int ids = resultSet.getInt(1); |
| String usernames = resultSet.getString(2); |
| String pwds = resultSet.getString(3); |
| System.out.println(ids + "\t" + usernames + "\t" + pwds); |
| } |
| } |
| } |
六、封装 JDBCUtils
1.说明
在jdbc操作中 ,获取连接和释放资源是经常使用到 ,可以将其封装成JDBC连接数据库的工具类 (JdbcUtiIs)

2.实际使用使用工具类 JDBCUtils
2-1.JdbcUtils
| |
| |
| |
| |
| |
| public class JdbcUtils { |
| |
| |
| private static String user; |
| |
| private static String password; |
| |
| private static String url; |
| |
| private static String driver; |
| |
| |
| static { |
| |
| Properties properties = new Properties(); |
| try { |
| |
| properties.load(new FileInputStream("src/com/hspedu/resource/jdbc.properties")); |
| |
| user = properties.getProperty("user"); |
| |
| password = properties.getProperty("password"); |
| |
| url = properties.getProperty("url"); |
| |
| driver = properties.getProperty("driver"); |
| } catch (IOException e) { |
| |
| |
| |
| |
| |
| throw new RuntimeException(e); |
| } |
| } |
| |
| |
| public static Connection getConnection() { |
| try { |
| return DriverManager.getConnection(url, user, password); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| public static void close(ResultSet resultSet, Statement statement, Connection connection) { |
| |
| try { |
| if (resultSet != null) { |
| resultSet.close(); |
| } |
| if (statement != null) { |
| statement.close(); |
| } |
| if (connection != null) { |
| connection.close(); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
2-2.更新记录
| |
| |
| |
| public static void upDate() { |
| |
| Connection connection = null; |
| |
| PreparedStatement preparedStatement = null; |
| |
| String updateSql = "update actor set name=? where id=?"; |
| try { |
| |
| connection = JdbcUtils.getConnection(); |
| |
| preparedStatement = connection.prepareStatement(updateSql); |
| |
| preparedStatement.setString(1, "志昂"); |
| preparedStatement.setInt(2, 2); |
| |
| int update = preparedStatement.executeUpdate(); |
| System.out.println(update > 0 ? "更新记录成功" : "执行失败"); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
2-3.插入记录
| |
| |
| |
| public static void inSert() { |
| Scanner scanner = new Scanner(System.in); |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| String insertSql = "insert into admin values(null,?,?)"; |
| try { |
| connection = JdbcUtils.getConnection(); |
| preparedStatement = connection.prepareStatement(insertSql); |
| boolean flag = true; |
| while (flag) { |
| System.out.print("请输入用户名:"); |
| String user = scanner.nextLine(); |
| preparedStatement.setString(1, user); |
| System.out.print("请输入密码"); |
| String pwd = scanner.nextLine(); |
| preparedStatement.setString(2, pwd); |
| int insert = preparedStatement.executeUpdate(); |
| System.out.println(insert > 0 ? "插入记录成功" : "执行失败"); |
| System.out.print("是否继续添加记录(y/n):"); |
| String w = scanner.next(); |
| if (!"y".equals(w)) { |
| flag = false; |
| } |
| String dubug = scanner.nextLine(); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
2-4.删除记录
| |
| |
| |
| public static void delEte() { |
| Scanner scanner = new Scanner(System.in); |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| String deleteSql = "delete from admin where username=?"; |
| try { |
| connection = JdbcUtils.getConnection(); |
| preparedStatement = connection.prepareStatement(deleteSql); |
| System.out.print("请输入需要删除的用户名:"); |
| String user = scanner.nextLine(); |
| preparedStatement.setString(1, user); |
| int delete = preparedStatement.executeUpdate(); |
| System.out.println(delete > 0 ? "删除记录成功" : "执行失败"); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
2-5.查询记录
| |
| |
| |
| public static void selEct() { |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| ResultSet resultSet = null; |
| String selectSql = "select id,username,pwd from admin"; |
| try { |
| connection = JdbcUtils.getConnection(); |
| preparedStatement = connection.prepareStatement(selectSql); |
| resultSet = preparedStatement.executeQuery(); |
| while (resultSet.next()) { |
| int id = resultSet.getInt(1); |
| String username = resultSet.getString(2); |
| String pwd = resultSet.getString(3); |
| System.out.println(id + "\t" + username + "\t" + pwd); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(resultSet, preparedStatement, connection); |
| } |
| } |
七、数据库连接池
1.传统获取Connection 问题分析
传统的JDBC数据库连接使用 DriverManager 来获取 ,每次向数据库建立连接的时候都要将 Connection 加载到内存中, 再验证IP地址、用户名和密码。需要数据库连接的时候,就向数据库要求一个 ,频繁的进行数据库连接操作将占用很多的系统资源 ,容易造成服务器崩溃 。
每一次数据库连接 ,使用完后都得断开 ,如果程序出现异常而未能关闭 ,将导致数据库内存泄漏 ,最终将导致重启数据库 。
传统获取连接的方式 ,不能控制创建的连接数量 ,如连接过多 ,也可能导致内存泄漏 ,MySQL崩溃 。
解决传统开发中的数据库连接问题 ,可以采用数据库连接池技术(connection pool)
数据库连接池种类
| - 1.JDBC 的数据库连接池使用 javax.sqI.DataSource 来表示 ,DataSource只是一个接口 ,该接口通常由第三方提供实现[提供.jar] |
| - 2.C3P0数据库连接池速度相对较慢稳定性不错 (hibernate, spring) |
| - 3.DBCP数据库连接池,速度相对C3P0较快 ,但不稳定 |
| - 4.Proxool数据库连接池 ,有监控连接池状态的功能 ,稳定性较C3P0差一点 |
| - 5.BoneCP 数据库连接池速度快 |
| - 6.Druid( 德鲁伊 )是阿里提供的数据库连接池 ,集 DBCP 、C3P0 、Proxool优点于一身的库连接池 |

2.C3P0应用实例
2-1.相关参数,在程序中指定 user, url , password 等
| public void testC3P0_One() throws IOException, PropertyVetoException, SQLException { |
| |
| ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); |
| |
| Properties properties = new Properties(); |
| properties.load(new FileInputStream("src/com/hspedu/resource/jdbc.properties")); |
| |
| String url = properties.getProperty("url"); |
| String user = properties.getProperty("user"); |
| String password = properties.getProperty("password"); |
| String driver = properties.getProperty("driver"); |
| |
| |
| comboPooledDataSource.setJdbcUrl(url); |
| comboPooledDataSource.setDriverClass(driver); |
| comboPooledDataSource.setUser(user); |
| comboPooledDataSource.setPassword(password); |
| |
| comboPooledDataSource.setInitialPoolSize(10); |
| |
| comboPooledDataSource.setMaxPoolSize(50); |
| |
| Connection connection = comboPooledDataSource.getConnection(); |
| connection.close(); |
| } |
2-2.使用配置文件模板来完成
前置操作
1.将C3P0的配置文件放到src目录下
2.设置配置文件的相关信息
c3p0-config.xml:
| <c3p0-config> |
| |
| <named-config name="hsp_jdbc"> |
| |
| <property name="driverClass">com.mysql.jdbc.Driver</property> |
| |
| <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/hsp_jdbc</property> |
| |
| <property name="user">root</property> |
| |
| <property name="password">123456</property> |
| |
| <property name="acquireIncrement">5</property> |
| |
| <property name="initialPoolSize">10</property> |
| |
| <property name="minPoolSize">5</property> |
| |
| <property name="maxPoolSize">10</property> |
| |
| |
| <property name="maxStatements">5</property> |
| |
| |
| <property name="maxStatementsPerConnection">2</property> |
| </named-config> |
| </c3p0-config> |
| public void testC3P0_Two() throws SQLException { |
| ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("hsp_jdbc"); |
| Connection connection = comboPooledDataSource.getConnection(); |
| connection.close(); |
| } |
3.Druid(德鲁伊)应用实例
前置操作
1.导入Druid.jar
2.将配置文件导入到src目录下
druid.properties:
| |
| driverClassName=com.mysql.jdbc.Driver |
| url=jdbc:mysql://localhost:3306/hsp_jdbc?rewriteBatchedStatements=true |
| |
| username=root |
| password=123456 |
| |
| initialSize=10 |
| |
| minIdle=5 |
| |
| maxActive=20 |
| |
| maxWait=5000 |
| public void test() throws Exception { |
| |
| Properties properties = new Properties(); |
| properties.load(new FileInputStream("src/druid.properties")); |
| |
| DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); |
| Connection connection = dataSource.getConnection(); |
| connection.close(); |
| } |
八、将 JDBCUtils 工具类改成Druid(德鲁伊)实现
通过德鲁伊数据库连接池获取连接对象
| |
| |
| |
| |
| |
| public class JdbcUtilsByDruid { |
| |
| private static DataSource dataSource; |
| |
| |
| static { |
| |
| Properties properties = new Properties(); |
| |
| try { |
| properties.load(new FileInputStream("src/druid.properties")); |
| dataSource = DruidDataSourceFactory.createDataSource(properties); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| |
| public static Connection getConnection() throws SQLException { |
| return dataSource.getConnection(); |
| } |
| |
| |
| |
| |
| |
| |
| public static void close(ResultSet resultSet, Statement statement, Connection connection) { |
| try { |
| if (resultSet != null) { |
| |
| resultSet.close(); |
| |
| } |
| if (statement != null) { |
| statement.close(); |
| } |
| if (connection != null) { |
| connection.close(); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| } |
1.实际使用使用工具类 JDBCUtilsByDruid
1-1.更新记录
| |
| |
| |
| public static void upDate() { |
| |
| Connection connection = null; |
| |
| PreparedStatement preparedStatement = null; |
| |
| String updateSql = "update actor set name=? where id=?"; |
| try { |
| |
| connection = JdbcUtilsByDruid.getConnection(); |
| |
| preparedStatement = connection.prepareStatement(updateSql); |
| |
| preparedStatement.setString(1, "志昂"); |
| preparedStatement.setInt(2, 2); |
| |
| int update = preparedStatement.executeUpdate(); |
| System.out.println(update > 0 ? "更新记录成功" : "执行失败"); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
1-2.插入记录
| |
| |
| |
| public static void inSert() { |
| Scanner scanner = new Scanner(System.in); |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| String insertSql = "insert into admin values(null,?,?)"; |
| try { |
| connection = JdbcUtilsByDruid.getConnection(); |
| preparedStatement = connection.prepareStatement(insertSql); |
| boolean flag = true; |
| while (flag) { |
| System.out.print("请输入用户名:"); |
| String user = scanner.nextLine(); |
| preparedStatement.setString(1, user); |
| System.out.print("请输入密码"); |
| String pwd = scanner.nextLine(); |
| preparedStatement.setString(2, pwd); |
| int insert = preparedStatement.executeUpdate(); |
| System.out.println(insert > 0 ? "插入记录成功" : "执行失败"); |
| System.out.print("是否继续添加记录(y/n):"); |
| String w = scanner.next(); |
| if (!"y".equals(w)) { |
| flag = false; |
| } |
| String dubug = scanner.nextLine(); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
1-3.删除记录
| |
| |
| |
| public static void delEte() { |
| Scanner scanner = new Scanner(System.in); |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| String deleteSql = "delete from admin where username=?"; |
| try { |
| connection = JdbcUtilsByDruid.getConnection(); |
| preparedStatement = connection.prepareStatement(deleteSql); |
| System.out.print("请输入需要删除的用户名:"); |
| String user = scanner.nextLine(); |
| preparedStatement.setString(1, user); |
| int delete = preparedStatement.executeUpdate(); |
| System.out.println(delete > 0 ? "删除记录成功" : "执行失败"); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(null, preparedStatement, connection); |
| } |
| } |
1-4.查询记录
| |
| |
| |
| public static void selEct() { |
| Connection connection = null; |
| PreparedStatement preparedStatement = null; |
| ResultSet resultSet = null; |
| String selectSql = "select id,username,pwd from admin"; |
| try { |
| connection = JdbcUtilsByDruid.getConnection(); |
| preparedStatement = connection.prepareStatement(selectSql); |
| resultSet = preparedStatement.executeQuery(); |
| while (resultSet.next()) { |
| int id = resultSet.getInt(1); |
| String username = resultSet.getString(2); |
| String pwd = resultSet.getString(3); |
| System.out.println(id + "\t" + username + "\t" + pwd); |
| } |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| JdbcUtils.close(resultSet, preparedStatement, connection); |
| } |
| } |
九、Apache—DBUtils
1.分析问题
关闭 Connection 后 ,ResuItSet 结果集无法使用
ResuItSet 不利于数据的管理

2.基本介绍
commons-dbutils 是 Apache 组织提供的一个开源 JDBC( 工具类库 , 它是对 JDBC 的封装,使用 dbutils 能极大简化jdbc编码的工作量 。
DbUtiIs 类:
| * QueryRunner 类 : 该类封装了 SQL 的执行 , 是线程安全的 。 可以实现增 、 删 、 改 、 查 、 批处理 |
| * 使用 QueryRunner 类实现查询 |
| * ResultSetHandIer 接口:该接口用于处理 java.sqI.ResultSet, 将数据按要求转换为另一种形式 |
方法:
| - update--插入、修改、删除,返回受影响的行数 |
| - insert--支持插入操作,获取自增列作为返回值 |
| - query--查询操作,自动处理ResultSet需要Handler的配合 |

3.实际使用DBUtils
3-1.插入记录
| public void testInsert() throws SQLException { |
| |
| QueryRunner queryRunner = new QueryRunner(); |
| |
| Connection connection = JdbcUtils.getConnection(); |
| String sql="insert into dogs values(null,?,?,?)"; |
| int update = queryRunner.update(connection, sql, "a", "公", 12); |
| System.out.println(update); |
| DbUtils.closeQuietly(connection); |
| } |
3-2.删除记录
| public void testDelete() throws SQLException { |
| QueryRunner queryRunner = new QueryRunner(); |
| String sql="delete from dogs where age>?"; |
| Connection connection = JdbcUtils.getConnection(); |
| int update = queryRunner.update(connection, sql, 10); |
| System.out.println(update); |
| DbUtils.closeQuietly(connection); |
| } |
3-3.查询记录(单条)
| public void testSelect() throws SQLException { |
| QueryRunner queryRunner = new QueryRunner(); |
| Connection connection = JdbcUtils.getConnection(); |
| String sql="select id,name,sex,age from dogs where id=?"; |
| |
| BeanHandler<Dogs> dogsBeanHandler = new BeanHandler<>(Dogs.class); |
| Dogs dogs = queryRunner.query(connection, sql, dogsBeanHandler, 4); |
| System.out.println(dogs); |
| DbUtils.closeQuietly(connection); |
| } |
3-4.查询记录(多条)
| public void testSelectAll() throws SQLException { |
| QueryRunner queryRunner = new QueryRunner(); |
| Connection connection = JdbcUtils.getConnection(); |
| String sql="select id,name,sex,age from dogs where id<?"; |
| BeanListHandler<Dogs> dogsBeanHandler = new BeanListHandler<>(Dogs.class); |
| List<Dogs> dogsList = queryRunner.query(connection, sql, dogsBeanHandler, 10); |
| dogsList.forEach(System.out::println); |
| DbUtils.closeQuietly(connection); |
| } |
3-5.修改记录
| public void testupDate() throws SQLException { |
| QueryRunner queryRunner = new QueryRunner(); |
| Connection connection = JdbcUtils.getConnection(); |
| String sql="update dogs set age=? where name=?"; |
| int update = queryRunner.update(connection, sql, 19, "f"); |
| System.out.println(update); |
| DbUtils.closeQuietly(connection); |
| } |
3-6.查询记录(聚合函数)
| public void testAggregate() throws SQLException { |
| QueryRunner queryRunner = new QueryRunner(); |
| Connection connection = JdbcUtils.getConnection(); |
| |
| String maxSql="select max(age) from dogs"; |
| ScalarHandler<Object> handler = new ScalarHandler<>(); |
| int max = (Integer) queryRunner.query(connection, maxSql, handler); |
| System.out.println(max); |
| DbUtils.closeQuietly(connection); |
| } |
4.再次分析问题(解决:抽象CRUD方法)
通过编写上述代码后相对于直接使用JdbcUtils简化了不少代码,但是我们发现代码重复量太高
十、抽象CRUD(BasicDao)
1.分析问题
apache-dbutils+Druid 简化了JDBC开发 ,但还有不足 :
| * SQL 语句是固定 ,不能通过参数传入 ,通用性不好 ,需要进行改进 ,更方便执行增删改查 |
| * 对于 select 操作 ,如果有返回值 ,返回类型不能固定 ,需要使用泛型 |
| * 将来的表很多 ,业务需求复杂 ,不可能只靠一个 Java 类完成 |

2.基本说明
DAO :data access object 数据访问对象这样的通用类 ,称为 BasicDao ,是专门和数据库交互的 ,即完成对数据库 ( 表 ) 的 crud 操作 。
在 BaiscDao 的基础上 ,实现一张表对应一个 Dao,更好的完成功能。
3.BasicDAO 应用实例
| |
| |
| |
| |
| |
| |
| public class BasicDao { |
| |
| QueryRunner queryRunner = new QueryRunner(); |
| |
| |
| |
| |
| |
| |
| public int update(String sql, Object... params) { |
| |
| Connection connection = JdbcUtils.getConnection(); |
| try { |
| |
| return queryRunner.update(connection, sql, params); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| } finally { |
| |
| DbUtils.closeQuietly(connection); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public <T>T selectOne(Class<T> clazz,String sql,Object ... params){ |
| Connection connection = JdbcUtils.getConnection(); |
| try { |
| return queryRunner.query(connection,sql,new BeanHandler<>(clazz),params); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| }finally{ |
| DbUtils.closeQuietly(connection); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public <T>List<T> selectList(Class<T> clazz,String sql,Object ... params){ |
| Connection connection = JdbcUtils.getConnection(); |
| try { |
| return queryRunner.query(connection,sql,new BeanListHandler<>(clazz),params); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| }finally{ |
| DbUtils.closeQuietly(connection); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| public Object selectAggregate(String sql,Object ... params){ |
| Connection connection = JdbcUtils.getConnection(); |
| try { |
| return queryRunner.query(connection,sql,new ScalarHandler<>(),params); |
| } catch (SQLException e) { |
| throw new RuntimeException(e); |
| }finally{ |
| DbUtils.closeQuietly(connection); |
| } |
| } |
| } |
所有的笔记来源于:韩顺平 (bilibili.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步