下面会详细介绍一种最实用的数据库链接池的详细介绍及其使用------德鲁伊(druid)java
通过上面的介绍,咱们须要建立一个链接池,以供咱们链接数据库操做,在没用链接池以前,用户访问数据库的时候都是本身建立链接对象的。mysql
咱们使用了链接池以后:从系统开始启动的时候就会建立一个工厂对象,里面有必定数量的数据库链接对象,用户使用的时候直接会从池子里拿链接对象,不须要本身在建立了。git
链接池解决现状问题的原理github
Connection链接对象 | 操做特色 |
---|---|
建立时 | 链接对象再也不由本身建立,而是系统启动的时候已经建立必定数量的链接, 而且放在链接池中 |
使用时 | 直接从链接池中去获取一个已经建立好的链接对象便可 |
关闭时 | 不是真的关闭链接对象,而是将链接对象再放回到链接池中,供下一个用户使用 |
数据源接口中的方法:sql
DataSource接口中的方法 | 描述 |
---|---|
Connection getConnection() | 从链接池中获取链接对象 |
每一个链接池都会有不少的参数,每一个参数都有不一样的含义,几乎全部的参数都是由默认值的,参数名在不一样的链接池中表明的意思也有所差别!数据库
经常使用参数 | 描述 |
---|---|
初始链接数 | 服务器启动的时候建立的链接对象数量 |
最大链接数 | 链接池中最多能够容许放多少个链接对象 |
最长等待时间 | 若是链接池中没有链接对象,设置用户等待的最长时间是多久,单位是毫秒。 若是超过这个时间就抛出异常 |
最长空闲回收时间 | 若是一个链接对象长时间没有人使用,设置多久回收这个对象,默认是不回收。 |
DataSource自己是Oracle公司提供的一个接口,自己没有具体的实现,它的实现由各大链接池的数据库厂商去实现,咱们只须要学习如何使用就ok了。服务器
经常使用的链接池组件:ide
Druid是阿里巴巴开发的号称为监控而生的数据库链接池,在功能、性能、扩展性方面,都超过其余数据库链接池。Druid已经在阿里巴巴部署了超过600个应用,通过一年多生产环境大规模部署的严苛考验。如:一年一度的双十一活动,每一年春运的抢火车票。工具
Druid的下载地址:https://github.com/alibaba/druid性能
DRUID链接池使用的jar包:druid-1.0.9.jar
参数 | 说明 |
---|---|
url | 链接字符串 |
username | 用户名 |
password | 密码 |
driverClassName | 驱动类名,会自动根据URL识别,这一项能够不配置 |
initialSize | 初始链接数 |
maxActive | 最大链接数 |
maxWait | 最长等待时间 |
Druid链接池API介绍
Class类中的方法 | 说明 |
---|---|
InputStream getResourceAsStream(String path) | 加载类路径下配置文件,转成一个输入流对象 |
DruidDataSourceFactory的方法 | 方法 |
---|---|
public static DataSource createDataSource(Properties properties) | 经过属性集合中属性,建立一个链接池 |
导包:
.properties配置文件:
url=jdbc:mysql://localhost:3306/test username=root password=root driverClassName=com.mysql.jdbc.Driver initialSize=5 maxActive=10 maxWait=2000
java代码:
public class Demo2Druid { public static void main(String[] args) throws Exception { //1.从类路径下加载配置文件,获取一个输入流。若是不指定路径,默认是读取同一个包下资源文件 InputStream inputStream = Demo2Druid.class.getResourceAsStream("/druid.properties"); //2.使用Properties对象的方法将配置文件中属性加载到Properties对象中 Properties properties = new Properties(); //加载了配置文件中全部的属性 properties.load(inputStream); //3.经过druid的工厂类建立链接池 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); //获取10个链接对象 for (int i = 1; i <= 11; i++) { Connection connection = dataSource.getConnection(); System.out.println("第" + i + "个链接对象:" + connection); //第3个链接关闭 if (i==3) { connection.close(); } } } }
可是若是超过了数据库最大链接数量:
可是咱们让第三个关闭了链接,至关于还给链接池一个链接对象,因此会打印是以个结果:(有两个地址值是相同的!)
使用Druid链接池来获取链接对象,达到提高访问数据库速度目的
package com.aoshen.Test; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.Properties; public class JDBCUtils { //声明链接池对象 private static DataSource dataSource; //使用静态,是类加载的时候就建立链接池 static{ try { //读取配置文件 InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid"); //获取Properties对象,加载到该对象中 Properties properties = new Properties(); //获取配置文件 properties.load(inputStream); //建立druid工厂 dataSource = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //获取数据库链接 public static Connection getConn() throws SQLException { return dataSource.getConnection(); } /** * 关闭链接 * 查询调用这个方法 */ public static void close(Connection connection, Statement statement, ResultSet resultSet) { try { if (resultSet != null) { resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (statement != null) { statement.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } /** * 关闭链接 * 增删改没有结果集 */ public static void close(Connection connection, Statement statement) { //直接调用上面的方法 close(connection, statement, null); } /** * 通用的增删改方法 */ public static int update(String sql,Object...args){ Connection conn = null; PreparedStatement ps = null; //返回影响的行数 int row = 0; try{ //获取链接 conn = getConn(); //获取预编译对象 ps = conn.prepareStatement(sql); //获取元数据,获得有多少占位符 ParameterMetaData metaData = ps.getParameterMetaData(); int count = metaData.getParameterCount(); //循环获取赋值 for (int i = 0; i < count; i++) { ps.setObject(i+1,args[i]); } //执行SQL语句 row = ps.executeUpdate(); }catch (Exception e){ e.printStackTrace(); }finally { close(conn,ps); } return row; } /** * 通用的查询方法 */ public static <T> List<T> equery(String sql,Class<T>c,Object...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; //建立集合用于接收数据库中查的值 List<T>list = new ArrayList<>(); try{ //获取链接 conn = getConn(); //获取预编译对象 ps = conn.prepareStatement(sql); //经过获取元数据给占位符赋值 ParameterMetaData metaData = ps.getParameterMetaData(); int count = metaData.getParameterCount(); for (int i = 0; i < count; i++) { ps.setObject(i+1,args[i]); } //执行sql rs = ps.executeQuery(); //遍历集合,封装到集合中吗,一行数据封装一个对象 while (rs.next()){ //每条记录封装成一个对象 T t = c.newInstance(); //获得实体类中有哪些列名 Field[] fields = c.getDeclaredFields(); //遍历赋值 for (Field field : fields) { //获取列名 String name = field.getName(); //获取内容 Object value = rs.getObject(name); //由于是私有的,要暴力反射 field.setAccessible(true); //把最后获得的值赋值给建立的对象中 field.set(t,value); } //把最后含每一行值的对象添加到集合中 list.add(t); } }catch (Exception e){ e.printStackTrace(); }finally { close(conn,ps,rs); } return list; } }
使用工具类
/** * 使用工具类 */ public class Demo3UseUtils { public static void main(String[] args) { //使用工具类添加1条记录 int row = JdbcUtils.update("insert into student values(null,?,?,?)", "嫦娥", 0, "1997-07-07"); System.out.println("添加了" + row + "条"); //使用工具类查询全部的数据 List<Student> students = JdbcUtils.query("select * from student", Student.class); //打印 students.forEach(System.out::println); } }
修改了链接的获取方式