常规Java程序对数据库进行操作,每次新的Java程序都需要重新建立它本身的数据库链接对象。很显然,如果多个Java程序都需要访问数据库,则需要重复执行这个对性能消耗较多的操作。故而为了节省性能,引入了数据库连接池的概。
什么是数据库连接池
- 顾名思义,数据集合存放的池子。一开始先在内存中开辟一块儿空间(集合),一开始向这块儿空间中放置多个事前准备好的半成品连接对象。如果有类似引言中出现的多个程序都需要数据连接对象的情况出现,则无需自己建立连接,从这个空间中取出使用即可。
- 这里可能出现一些问题:
a) 一些连接被借出之后,使用完是需要归还的,否则数据库连接池则会消失。
b) 这个连接池本身需要有应对需求大于库存的情况,例如预备了10个链接,来了11个对象申请。此时,需要自动扩容(反之,如果发现初始放的多了,也可以减容)。但是,扩容有个最终上限,达到这个上限在之后则强制新的申请暂时等待。
数据库连接池的作用
- 更快的速度:直接从连接池内获取连接,节省了自己创建的时间,提高了服务效率
- 节省内存:通过连接池尽可能的重用内存,提高了复用率,能够支持更多的客户服务
- 管理监督:可以通过自身的管理机制来对连接池进行管理监督,监视使用情况等
自定义连接池简析
- 针对上面的对于连接池的阐述,我们可以自己创建一个测试用例。Mydatasource类。这个类继承自Datasource。那么很显然,我们首先需要一个方来,来使用For循环建立一个集合来充当池子的角色,同时,我们需要写一个方法来接收程序返还的连接如addback()。每当一个程序需要使用连接池,就使用我们创建的这个类,需要返回时候就使用我们写的这个方法。
- 这样写有几个问题:
a) 对象没有做成单例:每次使用都需要New Mydatasource(),多个对象的声明则意味着不止一个池子
b) 额外记忆addback方法:这个方法是我们自己写的,sun公司写的 Datasource类里面只有close方法。我们自己用没问题,如果别人用就有问题了。
c)非面向接口编程:由于我们的连接池直接定义成了一个类,并且里面还额外添加了一个addBack方法,这就造成了我们无法面向接口编程
装饰者模式
针对自定义数据库连接的问题,想到的解决方案
- 修改源代码,使源代码中直接把Close方法内容实现了addback方法。当然,这是不可实现的
- 自建类,继承Connection接口实现类,然后在close方法的基础上,加入回收逻辑。由于无法判定Connection接口实现类是哪一个,也无法实现。
- 故而引入装饰者模式:主要就是用来扩展类,扩展开放,修改关闭。类的继承虽然也能实现扩展行为,但是它的粒度没有装饰者模式细,而且当有多个类需要被一个行为装饰时,你可能需要写多个继承对象。 装饰者模式必然有一个公共的接口或抽象类,用来作为对象的传递。你需要根据接口实现基本的被装饰类(Person),以及装饰类的公共接口(Decorator ),以后所有的装饰类都是继承自公共的装饰类接口,内部实现
开源连接池(DBCP & C3P0)
-
定义:DBCP(DataBase Connection Pool)数据库连接池,是java数据库连接池的一种,由Apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开
-
使用:
2.1 导入jar包
2.2 不使用配置文件方式BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/数据库名"); dataSource.setUsername("账号"); dataSource.setPassword("密码"); conn = dataSource.getConnection(); String sql = "sql语句"; pstmt = conn.prepareStatement(sql);
2.3 使用配置文件方式
2.3.1 在 src 下定义配置文件 dbcp.poperties.driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbc username=用户名 password=密码
2.3.2 使用代码读取配置文件,即可获取连接池
Properties properties = new Properties(); properties.load(new FileInputStream("src/dbcp.properties")); DataSource dataSource = BasicDataSourceFactory.createDataSource(properties); conn = dataSource.getConnection(); String sql = "sql语句"; pstmt = conn.prepareStatement(sql);
-
定义:C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等
-
使用:
2.1 导入jar包
2.2 不使用配置文件方式ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost/users"); dataSource.setUser("root"); dataSource.setPassword("root"); conn = dataSource.getConnection(); String sql = "select * from user"; pstmt = conn.prepareStatement(sql);
2.3 使用配置文件方式
c3p0的配置文件 支持 properties , 也支持 xml 方式。 不过开发中,一般使用xml方式来配置。
2.3.1 src下, 创建xml文件,名为:c3p0-config.xml 注意此处,名字需要固定<c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost/user</property> <property name="user">root</property> <property name="password">root</property> <!-- 可选配置 --> <property name="initialPoolSize">5</property> </default-config> </c3p0-config>
2.3.2 代码中获取连接child对象
ComboPooledDataSource dataSource = new ComboPooledDataSource();