java_JDBC,连接数据库方式,RestSet结果集,Statement,PreparedStatement,事务,批处理,数据库连接池(c3p0和Druid)、Apache-DBUtils、
一、JDBC 的概述
1.JDBC 为访问不同的数据薛是供了统一的接口,为使用者屏蔽了细节问题。
2. Java 程序员使用 JDBC, 可以连接任何提供了 JDBC 驱动程序的数据库系统,从而完成对数据库的各种操作。
二。JDBC 带来的好处
java 程序可以直接对数据库进行调用,但是没有很好的移植性(对用于不同的数据库),所以不推荐
JDBC 带来的好处:JDBC 是 java 提供一套用于数据库操作的接口 API,Java 程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。
JDBC API:JDBC API 是一系列的接口,它统一和规范了应用程序与数据库的连接,执行 SQL 语句,并得到返回结果等各类操作;
JDBC 程序编写步骤
1、注册驱动 --- 加载 Driver 类
2、获取连接 --- 得到 Connection
3、执行增删改查 --- 发送 Sql 给 mysql 执行
4、释放资源 --- 关闭相关连接
获取数据库连接的 5 种方式:
方式 1:使用(com.mysql.jdbc.Driver)com.mysql.cj.jdbc.Driver,属于静态加载,灵活性差,依赖性强
方式 2:使用反射机制,属于静态加载
方式 3:使用 DriverManager 替代 driver 进行统一管理
方式 4:使用 Class.forName 自动完成注册驱动,简化代码
这种方式连接是使用得最多的(推荐使用)
在底层会完成注册:
提示:
(1)mysql 驱动 5.1.6 可以无需 Class.forName(“com.mysql.jdbc.Driver”);
(2)从 jdk1.5 以后使用了 jdbc4, 不再需要显示调用 class.forName() 注册驱动而是自动调用驱动 jar 包下 META-INF\servicesljava .sql.Driver 文本中的类名称去注册
(3)建议加上 Class.forName(“com.mysql.jdbc.driver”),能够更加明确的感受到程序流程,利于掌握;
方式 5:利用 properties 文件配置数据库需要的相关的配置
更加的灵活,可以直接通过 properties 配置文件修改数据库连接相关的数据
对方式 5 的实例:
//properties 配置文件 driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC user=root password=123456 //连接数据库的相关操作 import java.io.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties;public class jdbc02 {
public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException {
//创建一个 properties 对象
Properties properties = new Properties();
//加载和获取创建的 properties 的相关数据
properties.load(new FileInputStream("src\db.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");String sql </span>= "insert into actor values (null,'王五','男','1975-11-23','110')"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">driver驱动,也可以不加,但是加上更容易读懂流程</span>
Class.forName(driver);
//连接和执行操作
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
statement.executeUpdate(sql);
//关闭连接
System.out.println("连接"+connection);
statement.close();
connection.close();}
}
三、RestSet【结果集】
基本介绍:
1. 表示数据库结果集的数据表, 通常通过执行查询数据库的语句生成
2. ResultSet 对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前
3. next 方法将光标移动到下一行,并且由于在 ResultSet 对象中没有更多行时返回
false, 因此可以在 while 循环中使用循环来遍历结果集
简单测试:
四、Statement:
基本介绍:
1.Statement 对象用于执行静态 SQL 语句并返回其生成的结果的对象
2. 在连接建立后,需要对数据库进行访问, 执行命名或是 SQL 语句,可以通过
Statement【存在 SQL 注入】
PreparedStatement【预处理】
CallableStatement【存储过程】
3. Statement 对象执行 SQL 语句,存在 SQL 注入风险
4.SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,恶意攻击数据库。
5. 要防范 SQL 注入,只要用 PreparedStatement(从 Statement 扩展而来) 取
代 Statement 就可以了
import java.io.*; import java.sql.*; import java.util.Properties;public class jdbc02 {
public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException {
//创建一个 properties 对象
Properties properties = new Properties();
//加载和获取创建的 properties 的相关数据
properties.load(new FileInputStream("src\db.properties"));
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");String sql </span>= "insert into actor values (null,'三毛','男','1975-11-23','110')"<span style="color: rgba(0, 0, 0, 1)">; String sql1 </span>= "select id,name from actor"<span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">driver驱动,也可以不加,但是加上更容易读懂流程</span>
Class.forName(driver);
//连接和执行操作
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();
// statement.executeUpdate(sql);// String sql1 = "select id,name from actor";
ResultSet resultSet = statement.executeQuery(sql1);
while (resultSet.next()) {
int i = resultSet.getInt(1);
String string1 = resultSet.getString(2);
System.out.println(i+"=="+string1);
}
//关闭连接
resultSet.close();
System.out.println("连接"+connection);
statement.close();
connection.close();}
}
PrepareStatement:
1. PreparedStatement 执行的 SQL 语句中的参数用问号 (?) 来表示, 调用
PreparedStatement 对象的 setXxx()方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引 (从 1 开始),第二个是设置的 SQL 语句中的参数的值
2. 调用 executeQuery),返回 ResultSet 对象
3. 调用 executeUpdate): 执行更新,包括增、删、修改
预处理的好处:
1. 不再使用 + 拼接 sql 语句, 减少语法错误
2. 有效的解决了 sql 注入问题!
3. 大大减少了编译次数,效率较高
对 preparestatement 的测试代码,配置文件还是上面的配置文件
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Properties;public class PrepareStatement {
public static void main(String[] args) throws Exception {Properties properties </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Properties(); properties.load(</span><span style="color: rgba(0, 0, 255, 1)">new</span> FileInputStream("src\\db.properties"<span style="color: rgba(0, 0, 0, 1)">)); String drive </span>= properties.getProperty("driver"<span style="color: rgba(0, 0, 0, 1)">); String url </span>= properties.getProperty("url"<span style="color: rgba(0, 0, 0, 1)">); String user </span>= properties.getProperty("user"<span style="color: rgba(0, 0, 0, 1)">); String password </span>= properties.getProperty("password"<span style="color: rgba(0, 0, 0, 1)">); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">更新操作
// String sql = "update actor set phone = ? where name = ?";
//删除操作
// String sql = "delete from actor where name = ?";
// 添加操作
// String sql = "insert into actor values(null,?,?,?,?)";
//查询操作
String sql = "select * from actor";Class.forName(drive); Connection connection </span>=<span style="color: rgba(0, 0, 0, 1)"> DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement </span>=<span style="color: rgba(0, 0, 0, 1)"> connection.prepareStatement(sql); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">更改操作
// preparedStatement.setString(1, "123456");
// preparedStatement.setString(2, "三毛");
//删除操作
// preparedStatement.setString(1, "二狗");
//添加操作
// preparedStatement.setString(1, "张三");
// preparedStatement.setString(2, "男");
// preparedStatement.setString(3, "1975-11-23 00:00:00");
// preparedStatement.setString(4,"456789");
// int i = preparedStatement.executeUpdate();
// System.out.println(i >0 ? "成功" : "失败");//查询操作
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.getString(2));
}preparedStatement.close(); connection.close(); }
}
总结:
五、事务:将多行代码当做 SQL 事务来处理,主要流程需要的关键代码:
connection.setAutoCommit(false);// 取消自动提交的操作,取消之后,会在提及之后完成事务
connection.commit(); 提交事务
connection.rollback();// 用于回退事务
批处理:
基本介绍:
1、当需要成批插入或者更新记录时。可以采用 Java 的批量更新机制,这一机制允
许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
2、JDBC 的批量处理语句包括下面方法:
addBatch(): 添加需要批量处理的 SQL 语句或参数 executeBatch(: 执行批量处理语句;
clearBatch(): 清空批处理包的语句
3、 JDBC 连接 MySQL 时,如果要使用批处理功能, 请再 url 中加参
数?rewriteBatchedStatements=true
4、批处理往往和 PreparedStatement 一起搭配使用, 可以既减少编译次数,又减少运行次数,效率大大提高
过程:
(1)将 sql 语句加入到批处理包中
preparedStatement.addBatch();
preparedStatement.addBatch(sql);
(2)执行 sql 和清空 sql
// 批量执行 sql 语句
preparedStatement.executeBatch();
// 清除批量的 sql 语句
preparedStatement.clearBatch();
将 SQL 加入到批处理包中源码所做的事情:
六、数据库连接池
传统 connection 问题分析:
1.传统的 JDBC 数据库连接使用 DriverManager 来获取,每次向数据库建立
连接的时候都要将 Connection 加载到内存中,再验证 IP 地址,用户名和密码 (0.05s~1s 时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。2 每一次数据库连接, 使用完后都得断开, 如果程序出现异常面未能关闭,将
导致数据库内存泄漏,最终将导致重启数据库。
3. 传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致
内存泄漏,MySQL 崩溃。
4. 解决传统开发中的数据库连接问题, 可以采用数据库连接池技术
(connection pool).
数据库连接池基本介绍:
1. 预先在缓冲池中放入一定数量的连接,,当需
要建立数据库连接时, 只需从“缓冲池”中取出一个,,使用完毕之后再放回去。
2. 数据库连接池负责分配、管理和释放数据库
连接, 它允许应用程序重复使用一个现有的数据库连接, 而不是重新建立一个。
3. 当应用程序向连接池请求的连接数超过最大
连接数量时,这些请求将被加入到等待队列中
数据库连接池示意图:
数据库连接池种类:
1.JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource
只是一个接口,该接口通常由第三方提供实现
2.C3PO 数据库连接池,速度相对较慢,稳定性不错 (hibernate, spring)
3.DBCP 数据库连接池,速度相对 c3p0 较快,但不稳定
4. Proxool 数据库连接池,有监控连接池状态的功能,稳定性较 c3p0 差一点
5.BoneCP 数据库连接池,速度快
6.Druid(德鲁伊) 是阿里提供的数据库连接池,集 DBCP、C3P0、Proxool
优点于身的数据库连接池
测试:C3P0 连接池的连接(需要导入第三方库:c3p0 的 jar 包)
第一个 C3P0 连接的配置文件还是上面的配置文件内容
第二个 C3P0 的连接需要有一个 xml 配置文件
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class ConDatasource {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\db.properties"));
String driver = properties.getProperty("driver");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">建立comboPooledDataSource管理连接池</span>
ComboPooledDataSource comboPooledDataSource = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ComboPooledDataSource();
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置初始化连接数和最大连接数</span>
comboPooledDataSource.setInitialPoolSize(<span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">);
comboPooledDataSource.setMaxPoolSize(</span><span style="color: rgba(128, 0, 128, 1)">50</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个方法就是从DataSource接口实现的</span>
Connection connection =<span style="color: rgba(0, 0, 0, 1)"> comboPooledDataSource.getConnection();
System.</span><span style="color: rgba(0, 0, 255, 1)">out</span>.println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1连接成功</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
connection.close();
}
@Test
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> ConDatasource02() throws SQLException {
ComboPooledDataSource comboPooledDataSource </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> ComboPooledDataSource(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">test_C3P0</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">long</span> start =<span style="color: rgba(0, 0, 0, 1)"> System.currentTimeMillis();
System.</span><span style="color: rgba(0, 0, 255, 1)">out</span>.println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">测试连接5000次需要的时间</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < <span style="color: rgba(128, 0, 128, 1)">5000</span>; i++<span style="color: rgba(0, 0, 0, 1)">) {
Connection connection </span>=<span style="color: rgba(0, 0, 0, 1)"> comboPooledDataSource.getConnection();
// System.out.println("2 连接成功");
connection.close();
}
long end = System.currentTimeMillis();
System.out.println("花费时长:"+(end-start));
}
}
//第二种方式的 xml 文件
<c3p0-config>
<named-config name="test_C3P0">
<!-- 驱动类 -->
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<!-- url-->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC</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=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">maxStatements</span><span style="color: rgba(128, 0, 0, 1)">"</span>><span style="color: rgba(128, 0, 128, 1)">5</span></property>
<!-- 每个连接对象可连接的最多的命令对象数 -->
<property name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">maxStatementsPerConnection</span><span style="color: rgba(128, 0, 0, 1)">"</span>><span style="color: rgba(128, 0, 128, 1)">2</span></property>
</named-config>
</c3p0-config>
测试:Druid 连接池的连接(需要第三方库 druid 的 jar 包)
package com.zjl.jdbc;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.util.Properties;
public class Druidsource {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\druid.properties"));// 如下定义的配置文件
DataSource dataSource </span>=<span style="color: rgba(0, 0, 0, 1)"> DruidDataSourceFactory.createDataSource(properties);
</span><span style="color: rgba(0, 0, 255, 1)">long</span> start =<span style="color: rgba(0, 0, 0, 1)"> System.currentTimeMillis();
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>;i < <span style="color: rgba(128, 0, 128, 1)">500000</span>;i++<span style="color: rgba(0, 0, 0, 1)"> ) {
Connection connection </span>=<span style="color: rgba(0, 0, 0, 1)"> dataSource.getConnection();
connection.close();
}
</span><span style="color: rgba(0, 0, 255, 1)">long</span> end =<span style="color: rgba(0, 0, 0, 1)"> System.currentTimeMillis();
System.</span><span style="color: rgba(0, 0, 255, 1)">out</span>.println(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Druid连接5000 次需要的时间:</span><span style="color: rgba(128, 0, 0, 1)">"</span> + (end - start));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Druid连接500000 次需要的时间:625</span>
}
}
// 连接中需要的一个配置文件
druid.properties:放在 src 目录下
#key=value
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC
#url=jdbc:mysql://localhost:3306/girls
username=root
password=123456
#initial connection Size 初始连接数
initialSize=10
#min idle connecton size 最小等待连接数
minIdle=5
#max active connection size 最大连接数
maxActive=20
#max wait time (5000 mil seconds)
# 最大等待时间,时间超过就结束这次连接等待下一次的连接
maxWait=5000
注意:对于 c3p0 和 Druid 他们的 close()是按照第三方库的连接方式,仅仅是将从连接池引用的数据库连接断开 ( 放弃引用)
重新将连接放回到连接池中,和原生 的 jdbc 连接中的 close 方法断开连接不同;
用 Druid 创建一个连接和断开的工具类;
package com.zjl.jdbc;import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class JDBCUtilsByDruid {
static DataSource ds;
static {
Properties properties = new Properties();</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { properties.load(</span><span style="color: rgba(0, 0, 255, 1)">new</span> FileInputStream("src\\druid.properties"<span style="color: rgba(0, 0, 0, 1)">)); ds </span>=<span style="color: rgba(0, 0, 0, 1)"> DruidDataSourceFactory.createDataSource(properties); } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) { e.printStackTrace(); } } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">编写获取Connection的方法</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException { </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ds.getConnection(); } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> close(ResultSet resultSet, Statement statement, Connection connection) { </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { </span><span style="color: rgba(0, 0, 255, 1)">if</span> (resultSet != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { resultSet.close(); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (statement != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { statement.close(); } </span><span style="color: rgba(0, 0, 255, 1)">if</span> (connection != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) { connection.close(); } } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将编译异常转成运行异常抛出</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> RuntimeException(e); } }
}
七、Apache-DBUtils
1、问题引出:在使用 Druid 连接数据库,返回结果集之后,如果断开连接,结果集就不能够再使用。解决方法如图,将返回的结果集保存到一个泛型列表中,那么当数据库连接断开后,还是可以使用返回的结果集。
2、对Apache-DBUtils 的基本介绍
1).commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,它是对 JDBC 的封装,
使用 dbutils 能极大简化 jdbc 编码的工作量 [真的]。
DbUtils 类
(1). QueryRunner 类: 该类封装了 SQL 的执行,是线程安全的。可以实现增、删、改、查、批处理
(2). 使用 QueryRunner 类实现查询
(3). ResultSetHandler 接口: 该接口用于处理 java.sql.ResultSet, 将数据按要求转换为另一种形式
对该 DBUtils 进行测试:需要对应的 jar 包(commons-dbutils-1.7.jar)可以去:http://commons.apache.org/下载
相应的 JDBCUtilsByDruid 类是上面的测试类:
package com.zjl.jdbc;import com.zjl.bean.Actor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;public class TestDBUtils {
public static void main(String[] args) throws Exception {
String sql = "select * fromactor
";
//从 Druid 中获取一个连接
Connection connection = JDBCUtilsByDruid.getConnection();
//引入 DBUtils 的 jar 包,并获得一个 QueryRunner 对象
QueryRunner queryRunner = new QueryRunner();</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">利用QueryRunner对象就可以直接查询数据库,执行SQl语句,返回结果封装到ArrayList集合中 </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> connection是一个连接,sql是一个执行语句 </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">new BeanListHandler<>(Actor.class):在将resultSet中的结果以Actor对象方式封装到ArrayList </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">底层使用反射机制,获取Actor类的属性,然后进行封装 </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1就是给sql 语句中的?赋值,可以有多个值,因为是可变参数0bject... params
// List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
//如果要返回单个查询数据就使用 BeanHandler<>(Actor.class),返回结果就会是单个对象或者为空
List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class));
//在底层会得到 resultSet 并在 query 中关闭,也会在底层使用 preparedStatement 并关闭
// JDBCUtilsByDruid.close(null, null, connection);
Iterator<Actor> iterator = list.iterator();
while (iterator.hasNext()) {
Actor next = iterator.next();
System.out.println(next);
}
//进行更新操作
String updateSql = "updateactor
set name = ? where id = ?";
int update = queryRunner.update(connection, updateSql, "王无无", 8);
System.out.println((update > 0) ? "更新成功" : "更新失败");
//进行删除操作
String delSql = "delete fromactor
where id = ?";
int update1 = queryRunner.update(connection, delSql, 10);
System.out.println((update > 0) ? "删除成功" : "删除失败");</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭资源</span> JDBCUtilsByDruid.close(<span style="color: rgba(0, 0, 255, 1)">null</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">, connection); }
}
八、BasicDao--DAO 和增删改查通用方法(DAO:data access object 数据访问对象)
基本说明:
1)、 DAO:data access object 数据访问对象
2)、这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库 (表) 的 crud 操作。
3)、在 BaiscDao 的基础上,实现一张表对应一个 Dao,更好的完成功能;
关系图如下: