数据库连接池与分页查询
数据库连接池: 由于数据连接资源宝贵,创建连接后又需要关闭连接, 频繁的进行连接打开关闭操作 影响程序的运行效率,采用连接池技术,预先创建一组连接 并采用队列存储这一组连接. 每次从队首取连接,释放连接放入队尾。 增加效率。先自己尝试设计一个简单的连接池。在学习使用已有的常用的连接池组件. 1.自定义连接池:
package com.ctgu.dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
import javafx.scene.control.ComboBox;
/*
* 自定义连接池
*/
public class MyPool {
private static int init_count = 2; //初始化连接数
private static int max_count = 5; //最大连接数
private static int cur_count = 0; //当前连接数
private LinkedList<Connection> pool = new LinkedList<Connection>(); //连接池
public MyPool(){
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < init_count; i++) {
cur_count++;
pool.addLast(createConnection());
}
}
//获取连接
public synchronized Connection getConnection() {
// TODO Auto-generated method stub
Connection conn = null;
if(pool.size() > 0) {
conn = pool.removeFirst();
}else if(cur_count < max_count) {
cur_count++;
conn = createConnection();
}else {
throw new RuntimeException("已达到最大连接");
}
return conn;
}
//释放连接
private synchronized void releaseConnection(Connection conn) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//创建连接
private Connection createConnection() {
Connection proxy = null;
try {
final Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
//使用代理模式,仅重写close方法,这样当用户直接调用close 方法时也能 将连接放入连接池
proxy = (Connection) Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
new Class[] {Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
String name = method.getName();
System.out.println("++++代理++++:"+name);
if("close".equals(name)) {
if(pool.size() < 2) {
pool.addLast(conn);
}else{
if(conn != null) {
try {
conn.close();
cur_count--;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}else {
method.invoke(conn, args);
}
return null;
}
});
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return proxy;
}
//测试
public static void main(String[] args) {
MyPool pool = new MyPool();
Connection conn1 = pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
Connection conn2 = pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
Connection conn3 = pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
pool.releaseConnection(conn1);
//pool.getConnection();
System.out.println("当前连接:" + pool.cur_count);
try {
conn2.close();
conn3.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("当前连接:" + pool.cur_count);
}
}
2.使用现有的连接池组件: 要实现连接池技术,都需要实现一个接口: javax.sql.DataSource ,这个接口称为数据源,DataSource 接口应该由驱动程序供应商实现,其中包括了连接池的实现 a. DBCP连接池 使用需要导入包: Commons- dbcp.jar Commons-pool.jar 下载:http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
//dbcp连接池核心类BasicDataSource
BasicDataSource dataSource = new BasicDataSource();
//初始化参数配置
dataSource.setUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setInitialSize(3); //初始化连接数
dataSource.setMaxActive(5); //允许的最大连接数
dataSource.setMaxIdle(3000); //最大空闲时间,超时未使用的连接将自动回收
try {
Connection conn = dataSource.getConnection();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
简单的做法是将初始化参数写入配置文件properties中,配置文件的键应该是固定写法,如:
url=jdbc:mysql:///test
driverClassName=com.mysql.jdbc.Driver
username=root
password=123456
initialSize=3
maxActive=6
maxIdle=3000
然后通过DataSource dataSource = BasicDataSourceFactory.createDataSouce(Properties properties); 创建配置好的数据源对象 b. C3P0连接池 需要的jar包 c3p0-version.jar mchange-commons-java-0.2.11.jar 下载: http://www.mchange.com/projects/c3p0/
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//ComboPooledDataSource也实现了DataSource 接口
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); //设置数据库地址
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver"); //设置驱动
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setInitialPoolSize(3); //初始连接池大小
dataSource.setMaxIdleTime(2000); //最大空闲时间
dataSource.setMaxPoolSize(5); //最大连接数
try {
Connection conn = dataSource.getConnection();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
c3p0也可以从配置文件加载初始化参数, 它提供了默认配置文件模板,只需在上改动即可,并且会默认加载src目录下面的配置文件: 注意命名: c3p0-config.xml
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">3000</property>
</default-config>
<!-- 可以配置多个数据库,在创建对象时指定name参数,说明调用哪个配置
<named-config name="dumbTestConfig">
<property name="maxStatements">200</property>
<property name="jdbcUrl">jdbc:test</property>
<user-overrides user="poop">
<property name="maxStatements">300</property>
</user-overrides>
</named-config>
-->
</c3p0-config>
可以看出数据库连接池使 java用jdbc连接数据库变得简单 并且高效。当在使用DButils组件进行数据库的操作时,可直接使用 QueryRunner qr=newQueryRunner(DataSource); 传入一个数据源对象即可,会自动进行连接的创建与释放. 分页 分页技术用于在页面中将多条数据分页显示。 关键点:sql 中 limit关键字可以限制查询数据的条数 select * from user limit 10; 查询10行 select * from user limit 10,10; 从第11行开始向后查询10行
分页实现:
代码结构: 其中PageBean实体类,封装保存当前的页数,每页显示的数据条数,页面的总页数,以及每页返回的数据。
indexservlet调用EmployeeServciceImpl处理数据请求,将返回数据传递给 list.jsp 显示。 效果图:
源码: https://github.com/ctguggbond/pagination