数据库连接池
1、连接池原理

目的:解决建立数据库连接消耗资源和时间很多的问题,提高性能。
2、编写标准的数据源
自定义数据库连接池要实现javax.sql.DataSource接口,一般都叫数据源。
public class MyDataSource implements DataSource {
private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>());
static {
try {
for (int i = 0; i < 10; i ++) {
Connection conn = DBUtils.getConnection();
pool.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化数据库连接失败,请检查配置文件是否正确");
}
}
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
if (pool.size() > 0) {
conn = pool.removeFirst();
MyConnection myConn = new MyConnection(conn,pool);
return myConn;
} else {
throw new RuntimeException("服务器忙");
}
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
3、编写数据源时遇到的问题和解决方法
装饰设计模式:使用频率很高
目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
口诀:
1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
2、定义一个被包装类类型的变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
5、对于需要改写的方法,写自己的代码
public class MyConnection implements Connection {
private Connection oldConnection;
private LinkedList<Connection> pool;
public MyConnection(Connection oldConnection, LinkedList<Connection> pool) {
this.oldConnection = oldConnection;
this.pool = pool;
}
@Override
public void close() throws SQLException {
//重写关闭方法
pool.addLast(oldConnection);
}
@Override
public Statement createStatement() throws SQLException {
return oldConnection.createStatement();
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return oldConnection.prepareStatement(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return oldConnection.prepareCall(sql);
}
........
}
public class Test {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
DataSource ds = new MyDataSource();
try {
conn = ds.getConnection();
ps = conn.prepareStatement("sql");
//.......
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
默认适配器:装饰设计模式一个变体
1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
2、定义一个被包装类类型的变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
常用的数据源配置(日后都使用数据源,一定要配置一下)
DBCP
DBCP:Apache推出的Database Connection Pool
使用步骤:
- 添加jar包 commons-dbcp-1.4.jar commons-pool-1.5.6.jar
- 添加属性资源文件
- 编写数据源工具类
public class DBCPUtils {
private static DataSource ds = null;
static {
Properties prop = new Properties();
try {
//根据DBCPUtiles的class,加载配置文件
prop.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));
ds = BasicDataSourceFactory.createDataSource(prop);//得到一个数据源
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化错误,请检查配置文件");
}
}
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException("服务器忙。。。");
}
}
public void release(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
C3P0
使用步骤:
1、添加jar包
2、编写配置文件
c3p0-config.xml,放在classpath中,或classes目录中
<?xml version="1.0" encoding="utf-8" ?>
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///testdb</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
<user-overrides user="test-user">
<property name="maxPoolSize">10</property>
<property name="minPoolSize">1</property>
<property name="maxStatements">0</property>
</user-overrides>
</default-config>
</c3p0-config>
3、编写工具类:
public class C3P0Util {
private static ComboPooledDataSource cpds = new ComboPooledDataSource();
public static Connection getConnection() {
try {
return cpds.getConnection();
} catch (SQLException e) {
throw new RuntimeException("服务器错误");
}
}
public void release(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
用JavaWeb服务器管理数据源:Tomcat
开发JavaWeb应用,必须使用一个JavaWeb服务器,JavaWeb服务器都内置数据源。
Tomcat:(DBCP)
数据源只需要配置服务器即可。
配置数据源的步骤:
1、拷贝数据库连接的jar到tomcatlib目录下
2、配置数据源XML文件
- 如果把配置信息写在tomcat下的conf目录的context.xml中,那么所有应用都能使用此数据源。
- 如果是在当前应用的META-INF中创建context.xml, 编写数据源,那么只有当前应用可以使用。
<Context>
<Resource name="jdbc/TomcatDBCP" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:///day13"/>
</Context>
3、使用连接池
<%
Context initContext = new InitialContext();
// Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)initContext.lookup("java:/comp/env/jdbc/TomcatDBCP");
Connection conn = ds.getConnection();
out.print(conn);
%>
JNDI:java nameing directory interface
JNDI容器就是一个Map
key(String) | value(Object) |
---|---|
path+name | 对象 |
path+"jdbc/day16" | DataSource对象 |
网友评论