JDBC03——数据库连接池、DButils、mysql表和JavaBean的数据类型映射关系
基本介绍
问题引出
- 连接5000次数据库
1.不即时关闭连接——抛出异常
package com.recorder.conn; import com.recorder.jdbcutils.JdbcUtils; import org.junit.jupiter.api.Test; /** * @author 紫英 * @version 1.0 * @discription 数据库连接5000问题 */ public class ConQuestion { @Test public void con(){ for (int i = 0; i < 5000; i++) { JdbcUtils.getConnection(); //做一些工作,比如得到 PreparedStatement ,发送 sql // .......... } }
}
2.及时关闭连接——耗费时间过久
package com.recorder.conn; import com.recorder.jdbcutils.JdbcUtils; import org.junit.jupiter.api.Test; import java.sql.Connection; /** * @author 紫英 * @version 1.0 * @discription 数据库连接5000问题 */ public class ConQuestion { @Test public void con() { long start = System.currentTimeMillis(); System.out.println("开始连接....."); for (int i = 0; i < 5000; i++) { Connection connection = JdbcUtils.getConnection(); //做一些工作,比如得到 PreparedStatement ,发送 sql // .......... JdbcUtils.close(null,null,connection); } long end = System.currentTimeMillis(); System.out.println("传统方式5000 次 耗时=" + (end - start));//传统方式 5000次 } }
问题分析
3.就像火车站安检,如果人数过多需要分批进入,一次性涌入会造成混乱。
基本介绍
放回连接池指Java程序不在对连接池中的链接进行引用,该连接依旧存在。
连接池种类
C3P0
第一种方式(不推荐)
public void testC3P0_01() throws Exception { //1. 创建一个数据源对象 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); //2. 通过配置文件 jdbc.properties 获取相关连接的信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\jdbc.properties")); //读取相关的属性值 String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); //给数据源 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++) { Connection connection = comboPooledDataSource.getConnection(); //这个方法就是从 DataSource 接口 实现的 //System.out.println("连接 OK"); connection.close(); } long end = System.currentTimeMillis(); //c3p0 5000 连接 mysql 耗时=391 System.out.println("c3p0 5000 连接 mysql 耗时=" + (end - start)); }
第二种方式(推荐——通过XML配置文件)
//第二种方式 使用配置文件模板来完成 // 1. 将 c3p0 提供的 c3p0.config.xml 拷贝到 src 目录下 // 2. 该文件指定了连接数据库和连接池的相关参数 @Test public void testC3P0_02() throws SQLException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("recorder"); //测试 5000 次连接 long start = System.currentTimeMillis(); System.out.println("开始执行...."); for (int i = 0; i < 5000; i++) { Connection connection = comboPooledDataSource.getConnection(); //System.out.println("连接 OK~"); connection.close(); } long end = System.currentTimeMillis(); //c3p0 的第二种方式 耗时=413 System.out.println("c3p0 的第二种方式(500000) 耗时=" + (end - start)); }
Druid(德鲁伊)
代码演示
可以看出效率还是很高的
package com.recorder.conn; import com.alibaba.druid.pool.DruidDataSourceFactory; import org.junit.jupiter.api.Test; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.util.Properties; /** * @author 紫英 * @version 1.0 * @discription 德鲁伊连接池 */ public class Druid { @Test public 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(); System.out.println("druid 连接池 操作 500000 耗时=" + (end - start)); } }
德鲁伊
c3p0
将 JdbcUtils 工具类改成 Druid(德鲁伊)实现
package com.recorder.jdbcutils; 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; /** * @author 紫英 * @version 1.0 * @discription 基于 druid 数据库连接池的工具类 */ public class JDBCUtilsByDruid { private static DataSource ds; //在静态代码块完成 ds 初始化 static { Properties properties = new Properties(); try { properties.load(new FileInputStream("src\\druid.properties")); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //编写 getConnection 方法 public static Connection getConnection() throws SQLException { return ds.getConnection(); } //关闭连接,这里注意: 在数据库连接池技术中,close 不是真的断掉连接 // 而是把使用的 Connection 对象放回连接池,因为这里的connection是上面的return ds.getConnection()得到的 public static void close(ResultSet set, Statement statement, Connection connection) { try { //判断是否为空 if (set != null) { set.close(); } if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { //将编译异常转成运行异常抛出 throw new RuntimeException(e); } } }
使用德鲁伊工具类:
package com.recorder.jdbcutils; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * @author 紫英 * @version 1.0 * @discription */ public class Druid_use { @Test public void dmlTest(){ //1.得到链接 Connection connection = null; PreparedStatement preparedStatement = null; //2.组织SQL String sql = "insert into admin values(?,?)"; try { connection = JDBCUtilsByDruid.getConnection(); //3.创建preparedstatement对象 preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "admin"); preparedStatement.setString(2, "666"); preparedStatement.executeUpdate(); System.out.println("添加成功"); } catch (SQLException e) { e.printStackTrace(); } finally { //关闭资源 //dml语句没有结果集所以写null JDBCUtilsByDruid.close(null, preparedStatement, connection); } } }
Apache—DBUtils
问题引出
JavaBean
也可以叫domain pojo——指与数据库中表对应的Java类
代码模拟(土方法实现)
package com.recorder.DBUtils; /** * @author 紫英 * @version 1.0 * @discription admin表 */ public class Admin { private String name; private String pwd; public Admin() { //一定要带一个无参构造器,方便底层反射 } @Override public String toString() { return "Admin{" + "name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public Admin(String name, String pwd) { this.name = name; this.pwd = pwd; } }
package com.recorder.DBUtils; import com.recorder.jdbcutils.JDBCUtilsByDruid; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; /** * @author 紫英 * @version 1.0 * @discription 使用土方法来解决 ResultSet =封装=> Arraylist */ public class BeanTest { @Test public /*ArrayList<Admin>*/ void testSelectToArrayList() { System.out.println("使用 druid 方式完成"); //1. 得到连接 Connection connection = null; //2. 组织一个 sql String sql = "select * from admin "; PreparedStatement preparedStatement = null; ResultSet set = null; ArrayList<Admin> list = new ArrayList<>(); //创建 ArrayList 对象,存放 actor 对象 //3. 创建 PreparedStatement 对象 try { connection = JDBCUtilsByDruid.getConnection(); System.out.println(connection.getClass());//运行类型 com.alibaba.druid.pool.DruidPooledConnection preparedStatement = connection.prepareStatement(sql); //执行, 得到结果集 preparedStatement = connection.prepareStatement(sql); set = preparedStatement.executeQuery(); //遍历该结果集 while (set.next()) { String name = set.getString("name"); String pwd = set.getString("pwd"); //把得到的 resultset 的记录,封装到 Actor 对象,放入到 list 集合 list.add(new Admin(name, pwd)); } System.out.println("list 集合数据=" + list); for (Admin admin : list) { System.out.println("name=" + admin.getName() + "\tpwd= " + admin.getPwd()); } } catch (SQLException e) { e.printStackTrace(); } } }
DButils实现封装
下载地址:DbUtils – Download Apache Commons DbUtils
基本介绍
ResultSetHandler结果集处理类(8个实现类)
QueryRunner核心类:
- QueryRunner(DataSource ds) ;传入参数为连接池
- update(String sql, Object… params) ,执行dml语句
- query(String sql, ResultSetHandler rsh, Object… params) ,执行 select操作
代码演示
查询多行(返回一个arraylist——使用 BeanListHandler)
package com.recorder.DBUtils; import com.recorder.jdbcutils.JDBCUtilsByDruid; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.junit.jupiter.api.Test; import java.sql.Connection; import java.sql.SQLException; import java.util.List; /** * @author 紫英 * @version 1.0 * @discription DBUtils + druid完成数据封装 */ public class DBUtils_use { //使用 apache-DBUtils 工具类 + druid 完成对表的 crud 操作 @Test public void queryManyTest() throws SQLException { //1.得到链接(德鲁伊方式) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 执行相关的方法,返回 ArrayList 结果集 String sql = "select * from admin"; //说明 //(1) query 方法就是执行 sql 语句,得到 resultset ---封装到 --> ArrayList 集合中 //(2) 返回集合 //(3) connection: 连接 //(4) sql : 执行的 sql 语句 //(5) new BeanListHandler<>(Actor.class):再将resultset -> Actor 对象 -> 封装到 ArrayList //底层使用反射机制 去获取 Actor 类的属性,然后进行封装 //(6) 1 就是给 sql 语句中的? 赋值,可以有多个值,因为是可变参数 Object... params
//(7) 底层得到的 resultset、PreparedStatment会在 query关闭 List<Admin> admins = queryRunner.query(connection, sql, new BeanListHandler<>(Admin.class)); System.out.println("输出集合的信息"); for (Admin admin : admins) { System.out.println(admin); } //释放资源 JDBCUtilsByDruid.close(null, null, connection); } }
查询单行数据——返回一个对应的Javabean对象(使用BeanHandler)
//使用 apache-DBUtils 工具类 + druid 完成对表的单行数据查询
@Test public void queryManyTest_single() throws SQLException { //1.得到链接(德鲁伊方式) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 执行相关的方法,返回 ArrayList 结果集 String sql = "select * from admin where name = 'along'"; Admin admin = queryRunner.query(connection, sql, new BeanHandler<>(Admin.class)); System.out.println("查询到的的信息:" + admin); //释放资源 JDBCUtilsByDruid.close(null, null, connection); }
查询单行单列(返回一个object对象——使用ScalarHandler)
//使用 apache-DBUtils 工具类 + druid 完成对表的单行单列数据查询 @Test public void queryManyTest_obj() throws SQLException { //1.得到链接(德鲁伊方式) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 执行相关的方法,返回 ArrayList 结果集 String sql = "select pwd from admin where name = 'along'"; Object obj = queryRunner.query(connection, sql, new ScalarHandler()); System.out.println("查询到的的信息:" + obj); //释放资源 JDBCUtilsByDruid.close(null, null, connection); }
DML语句(返回受影响的行数——使用queryRunner.execute)
//使用 apache-DBUtils 工具类 + druid 完成对表的DML @Test public void queryManyTest_dml() throws SQLException { //1.得到链接(德鲁伊方式) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入 DBUtils 相关的 jar , 加入到本 Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 执行相关的方法,返回 ArrayList 结果集 String sql = "update admin set pwd = ? where name = ?"; //String sql = "delete from admin where name = ?"; //String sql = "insert into admin values(?,?)"; int i = queryRunner.update(connection, sql, "alonggiao", "along"); System.out.println(i > 0 ? i + "行更新成功" : "表未受影响"); //释放资源 JDBCUtilsByDruid.close(null, null, connection); }
源码分析
queryRunner.query 方法分析
private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { if (conn == null) { throw new SQLException("Null connection"); } else if (sql == null) { if (closeConn) { this.close(conn); } throw new SQLException("Null SQL statement"); } else if (rsh == null) { if (closeConn) { this.close(conn); } throw new SQLException("Null ResultSetHandler"); } else { PreparedStatement stmt = null; //定义PreparedStatement
ResultSet rs = null; 用于接收返回的ResultSet Object result = null; 作为返回值的ArrayList try { stmt = this.prepareStatement(conn, sql); 创建PreparedStatement this.fillStatement(stmt, params); 对sql语句的占位符(?)进行赋值 rs = this.wrap(stmt.executeQuery()); 执行sql语句,返回ResultSet result = rsh.handle(rs); 将返回的resultset封装到 arraylist【result】(使用反射对传入的class对象进行处理) } catch (SQLException var33) { this.rethrow(var33, sql, params); } finally { try { this.close(rs); 关闭resultset } finally { this.close(stmt); 关闭preparedstatement if (closeConn) { this.close(conn); } } } return result; } }
mysql表和JavaBean的数据类型映射关系
主要可以分为:数值型、字符型和日期型
- 数值型使用对用的包装类
- 字符型对应String
- 日期使用java.util包下面的Date类型
本文来自博客园,作者:紫英626,转载请注明原文链接:https://www.cnblogs.com/recorderM/p/15916949.html