JDBC(二)(3)

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: JDBC(二)(3)

JDBC(二)(2)+https://developer.aliyun.com/article/1556660

7.2.2 DBCP数据库连接池

  • DBCP 是 Apache 软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统:Common-pool。如需使用该连接池实现,应在系统中增加如下两个 jar 文件:
  • Commons-dbcp.jar:连接池的实现
  • Commons-pool.jar:连接池实现的依赖库
  • **Tomcat 的连接池正是采用该连接池来实现的。**该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。
  • 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
  • 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但上面的代码并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。
  • 配置属性说明
属性 默认值 说明
initialSize 0 连接池启动时创建的初始化连接数量
maxActive 8 连接池中可同时连接的最大的连接数
maxIdle 8 连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制
minIdle 0 连接池中最小的空闲的连接数,低于这个数量会被创建新的连接。该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;但是不能太大。
maxWait 无限制 最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待
poolPreparedStatements false 开启池的Statement是否prepared
maxOpenPreparedStatements 无限制 开启池的prepared 后的同时最大连接数
minEvictableIdleTimeMillis 连接池中连接,在时间段内一直空闲, 被逐出连接池的时间
removeAbandonedTimeout 300 超过时间限制,回收没有用(废弃)的连接
removeAbandoned false 超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收

DBCPTest.java

  • 获取连接方式一:
@Test
  public void testGetConnection() throws SQLException{
    //创建了DBCP的数据库连接池
    BasicDataSource source = new BasicDataSource();
    
    //设置基本信息
    source.setDriverClassName("com.mysql.jdbc.Driver");
    source.setUrl("jdbc:mysql:///myDB");
    source.setUsername("root");
    source.setPassword("root");
    
    //还可以设置其他涉及数据库连接池管理的相关属性:
    source.setInitialSize(10);
    source.setMaxActive(10);
    //。。。
    
    Connection conn = source.getConnection();
    System.out.println(conn);
  }
  • 获取连接方式二:
@Test
  public void testGetConnection1() throws Exception{
    Properties pros = new Properties();
    
    //方式1:
//    InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties");
    //方式2:
    FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));
    
    
    pros.load(is);
    DataSource source = BasicDataSourceFactory.createDataSource(pros);
    
    Connection conn = source.getConnection();
    System.out.println(conn);
  }

dbcp.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useServerPrepStmts=false
username=root
password=abc123
initialSize=10
#...

7.2.3 Druid(德鲁伊)数据库连接池

Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、Proxool等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池,可以说是目前最好的连接池之一。

package com.atguigu4.connection;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.junit.Test;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class DruidTest {
  
  @Test
  public void getConnection() throws Exception{
    Properties pros = new Properties();
    
    InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
    
    pros.load(is);
    
    DataSource source = DruidDataSourceFactory.createDataSource(pros);
    Connection conn = source.getConnection();
    System.out.println(conn);
    
  }
}

druid.properties

url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver
initialSize=10
maxActive=20
maxWait=1000
filters=wall
  • 详细配置参数:
配置 缺省 说明
name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.identityHashCode(this)
url 连接数据库的url,不同数据库不一样。例如:mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username 连接数据库的用户名
password 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/使用ConfigFilter
driverClassName 根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrow true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdle false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis 有两个含义: 1)Destroy线程会检测连接的间隔时间2)testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis
connectionInitSqls 物理连接初始化的时候执行的sql
exceptionSorter 根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters 类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

第8章:Apache-DBUtils实现CRUD操作

8.1 Apache-DBUtils简介

  • commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
  • API介绍:
  • org.apache.commons.dbutils.QueryRunner
  • org.apache.commons.dbutils.ResultSetHandler
  • 工具类:org.apache.commons.dbutils.DbUtils

8.2 主要API的使用

8.2.1 DbUtils

  • DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
  • public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
  • public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。
  • public static void commitAndClose(Connection conn)throws SQLException: 用来提交连接的事务,然后关闭连接
  • public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常。
  • public static void rollback(Connection conn)throws SQLException:允许conn为null,因为方法内部做了判断
  • public static void rollbackAndClose(Connection conn)throws SQLException
  • rollbackAndCloseQuietly(Connection)
  • public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。

8.2.2 QueryRunner类

  • 该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
  • QueryRunner类提供了两个构造器:
  • 默认的构造器
  • 需要一个 javax.sql.DataSource 来作参数的构造器
  • QueryRunner类的主要方法:
  • 更新
  • public int update(Connection conn, String sql, Object… params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
  • 插入
  • public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
  • 批处理
  • public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
  • public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句
  • 查询
  • public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
  • 测试
// 测试添加
@Test
public void testInsert() throws Exception {
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
    
  String sql = "insert into customers(name,email,birth)values(?,?,?)";
  int count = runner.update(conn, sql, "何成飞", "he@qq.com", "1992-09-08");
  System.out.println("添加了" + count + "条记录");
    
  JDBCUtils.closeResource(conn, null);
}
// 测试删除
@Test
public void testDelete() throws Exception {
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
  String sql = "delete from customers where id < ?";
  int count = runner.update(conn, sql,3);
  System.out.println("删除了" + count + "条记录");
    
  JDBCUtils.closeResource(conn, null);
}

8.2.3 ResultSetHandler接口及实现类

  • 该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
  • ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
  • 接口的主要实现类:
  • ArrayHandler:把结果集中的第一行数据转成对象数组。
  • ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
  • **BeanHandler:**将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  • **BeanListHandler:**将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
  • ColumnListHandler:将结果集中某一列的数据存放到List中。
  • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
  • **MapHandler:**将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  • **MapListHandler:**将结果集中的每一行数据都封装到一个Map里,然后再存放到List
  • **ScalarHandler:**查询单个值对象
  • 测试
/*
 * 测试查询:查询一条记录
 * 
 * 使用ResultSetHandler的实现类:BeanHandler
 */
@Test
public void testQueryInstance() throws Exception{
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
    
  String sql = "select id,name,email,birth from customers where id = ?";
    
  //
  BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);
  Customer customer = runner.query(conn, sql, handler, 23);
  System.out.println(customer); 
  JDBCUtils.closeResource(conn, null);
}
/*
 * 测试查询:查询多条记录构成的集合
 * 
 * 使用ResultSetHandler的实现类:BeanListHandler
 */
@Test
public void testQueryList() throws Exception{
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
    
  String sql = "select id,name,email,birth from customers where id < ?";
    
  //
  BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
  List<Customer> list = runner.query(conn, sql, handler, 23);
  list.forEach(System.out::println);
    
  JDBCUtils.closeResource(conn, null);
}
/*
 * 自定义ResultSetHandler的实现类
 */
@Test
public void testQueryInstance1() throws Exception{
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
    
  String sql = "select id,name,email,birth from customers where id = ?";
    
  ResultSetHandler<Customer> handler = new ResultSetHandler<Customer>() {
    @Override
    public Customer handle(ResultSet rs) throws SQLException {
      System.out.println("handle");
//      return new Customer(1,"Tom","tom@126.com",new Date(123323432L));
        
      if(rs.next()){
        int id = rs.getInt("id");
        String name = rs.getString("name");
        String email = rs.getString("email");
        Date birth = rs.getDate("birth");
          
        return new Customer(id, name, email, birth);
      }
      return null;
        
    }
  };
    
  Customer customer = runner.query(conn, sql, handler, 23);
    
  System.out.println(customer);
    
  JDBCUtils.closeResource(conn, null);
}
/*
 * 如何查询类似于最大的,最小的,平均的,总和,个数相关的数据,
 * 使用ScalarHandler
 * 
 */
@Test
public void testQueryValue() throws Exception{
  QueryRunner runner = new QueryRunner();
  Connection conn = JDBCUtils.getConnection3();
    
  //测试一:
//  String sql = "select count(*) from customers where id < ?";
//  ScalarHandler handler = new ScalarHandler();
//  long count = (long) runner.query(conn, sql, handler, 20);
//  System.out.println(count);
    
  //测试二:
  String sql = "select max(birth) from customers";
  ScalarHandler handler = new ScalarHandler();
  Date birth = (Date) runner.query(conn, sql, handler);
  System.out.println(birth);
    
  JDBCUtils.closeResource(conn, null);
}


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
9月前
|
Java 关系型数据库 MySQL
JDBC知识【JDBC概述】第一章
JDBC知识【JDBC概述】第一章
|
2天前
|
SQL Java 关系型数据库
JDBC(二)(1)
JDBC(二)(1)
8 0
|
2天前
|
存储 Java 数据库连接
JDBC(一)(1)
JDBC(一)(1)
7 0
|
2天前
|
Java 数据库连接 数据库
JDBC(一)(3)
JDBC(一)(3)
3 0
|
2天前
|
监控 Java 数据库连接
JDBC(二)(2)
JDBC(二)(2)
4 0
|
2天前
|
SQL 存储 Java
JDBC(一)(2)
JDBC(一)(2)
6 0
|
9月前
|
Java 数据库连接 数据库
JDBC知识【JDBC练习】第五章
JDBC知识【JDBC练习】第五章
|
SQL Oracle Java
JDBC 的原理 | 学习笔记
快速学习 JDBC 的原理
137 0
JDBC 的原理 | 学习笔记
|
SQL Java 数据库连接
JDBC(一) 如何使用JDBC进行编程?
JDBC常见操作总结(详略分明)
|
Java 关系型数据库 MySQL
JDBC - 基础篇
JDBC - 基础篇
98 0
JDBC - 基础篇