为什么使用数据库连接池技术
- 对于一个简单的数据库应用,由于对于数据库的访问不是很频繁。这时可以简单地在需要访问数据库时,就新创建一个连接,用完后就关闭它,这样做也不会带来什么明显的性能上的开销。但是对于一个复杂的数据库应用,情况就完全不同了。频繁的建立、关闭连接,会极大的减低系统的性能,因为对于连接的使用成了系统性能的瓶颈。
- 连接复用。通过建立一个数据库连接池以及一套连接使用管理策略,使得一个数据库连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。
- 对于共享资源,有一个很著名的设计模式:资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,就是建立一个数据库连接池,提供一套高效的连接分配、使用策略,最终目标是实现连接的高效、安全的复用。
- 数据库连接池的基本原理是在内部对象池中维护一定数量的数据库连接,并对外暴露数据库连接获取和返回方法。如:外部使用者可通过getConnection 方法获取连接,使用完毕后再通过releaseConnection方法将连接返回,注意此时连接并没有关闭,而是由连接池管理器回收,并为下一次使用做好准备。
几种主流的连接池技术及其特点
- 在目前技术前沿比较流行的数据库连接池有:DBCP、Tomcat Jdbc Pool、BoneCP、Druid、C3P0等
- DBCP:由Apache开发的一个Java数据库连接池项目, Jakarta commons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。单线程,并发量低,性能不好,适用于小型系统。
- Tomcat Jdbc Pool:Tomcat在7.0以前都是使用common-dbcp做为连接池组件,但是dbcp是单线程,为保证线程安全会锁整个连接池,性能较差,dbcp有超过60个类,也相对复杂。Tomcat从7.0开始引入了新增连接池模块叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,超级简单核心文件只有8个,支持JMX,支持XA Connection。
- BoneCP:官方说法BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计初衷就是为了提高数据库连接池性能,根据某些测试数据显示,BoneCP的速度是最快的,要比当时第二快速的连接池快25倍左右,完美集成到一些持久化产品如Hibernate和DataNucleus中。BoneCP特色:高度可扩展,快速;连接状态切换的回调机制;允许直接访问连接;自动化重置能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;较好的Java代码组织,100%单元测试分支代码覆盖率;代码40KB左右。
- Druid:Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;Druid是一个开源项目,源码托管在github上。
- C3p0:开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。单线程,性能较差,适用于小型系统,代码600KB左右。
JDBCTemplate介绍
- JDBC已经能够满足大部分用户最基本的需求,但是在使用JDBC时,必须自己来管理数据库资源如:获取PreparedStatement,设置SQL语句参数,关闭连接等步骤。
- JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。JdbcTemplate处理了资源的建立和释放。他帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。
- 在JdbcTemplate中执行SQL语句的方法大致分为3类:
(1)execute:可以执行所有SQL语句,一般用于执行DDL语句。
(2)update:用于执行INSERT、UPDATE、DELETE等DML语句。
(3)queryXxx:用于DQL数据查询语句。
使用MVC开发模式利用durid连接池和JDBCTemplate搭建数据库
-
使用mvc模式创建项目,数据操作层StudentDaoImpl,实体类Student,工具类JdbcUtils。
以下是整个数据库搭建的项目整体结构
-
准备druid连接池
- 导入jar包:druid-1.0.9.jar
- 在src路径下创建druid.properties文件
- 将以下内容复制到druid.properties文件中:driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db_qbj(要进行数据操作的数据库名)?characterEncoding=utf-8&unicode=true
username=root(你的数据库连接账户)
password=root(你的数据库连接密码)
initialSize=5
maxActive=10
maxWait=3000
-
导入JdbcTemplate依赖的jar包
mysql-connector-java-5.1.6-bin.jar
spring-beans-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-jdbc-4.2.4.RELEASE.jar
spring-tx-4.2.4.RELEASE.jar
commons-logging-1.1.1.jar
如果使用的是idea编写的,在lib中导入所有的包后记得鼠标右键点击lib,选择Add as Library后点击OK。 -
在工具类中创建方法getDs()获取druid资源
package Util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.util.Properties;
public class JdbcUtils {
private static DataSource ds;
static{
Properties pro = new Properties();
try {
pro.load(JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDs() {
return ds;
}
}
- 创建实体类Student
package entity;
public class Student {
private String Sno; //学号
private String Sname; //姓名
private String Ssex; //性别
private int Sgrade; //成绩
public String getSno() {
return Sno;
}
public void setSno(String sno) {
Sno = sno;
}
public String getSname() {
return Sname;
}
public void setSname(String sname) {
Sname = sname;
}
public String getSsex() {
return Ssex;
}
public void setSsex(String ssex) {
Ssex = ssex;
}
public int getSgrade() {
return Sgrade;
}
public void setSgrade(int sgrade) {
Sgrade = sgrade;
}
}
- 在StudentDaoImpl类中创建JdbcTemplate对象,传入Druid连接池,写入要进行的数据操作语句。
使用步骤:
- 1.创建JdbcTemplate对象
- 2.编写要执行的SQL语句
- 3.使用JdbcTemplate对象相应的数据库操作方法
- JdbcTemplate 数据操作方法:
- update(),用于增删改操作。
- queryForObject(),JdbcTemplate查询-queryForObject返回String
- queryForMap(),JdbcTemplate查询-queryForMap返回一个Map集合
- queryForList(),JdbcTemplate查询-queryForList返回一个List集合
- RowMapper<>(),JdbcTemplate查询-RowMapper返回自定义对象
- BeanPropertyRowMapper<>(Product.class),JdbcTemplate查询-BeanPropertyRowMapper返回自定义对象
以下是对student数据操作的源码:
package Daoimpl;
import entity.Student;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import Util.JdbcUtils;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public class StudentDaoImpl {
//创建JdbcTemplate对象,传入Druid连接池
private JdbcTemplate template = new JdbcTemplate(JdbcUtils.getDs());
//增加数据
public void test1(){
String sql = "insert into student values(?,?,?,?);";
template.update(sql, "1813004745", "邋遢男","男",61);
template.update(sql, "1813004747", "小胖子","男",70);
template.update(sql, "1813004748", "帅哥哥","男",89);
}
//修改数据
public void test2(){
String sql = "update student set Sno=? where Sname=?;";
template.update(sql,"1813004311","网页");
}
//删除数据
public void test3(){
String sql = "delete student where Sno=?;";
template.update(sql,"1001122");
}
//查询-queryForObject()返回一个自定义类型
public void test4(){
String sql = "SELECT Sname FROM student WHERE Sno=?;";
String str = template.queryForObject(sql,String.class, "1813004748");
System.out.println(str);
}
//查询-queryForMap返回一个Map集合
public void test5(){
String sql = "SELECT * FROM student WHERE Sno=?;";
Map<String, Object> map = template.queryForMap(sql, "1813004748");
System.out.println(map);
}
//查询-queryForList返回一个List集合
public void test6() {
String sql = "SELECT * FROM student WHERE Sgrade<?;";
List<Map<String, Object>> list = template.queryForList(sql, 90);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
//查询-RowMapper返回自定义对象
public void test7(){
String sql = "SELECT * FROM Student;";
List<Student> query = template.query(sql, new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet rs, int arg1) throws SQLException {
Student S = new Student();
S.setSno(rs.getString("Sno"));
S.setSname(rs.getString("Sname"));
S.setSname(rs.getString("Ssex"));
S.setSgrade(rs.getInt("Sgrade"));
return S;
}
});
for (Student student : query) {
System.out.println(student);
}
}
//查询-BeanPropertyRowMapper返回自定义对象
public void test8(){
String sql = "SELECT * FROM Student;";
List<Student> list = template.query(sql, new BeanPropertyRowMapper<>(Student.class));
for (Student student : list) {
System.out.println(student);
}
}
}
- 测试
package Test;
import Daoimpl.StudentDaoImpl;
public class Test {
public static void main(String [] args ) {
StudentDaoImpl jdi = new StudentDaoImpl();
jdi.test1();
jdi.test2();
jdi.test3();
jdi.test4();
jdi.test5();
jdi.test6();
jdi.test7();
jdi.test8();
}
}