第二十五章 JDBC 和数据库连接池
一、JDBC 概述(P821)
1. 基本介绍
(1)JDBC 为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。
(2)Java 程序员使用 JDBC,可以连接任何提供了 JDBC 驱动程序的数据库系统,从完成对数据库的各种操作。
2. 模拟 JDBC
public interface JdbcInterface {//连接public Object getConnection() ;//crudpublic void crud();//关闭连接public void close();
}
public class MysqlJdbcImpl implements JdbcInterface {@Overridepublic Object getConnection() {System.out.println("得到 mysql 的连接");return null;}@Overridepublic void crud() {System.out.println("完成 mysql 增删改查");}@Overridepublic void close() {System.out.println("关闭 mysql 的连接");}
}
public class OracleJdbcImpl implements JdbcInterface {@Overridepublic Object getConnection() {System.out.println("得到 oracle 的连接 升级");return null;}@Overridepublic void crud() {System.out.println("完成 对 oracle 的增删改查");}@Overridepublic void close() {System.out.println("关闭 oracle 的连接");}
}
public class TestJDBC {public static void main(String[] args) throws Exception {//完成对 mysql 的操作JdbcInterface jdbcInterface = new MysqlJdbcImpl();jdbcInterface.getConnection(); //通过接口来调用实现类[动态绑定]jdbcInterface.crud();jdbcInterface.close();//完成对 oracle 的操作System.out.println("==============================");jdbcInterface = new OracleJdbcImpl();jdbcInterface.getConnection(); //通过接口来调用实现类[动态绑定]jdbcInterface.crud();jdbcInterface.close();}
}
说明:JDBC 是 Java 提供一套用于数据库操作的接口 API,Java 程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。
3. JDBC API
JDBC API 是一系列的接口,它统一和规范了应用程序与数据库的连接、执行 SQL 语句,并到得到返回结果等各类操作,相关类和接口在 【java.sql】与【javax.sql】 包中
二、JDBC 快速入门
1. JDBC程序编写步骤
(1)注册驱动 - 加载 Driver 类
(2)获取连接-得到Connection
(3)执行增删改查 - 发送 SQL 给 mysql 执行
(4)释放资源-关闭相关连接
2. JDBC 第一个程序
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class Jdbc01 {public static void main(String[] args) throws Exception {//前置工作: 在项目下创建一个文件夹比如 libs// 将 mysql.jar 拷贝到该目录下,点击 add to project ..加入到项目中//1. 注册驱动Driver driver = new Driver(); //创建 driver 对象//2. 得到连接//(1) jdbc:mysql:// 规定好表示协议,通过 jdbc 的方式连接 mysql//(2) localhost 主机,可以是 ip 地址//(3) 3306 表示 mysql 监听的端口//(4) hsp_db02 连接到 mysql dbms 的哪个数据库//(5) mysql 的连接本质就是前面学过的 socket 连接String url = "jdbc:mysql://localhost:3306/hsp_db02";//将 用户名和密码放入到 Properties 对象Properties properties = new Properties();//说明 user 和 password 是规定好,后面的值根据实际情况写properties.setProperty("user", "root");// 用户properties.setProperty("password", "hsp"); //密码Connection connect = driver.connect(url, properties);//3. 执行 sql//String sql = "insert into actor values(null, '刘德华', '男', '1970-11-11', '110')";//String sql = "update actor set name='周星驰' where id = 1";String sql = "delete from actor where id = 1";//statement 用于执行静态 SQL 语句并返回其生成的结果的对象Statement statement = connect.createStatement();int rows = statement.executeUpdate(sql); // 如果是 dml 语句,返回的就是影响行数System.out.println(rows > 0 ? "成功" : "失败");//4. 关闭连接资源statement.close();connect.close();}
}
三、获取数据库连接 5 种方式
1. 方式1 获取 Driver 实现类对象
public class Demo {public static void main(String[] args) throws Exception {Driver driver = new Driver();String url = "jdbc:mysql://localhost:3306/hsp_db02";Properties properties = new Properties();properties.setProperty("user", "root");// 用户properties.setProperty("password", "hsp"); //密码Connection connect = driver.connect(url, properties); }
}
2. 方式2 反射加载 Driver 类
public class JdbcConn {@Testpublic void connect02() throws Exception {//使用反射加载 Driver 类 , 动态加载,更加的灵活,减少依赖性Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");Driver driver = (Driver) aClass.newInstance();String url = "jdbc:mysql://localhost:3306/hsp_db02";//将 用户名和密码放入到 Properties 对象Properties properties = new Properties();//说明 user 和 password 是规定好,后面的值根据实际情况写properties.setProperty("user", "root");// 用户properties.setProperty("password", "hsp"); //密码Connection connect = driver.connect(url, properties);System.out.println("方式 2=" + connect);}
}
3. 方式3 使用 DriverManager 替代 driver
public class JdbcConn {//方式 3 使用 DriverManager 替代 driver 进行统一管理@Testpublic void connect03() throws Exception {//使用反射加载 DriverClass<?> aClass = Class.forName("com.mysql.jdbc.Driver");Driver driver = (Driver) aClass.newInstance();//创建 url 和 user 和 passwordString url = "jdbc:mysql://localhost:3306/hsp_db02";String user = "root";String password = "hsp";DriverManager.registerDriver(driver);//注册 Driver 驱动Connection connection = DriverManager.getConnection(url, user, password);System.out.println("第三种方式=" + connection);}
}
4. 方式4 使用 Class.forName 自动完成注册驱动(推荐使用)
public class JdbcConn {//方式 4: 使用 Class.forName 自动完成注册驱动,简化代码//这种方式获取连接是使用的最多,推荐使用@Testpublic void connect04() throws Exception {//使用反射加载了 Driver 类//在加载 Driver 类时,完成注册/*源码:1. 静态代码块,在类加载时,会执行一次.2. DriverManager.registerDriver(new Driver());3. 因此注册 driver 的工作已经完成static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}*/Class.forName("com.mysql.jdbc.Driver");//创建 url 和 user 和 passwordString url = "jdbc:mysql://localhost:3306/hsp_db02";String user = "root";String password = "hsp";Connection connection = DriverManager.getConnection(url, user, password);System.out.println("第 4 种方式~ " + connection);}
}
5. 方式5 增加配置文件
public class JdbcConn {//方式 5 , 在方式 4 的基础上改进,增加配置文件,让连接 mysql 更加灵活@Testpublic void connect05() throws Exception {//通过 Properties 对象获取配置文件的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.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);System.out.println("方式 5 " + connection);}
}
四、ResultSet(结果集)
1. 基本介绍
(1)表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
(2)ResultSet 对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。
(3)next 方法将光标移动到下一行,并且由于在 ResultSet 对象中没有更多行时返回 false,因此可以在 while 循环中使用循环来遍历结果集。
2. 应用实例
演示 select 语句返回 ResultSet ,并取出结果。
public class ResultSet_ {public static void main(String[] args) throws Exception {//通过 Properties 对象获取配置文件的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));//获取相关的值String user = properties.getProperty("user");String password = properties.getProperty("password");String driver = properties.getProperty("driver");String url = properties.getProperty("url");//1. 注册驱动Class.forName(driver);//建议写上//2. 得到连接Connection connection = DriverManager.getConnection(url, user, password);//3. 得到 StatementStatement statement = connection.createStatement();//4. 组织 SqLString sql = "select id, name , sex, borndate from actor";//执行给定的 SQL 语句,该语句返回单个 ResultSet 对象/*+----+-----------+-----+---------------------+| id | name | sex | borndate |+----+-----------+-----+---------------------+| 4 | 刘德华 | 男 | 1970-12-12 00:00:00 || 5 | jack | 男 | 1990-11-11 00:00:00 |+----+-----------+-----+---------------------+*//*老韩阅读 debug 代码 resultSet 对象的结构*/ResultSet resultSet = statement.executeQuery(sql);//5. 使用 while 取出数据while (resultSet.next()) { // 让光标向后移动,如果没有更多行,则返回 falseint id = resultSet.getInt(1); //获取该行的第 1 列//int id1 = resultSet.getInt("id"); 通过列名来获取值, 推荐String name = resultSet.getString(2);//获取该行的第 2 列String sex = resultSet.getString(3);Date date = resultSet.getDate(4);System.out.println(id + "\t" + name + "\t" + sex + "\t" + date);}//6. 关闭连接resultSet.close();statement.close();connection.close();}}
五、Statement
1. 基本介绍
(1)Statement 对象,用于执行静态 SQL 语句并返回其生成的结果的对象。
(2)在连接建立后,需要对数据库进行访问,执行命名或是 SQL 语句,可以通过
1️⃣Statement【存在 SQL 注入】
2️⃣PreparedStatement【预处理】
3️⃣CallableStatement【存储过程】
(3)Statement 对象执行 SQL 语句,存在 SQL 注入风险。
(4)SQL注入 是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL 语句段或命令,恶意攻击数据库。
(5)要防范 SQL 注入,只要用 PreparedStatement(从 Statement 扩展而来)取
代 Statement 就可以了。
2. 应用实例
public class ResultSet_ {public static void main(String[] args) throws Exception {//让用户输入管理员名和密码(万能用户名和密码)System.out.print("请输入管理员的名字: ");String admin_name = "1\' or";System.out.print("请输入管理员的密码: ");String admin_pwd = "\'1\'=\'1 ";//通过 Properties 对象获取配置文件的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值String user = properties.getProperty("user");String password = properties.getProperty("password");String driver = properties.getProperty("driver");String url = properties.getProperty("url");//1. 注册驱动Class.forName(driver);//2. 得到连接Connection connection = DriverManager.getConnection(url, user, password);//3. 得到 StatementStatement statement = connection.createStatement();//4. 组织 SqLString sql = "select name , pwd from admin where "+ "name ='" + admin_name+ "' and pwd = '" + admin_pwd + "'";ResultSet resultSet = statement.executeQuery(sql);if (resultSet.next()) { //如果查询到一条记录,则说明该管理存在System.out.println("恭喜, 登录成功");} else {System.out.println("对不起,登录失败");}//关闭连接resultSet.close();statement.close();connection.close();}
}
六、PreparedStatement
1. 基本介绍
(1)PreparedStatement 执行的 SQL 语句中的参数用问号(?)来表示,调用
Preparedstatement 对象的 setXxx()方法来设置这些参数。setXxx()方法有
两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从1开始),第二
个是设置的 SQL 语句中的参数的值。
(2)调用 executeQuery(),返回 ResultSet 对象。
(3)调用 executeUpdate(),执行更新,包括增、删、修改。
2. 预处理好处
(1)不再使用 + 拼接 sql 语句,减少语法错误。
(2)有效的解决了 sql 注入问题!
(3)大大减少了编译次数,效率较高。
3. 应用实例
public class PreparedStatement_ {public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);//让用户输入管理员名和密码System.out.print("请输入管理员的名字: "); //next(): 当接收到 空格或者 '就是表示结束String admin_name = scanner.nextLine(); // 老师说明,如果希望看到 SQL 注入,这里需要用 nextLineSystem.out.print("请输入管理员的密码: ");String admin_pwd = scanner.nextLine();//通过 Properties 对象获取配置文件的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));//获取相关的值String user = properties.getProperty("user");String password = properties.getProperty("password");String driver = properties.getProperty("driver");String url = properties.getProperty("url");//1. 注册驱动Class.forName(driver);//建议写上//2. 得到连接Connection connection = DriverManager.getConnection(url, user, password);//3. 得到 PreparedStatement//3.1 组织 SqL , Sql 语句的 ? 就相当于占位符String sql = "select name , pwd from admin where name =? and pwd = ?";//3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象PreparedStatement preparedStatement = connection.prepareStatement(sql);//3.3 给 ? 赋值preparedStatement.setString(1, admin_name);preparedStatement.setString(2, admin_pwd);//4. 执行 select 语句使用 executeQuery// 如果执行的是 dml(update, insert ,delete) executeUpdate()// 这里执行 executeQuery ,不要在写 sqlResultSet resultSet = preparedStatement.executeQuery(sql);if (resultSet.next()) { //如果查询到一条记录,则说明该管理存在System.out.println("恭喜, 登录成功");} else {System.out.println("对不起,登录失败");}//关闭连接resultSet.close();preparedStatement.close();connection.close();}
}
七、封装 JDBCUtils
1. 说明
在 jdbc 操作中,获取连接和释放资源是经常使用到,可以将其封装 JDBC 连接的工具类 JDBCUtils。
2. 代码实现
public class JDBCUtils {//定义相关的属性(4 个), 因为只需要一份,因此,我们做出 staticprivate static String user; //用户名private static String password; //密码private static String url; //urlprivate static String driver; //驱动名//在 static 代码块去初始化static {try {Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));//读取相关的属性值user = properties.getProperty("user");password = properties.getProperty("password");url = properties.getProperty("url");driver = properties.getProperty("driver");} catch (IOException e) {//在实际开发中,我们可以这样处理//1. 将编译异常转成 运行异常//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便. throw new RuntimeException(e);}}//连接数据库, 返回 Connectionpublic static Connection getConnection() {try {return DriverManager.getConnection(url, user, password);} catch (SQLException e) {//1. 将编译异常转成 运行异常//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便. throw new RuntimeException(e);}}//关闭相关资源/*1. ResultSet 结果集2. Statement 或者 PreparedStatement3. Connection4. 如果需要关闭资源,就传入对象,否则传入 null*/public static void close(ResultSet set, Statement statement, Connection connection) {//判断是否为 nulltry {if (set != null) {set.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {//将编译异常转成运行异常抛出throw new RuntimeException(e);}}
}
八、事务
1. 基本介绍
(1)JDBC 程序中当一个 Connection 对象创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
(2)JDBC 程序中为了让多个 SQL 语句作为一个整体执行,需要 使用事务。
(3)调用 Connection 的 setAutoCommit(false)可以取消自动提交事务。
(4)在所有的 SQL 语句都成功执行后,调用 Connection 的 commit()方法提交事务。
(5)在其中某个操作失败或出现异常时,调用 Connection 的 rollback()方法回滚事务。
2. 代码实现
public class Transaction_ {//事务来解决@Testpublic void useTransaction() {//操作转账的业务//1. 得到连接Connection connection = null;//2. 组织一个 sqlString sql = "update account set balance = balance - 100 where id = 1";String sql2 = "update account set balance = balance + 100 where id = 2";PreparedStatement preparedStatement = null;//3. 创建 PreparedStatement 对象try {connection = JDBCUtils.getConnection(); // 在默认情况下,connection 是默认自动提交//将 connection 设置为不自动提交connection.setAutoCommit(false); //开启了事务preparedStatement = connection.prepareStatement(sql);preparedStatement.executeUpdate(); // 执行第 1 条 sqlint i = 1 / 0; //抛出异常preparedStatement = connection.prepareStatement(sql2);preparedStatement.executeUpdate(); // 执行第 3 条 sql//这里提交事务connection.commit();} catch (SQLException e) {//这里我们可以进行回滚,即撤销执行的 SQL//默认回滚到事务开始的状态. System.out.println("执行发生了异常,撤销执行的 sql");try {connection.rollback();} catch (SQLException throwables) {throwables.printStackTrace();}e.printStackTrace();} finally {//关闭资源JDBCUtils.close(null, preparedStatement, connection);}}
}
九、批处理
1. 基本介绍
(1)当需要感批插入或者更新记录时。可以采用 Java 的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
(2)JDBC 的批量处理语句包括下面方法:
1️⃣addBatch():添加需要批量处理的 SQL 语句或参数
2️⃣executeBatch():执行批量处理语句
3️⃣clearBatch():清空批处理包的语句
(3)JDBC 连接 MySQL 时,如果要使用批处理功能,请再 url 中加参数【rewriteBatcherStatements=true】
(4)批处理往往和 PreparedStatement 一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高。
2. 应用实例
public class Batch_ {//使用批量方式添加数据@Testpublic void batch() throws Exception {Connection connection = JDBCUtils.getConnection();String sql = "insert into admin2 values(null, ?, ?)";PreparedStatement preparedStatement = connection.prepareStatement(sql);System.out.println("开始执行");long start = System.currentTimeMillis();//开始时间for (int i = 0; i < 5000; i++) {//5000 执行preparedStatement.setString(1, "jack" + i);preparedStatement.setString(2, "666");//将 sql 语句加入到批处理包中preparedStatement.addBatch();//当有 1000 条记录时,在批量执行if ((i + 1) % 1000 == 0) {//满 1000 条 sqlpreparedStatement.executeBatch();//清空一把preparedStatement.clearBatch();}}long end = System.currentTimeMillis();System.out.println("批量方式 耗时=" + (end - start));//批量方式 耗时=108//关闭连接JDBCUtils.close(null, preparedStatement, connection);}
}
十、数据库连接池
1. 传统获取 Connection 问题分析
(1)传统的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证IP地址、用户名和密码。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器前溃。
(2)每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库 内存泄露,最终将导致重启数据库。
(3)传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄漏,MySQL 崩溃。
(4)解决传统开发中的数据库连接问题,可以采用数据库 连接池 技术(connection pool)。
2. 数据库连接池基本介绍
(1)预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”取出一个,使用完毕之后再放回去。
(2)数据库连接池负责分配、管理和释放数据库连接,它允许应用程序 重复使用 一个现有的数据库连接,而不是重新建立一个。
(3)当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
3. 数据库连接池种类
(1) JDBC 的数据库连接池使用 javax.sgl.DataSource 来表示,DataSource 只是一个接口,该接口通常由第三方提供实现。
1️⃣ C3P0 数据库连接池,速度相对较慢,稳定性不错(hibernate,spring)
2️⃣DBCP 数据库连接池,速度相对 C3P0 较快,但不稳定
3️⃣Proxool 数据库连接池,有监控连接池状态的功能,稳定性较 C3P0 差一点
4️⃣BoneCP数据库连接池,速度快
5️⃣ Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3PO、Proxool 优点于一身的数据库连接池。
4. C3P0 应用实例
public class C3P0_ {//方式 1: 相关参数,在程序中指定 user, url , password 等@Testpublic void testC3P0_01() throws Exception {//1. 创建一个数据源对象ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();//2. 通过配置文件 mysql.properties 获取相关连接的信息Properties properties = new Properties();properties.load(new FileInputStream("src\\mysql.properties"));//读取相关的属性值String user = properties.getProperty("user");String password = properties.getProperty("password");String url = properties.getProperty("url");String driver = properties.getProperty("driver");//给数据源 comboPooledDataSource 设置相关的参数//注意:连接管理是由 comboPooledDataSource 来管理comboPooledDataSource.setDriverClass(driver);comboPooledDataSource.setJdbcUrl(url);comboPooledDataSource.setUser(user);comboPooledDataSource.setPassword(password);//设置初始化连接数comboPooledDataSource.setInitialPoolSize(10);//最大连接数comboPooledDataSource.setMaxPoolSize(50);//测试连接池的效率, 测试对 mysql 5000 次操作long start = System.currentTimeMillis();for (int i = 0; i < 5000; i++) {//这个方法就是从 DataSource 接口实现的Connection connection = comboPooledDataSource.getConnection();connection.close();}long end = System.currentTimeMillis();//c3p0 5000 连接 mysql 耗时=391System.out.println("c3p0 5000 连接 mysql 耗时=" + (end - start));}//方式 2: 使用配置文件模板来完成@Testpublic void testC3P0_02() throws SQLException {ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("hsp_edu");//测试 5000 次连接 mysqllong start = System.currentTimeMillis();System.out.println("开始执行....");for (int i = 0; i < 500000; i++) {Connection connection = comboPooledDataSource.getConnection();connection.close();}long end = System.currentTimeMillis();//c3p0 的第二种方式 耗时=413System.out.println("c3p0 的第二种方式(500000) 耗时=" + (end - start));//1917}
}
5. Druid(德鲁伊)应用实例
public class Druid_ {@Testpublic void testDruid() throws Exception {//1. 加入 Druid jar 包//2. 加入 配置文件 druid.properties , 将该文件拷贝项目的 src 目录//3. 创建 Properties 对象, 读取配置文件Properties properties = new Properties();properties.load(new FileInputStream("src\\druid.properties"));//4. 创建一个指定参数的数据库连接池, Druid 连接池DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);long start = System.currentTimeMillis();for (int i = 0; i < 500000; i++) {Connection connection = dataSource.getConnection();System.out.println(connection.getClass());//System.out.println("连接成功!");connection.close();}long end = System.currentTimeMillis();//druid 连接池 操作 5000 耗时=412System.out.println("druid 连接池 操作 500000 耗时=" + (end - start));//539}
}
十一、Apache—DBUtils
1. 基本介绍
(1)commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,它是对 JDBC 的封装,使用 dbutils 能极大简化 jdbc 编码的工作量。
DbUtils类
(1)QueryRunner类:该类封装了 SQL 的执行,是线程安全的。可以实现增、删、改、查、批处理。
(2)使用 QueryRunner 类实现查询。
(3)ResultSetHandler接口:该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
2. 应用实例
public class DBUtils_USE {//使用 apache-DBUtils 工具类 + druid 完成对表的 crud 操作@Testpublic void testQueryMany() throws Exception { //返回结果是多行的情况//1. 得到 连接 (druid)Connection connection = JDBCUtilsByDruid.getConnection();//2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project//3. 创建 QueryRunnerQueryRunner queryRunner = new QueryRunner();//4. 就可以执行相关的方法,返回 ArrayList 结果集//String sql = "select * from actor where id >= ?";// 注意: sql 语句也可以查询部分列String sql = "select id, name from actor where id >= ?";// 老韩解读//(1) query 方法就是执行 sql 语句,得到 resultset ---封装到 --> ArrayList 集合中//(2) 返回集合//(3) connection: 连接//(4) sql : 执行的 sql 语句//(5) new BeanListHandler<>(Actor.class): 在将 resultset -> Actor 对象 -> 封装到 ArrayList//(6) 1 就是给 sql 语句中的? 赋值,可以有多个值,因为是可变参数 Object... params//(7) 底层得到的 resultset ,会在 query 关闭, 关闭 PreparedStatmentList<Actor> list =queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);System.out.println("输出集合的信息");for (Actor actor : list) {System.out.print(actor);}//释放资源JDBCUtilsByDruid.close(null, null, connection);}
}
十二、DAO
1. 基本说明
(1)DAO:data access object,数据访问对象
(2)这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作。
(3)在 BaiscDao 的基础上,实现一张表对应一个 Dao,更好的完成功能。
相关文章:
第二十五章 JDBC 和数据库连接池
一、JDBC 概述(P821) 1. 基本介绍 (1)JDBC 为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。 (2)Java 程序员使用 JDBC,可以连接任何提供了 JDBC 驱动程序的数据库系统…...
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的固定帧率(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的固定帧率(C) Baumer工业相机Baumer工业相机的固定帧率功能的技术背景CameraExplorer如何查看相机固定帧率功能在NEOAPI SDK里通过函数设置相机固定帧率 Baumer工业相机通过NEOAPI SDK设置相机固定…...
基于Java课堂签到系统
基于Java课堂签到系统 功能需求 1、用户登录:学生需要使用学号或手机号等唯一标识登录系统。 2、签到功能:在课堂开始时,学生可以通过系统进行签到,以证明出席。 3、签出功能:在课堂结束时,学生可以通过…...
springboot整合webservice使用总结
因为做的项目中用到了webservice,所以在此总结一下。 一、webservice简介 Web Service也叫XML Web Service, WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是通过SOAP在Web上提供的软件服务,使…...
MySQL中的索引之分类,原理,作用,优缺点和执行计划
索引 索引的作用:加速查找 例如: 300w条数据的表中查询,无索引需要700s, 利用索引可能只需要1s用索引的时机是,数据量巨大,并且搜索快速 索引为什么能实现加速查找 基于索引的内部存储结构索引底层基于 BTree 的数据结构存储的在…...
如何做好档案数字化前的鉴定工作
要做好档案数字化前的鉴定工作,可以按照以下步骤进行: 1. 确定鉴定目标:明确要鉴定的档案的内容、数量和性质,确定鉴定的范围和目标。 2. 进行档案清点:对档案进行全面清点和登记,包括数量、种类、状况等信…...
pytorch04:网络模型创建
目录 一、模型创建过程1.1 以LeNet网络为例1.2 LeNet结构1.3 nn.Module 二、网络层容器(Containers)2.1 nn.Sequential2.1.1 常规方法实现2.1.2 OrderedDict方法实现 2.2 nn.ModuleList2.3 nn.ModuleDict2.4 三种容器构建总结 三、AlexNet网络构建 一、模型创建过程 1.1 以LeNe…...
用js让用户输入一个数累加和
需求:用户输入一个数, 计算 1 到这个数的和。 比如 用户输入的是 5, 则计算 1~5 之间的累加和 并且输出到控制台 <body><script>let numprompt(请输入一个数)let sum0for(let i1;i<num;i){sumi}console.log(sum)</script…...
踩坑记录-安装nuxt3报错:Error: Failed to download template from registry: fetch failed;
报错复现 安装nuxt3报错:Error: Failed to download template from registry: fetch failednpx nuxi init nuxt-demo 初始化nuxt 项目 报错 Error: Failed to download template from registry: fetch faile 解决方法 配置hosts Mac电脑:/etc/hostswin电…...
大数据学习(31)-Spark非常用及重要特性
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦ᾑ…...
【教学类-43-14】 20240103 (4宫格数独:正确版:576套) 不重复的基础模板数量:576套
作品展示::——4宫格 576套不重复模板(48页*12套题) 背景需求: 生成4宫格基础模板768套,观看64页内容时,明显看到有错误 【教学类-43-13】 20240103 (4宫格数独:错误版…...
AIGC开发:调用openai的API接口实现简单机器人
简介 开始进行最简单的使用:通过API调用openai的模型能力 OpenAI的能力如下图: 文本生成模型 OpenAI 的文本生成模型(通常称为生成式预训练 Transformer 或大型语言模型)经过训练可以理解自然语言、代码和图像。这些模型提供文…...
c基础(二)
指针: 含义:是一个值,一个值代表着一个内存地址,类似于存放路径 * 运算符 : 1 字符*表示指针 作用:通常跟在类型关键字的后面,表示指针指向的是什么类型的值 int * foo, * bar;声明指针后会…...
人工智能趋势报告解读:ai野蛮式生长的背后是机遇还是危机?
近期,Enterprise WordPress发布了生成式人工智能在营销中的应用程度的报告,这是一个人工智能迅猛发展的时代,目前人工智能已经广泛运用到内容创作等领域,可以预见的是人工智能及其扩展应用还将延伸到我们工作与生活中的方方面面。…...
三、C语言中的分支与循环—goto语句 (10) (完)
在C语言中,goto语句允许程序无条件地跳转到同一函数内的标记位置。这个标记位置通过一个标签和冒号(:)来标示。goto语句可以用于从深层嵌套的循环或条件语句中直接跳出,或者跳过某些代码执行。尽管goto语句在某些情况下可以使程序逻辑变得清晰࿰…...
RabbitMQ 常见问题
1. 如何保证消息顺序消费 在RabbitMQ中,消息最终会保存在队列中,在同一个队列中,消息是顺序的,保持先进先出的原则,这个由Rabbitmq保证。而不同队列中的消息,RabbitMQ 是无法保证其顺序性。顺序消费主要是…...
阶段二-Day10-日期类
日期类结构: 1.java.util.Date是日期类 2.DateFormat是日期格式类、SimpleDateFormat是日期格式类的子类 Timezone代表时区 3.Calendar是日历类,GregorianCalendar是日历的子类 一. 常用类-Date 1.1 Date构造方法 Date(long date) 使用给定的毫秒时间价值构建…...
多任务并行处理相关面试题
我自己面试时被问过两次多任务并行相关的问题: 假设现在有10个任务,要求同时处理,并且必须所有任务全部完成才返回结果 这个面试题的难点是: 既然要同时处理,那么肯定要用多线程。怎么设计多线程同时处理任务呢&…...
Shell脚本学习笔记
1. 写在前面 工作中,需要用到写一些shell脚本去完成一些简单的重复性工作, 于是就想系统的学习下shell脚本的相关知识, 本篇文章是学习shell脚本整理的学习笔记,内容参考主要来自C语言中文网, 学习过程中,…...
ROS-安装xacro
安装 运行下列命令进行安装,xxxxxx处更改为自己的版本 sudo apt-get install ros-xxxxxx-xacro运行 输入下列命令 roscd xacro如果没有报错,并且进入了xacro软件包的目录,则表示安装成功。 参考: [1]https://wenku.csdn.net/ans…...
为什么说 $mash 是 Solana 上最正统的铭文通证?
早在 2023 年的 11 月,包括 Solana、Avalanche、Polygon、Arbitrum、zkSync 等生态正在承接比特币铭文生态外溢的价值。当然,因铭文赛道过于火爆,当 Avalanche、BNB Chain 以及 Polygon 等链上 Gas 飙升至极值,Arbitrum、zkSync 等…...
安装elasticsearch、kibana、IK分词器、扩展IK词典
安装elasticsearch、kibana、IK分词器、扩展IK词典 后面还会安装kibana,这个会提供可视化界面方面学习。 需要注意的是elasticsearch和kibana版本一定要一样!!! 否则就像这样 elasticsearch 1、创建网络 因为我们还需要部署k…...
Spring中常见的BeanFactory后处理器
常见的BeanFacatory后处理器 先给出没有添加任何BeanFactory后处理器的测试代码 public class TestBeanFactoryPostProcessor {public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();context.registerBean("co…...
FPGA LCD1602驱动代码 (已验证)
一.需求解读 1.需求 在液晶屏第一行显示“HELLO FPGA 1234!” 2. 知识背景 1602 液晶也叫 1602 字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵 型液晶模块。它由若干个 5X7 或者 5X11 等点阵字符位组成,每个点阵字符位都可以显示一 个字符,每位之间有一个点距的…...
c++编程要养成的好习惯
1、缩进 你说有缩进看的清楚还是没缩进看的清楚 2、i和i i运行起来和i更快 3、 n%20和n&1 不要再用n%20来判断n是不是偶数了,又慢又土,用n&10,如果n&10就说明n是偶数 同理,n&11说明n是奇数 4、*2和<<…...
后台管理项目的多数据源方案
引言 在互联网开发公司中,往往伴随着业务的快速迭代,程序员可能没有过多的时间去思考技术扩展的相关问题,长久下来导致技术过于单一。为此最近在学习互联网思维,从相对简单的功能开始做总结,比如非常常见的基础数据的…...
视频美颜SDK趋势畅想:未来发展方向与应用场景
当下,视频美颜SDK正不断演进,本文将深入探讨视频美颜SDK的发展趋势,探讨未来可能的方向和广泛的应用场景。 1.深度学习与视频美颜的融合 未来,我们可以期待看到更多基于深度学习算法的视频美颜SDK,为用户提供更高质量…...
C++ const 限定符的全面介绍
C const 限定符的全面介绍 1. const 修饰基本数据类型 定义 const 修饰的基本数据类型变量,值不可改变。 语法 const type variable value;特点 不可变性,增加代码可读性。 作用 定义不可修改的常量。 使用场景 全局常量、配置项。 注意事项…...
Vue 中的 ref 与 reactive:让你的应用更具响应性(上)
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
华为云CCE-集群内访问-根据ip访问同个pod
华为云CCE-集群内访问-根据ip访问同个pod 问题描述:架构如下:解决方法: 问题描述: 使用service集群内访问时,由于启用了两个pod,导致请求轮询在两个pod之间,无法返回正确的结果。 架构如下&am…...
网站开发移动端多少钱/网站平台如何推广
帧中继( Frame Relay)是一种用于连接计算机系统的面向分组的通信方法。它主要用在公共或专用网上的局域网互联以及广域网连接。大多数公共电信局都提供帧中继服务,把它作为建立高性能的虚拟广域连接的一种途径。1.实验器材3台思科路由器 3台…...
手机做网站服务器吗/短视频获客系统
在子线程中new一个Handler为什么会报以下错误? java.lang.RuntimeException: Cant create handler inside thread that has not called Looper.prepare() 这是因为Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用…...
网站的技术解决方案/域名停靠
1、Microsoft Office Word 2007 是一个文档创作程序,集一组全面的写入工具和易用界面于一体,可以帮助用户创建和共享美观的文档。 2、Microsoft Office Excel 2007 是一个功能强大的电子表格程序,您可以用来分析、交流和管理信息,…...
做外贸需要用什么网站/seo收费还是免费
第四章 Generating DocumentationVP-UML提供了几种产生项目报告的工具。ReportWriter通过跟踪和同步你的项目来简化你的工作。它可以输出HTML或PDF格式的项目报告,还自带了精致的打印工具来打印你建立的视图。在本章中,主要有以下内容:&#…...
员工管理网站模板/什么是精准营销
集合类 2017-07-10 22:24:57 blog site https://github.com/Fiz1994 类型解释: Collection : Set,List 的父类 Set(集):集合中的元素不按特定方式排序,并且没有重复对象。他的有些实现类能对集合中的对象按特定方式排序…...
网站ps照片怎么做的/2023新闻热点摘抄
本文总结华为交换机的配置大全,今天我们一起了解下。华为路由器交换机配置命令:计算机命令PCAlogin:root;使用root用户password:linux;口令是linux#shutdown-hnow;关机#init0;关机#logout;用户注…...