一、应用程序直接获取数据库连接的缺点

  用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。如下图所示:

  

二、使用数据库连接池优化程序性能

2.1、数据库连接池的基本概念

  数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库连接池正式针对这个问题提出来的.数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。如下图所示:

  

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中, 这些数据库连接的数量是由最小数据库连接数来设定的.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中.

数据库连接池的最小连接数和最大连接数的设置要考虑到以下几个因素:

  1. 最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
  2. 最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
  3. 如果最小连接数与最大连接数相差很大:那么最先连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接.不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是空间超时后被释放.

2.2、编写数据库连接池

  编写连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:

  • Connection getConnection()
  • Connection getConnection(String username, String password)

  实现DataSource接口,并实现连接池功能的步骤:

  1. 在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。
  2. 实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。
  3. 当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。Collection保证将自己返回到LinkedList中是此处编程的难点

数据库连接池核心代码

  使用动态代理技术构建连接池中的connection

 proxyConn = (Connection) Proxy.newProxyInstance(this.getClass()
.getClassLoader(), conn.getClass().getInterfaces(),
new InvocationHandler() {
//此处为内部类,当close方法被调用时将conn还回池中,其它方法直接执行
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (method.getName().equals("close")) {
pool.addLast(conn);
return null;
}
return method.invoke(conn, args);
}
});

数据库连接池编写范例:

 package me.gacl.demo;

 import java.io.InputStream;
import java.io.PrintWriter;
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 java.util.Properties;
import javax.sql.DataSource; /**
* @ClassName: JdbcPool
* @Description:编写数据库连接池
* @author: 孤傲苍狼
* @date: 2014-9-30 下午11:07:23
*
*/
public class JdbcPool implements DataSource{ /**
* @Field: listConnections
* 使用LinkedList集合来存放数据库链接,
* 由于要频繁读写List集合,所以这里使用LinkedList存储数据库连接比较合适
*/
private static LinkedList<Connection> listConnections = new LinkedList<Connection>(); static{
//在静态代码块中加载db.properties数据库配置文件
InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
try {
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
//数据库连接池的初始化连接数大小
int jdbcPoolInitSize =Integer.parseInt(prop.getProperty("jdbcPoolInitSize"));
//加载数据库驱动
Class.forName(driver);
for (int i = 0; i < jdbcPoolInitSize; i++) {
Connection conn = DriverManager.getConnection(url, username, password);
System.out.println("获取到了链接" + conn);
//将获取到的数据库连接加入到listConnections集合中,listConnections集合此时就是一个存放了数据库连接的连接池
listConnections.add(conn);
} } catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} @Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
} @Override
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub } @Override
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub } @Override
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
} @Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
} @Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
} /* 获取数据库连接
* @see javax.sql.DataSource#getConnection()
*/
@Override
public Connection getConnection() throws SQLException {
//如果数据库连接池中的连接对象的个数大于0
if (listConnections.size()>0) {
//从listConnections集合中获取一个数据库连接
final Connection conn = listConnections.removeFirst();
System.out.println("listConnections数据库连接池大小是" + listConnections.size());
//返回Connection对象的代理对象
return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(!method.getName().equals("close")){
return method.invoke(conn, args);
}else{
//如果调用的是Connection对象的close方法,就把conn还给数据库连接池
listConnections.add(conn);
System.out.println(conn + "被还给listConnections数据库连接池了!!");
System.out.println("listConnections数据库连接池大小为" + listConnections.size());
return null;
}
}
});
}else {
throw new RuntimeException("对不起,数据库忙");
}
} @Override
public Connection getConnection(String username, String password)
throws SQLException {
return null;
}
}

db.properties配置文件如下:

 driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy
username=root
password=XDP jdbcPoolInitSize=10

写一个JdbcUtil测试数据库连接池

 package me.gacl.utils;

 import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import me.gacl.demo.JdbcPool; public class JdbcUtil { /**
* @Field: pool
* 数据库连接池
*/
private static JdbcPool pool = new JdbcPool(); /**
* @Method: getConnection
* @Description: 从数据库连接池中获取数据库连接对象
* @Anthor:孤傲苍狼
* @return Connection数据库连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return pool.getConnection();
} /**
* @Method: release
* @Description: 释放资源,
* 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
* @Anthor:孤傲苍狼
*
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
} if(conn!=null){
try{
//关闭Connection数据库连接对象
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}

三、开源数据库连接池

  现在很多WEB服务器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的实现,即连接池的实现。通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
  也有一些开源组织提供了数据源的独立实现:

  • DBCP 数据库连接池
  • C3P0 数据库连接池

  在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接。

3.1、DBCP数据源

  DBCP 是 Apache 软件基金组织下的开源连接池实现,要使用DBCP数据源,需要应用程序应在系统中增加如下两个 jar 文件:

  • Commons-dbcp.jar:连接池的实现
  • Commons-pool.jar:连接池实现的依赖库

  Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

3.2、在应用程序中加入dbcp连接池

  1.导入相关jar包
        commons-dbcp-1.2.2.jar、commons-pool.jar
  2、在类目录下加入dbcp的配置文件:dbcpconfig.properties

    dbcpconfig.properties的配置信息如下:

 #连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy
username=root
password=XDP #<!-- 初始化连接 -->
initialSize=10 #最大连接数量
maxActive=50 #<!-- 最大空闲连接 -->
maxIdle=20 #<!-- 最小空闲连接 -->
minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8 #指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly= #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

  如下图所示:

  

  3、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池

 package me.gacl.util;

 import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory; /**
* @ClassName: JdbcUtils_DBCP
* @Description: 数据库连接工具类
* @author: 孤傲苍狼
* @date: 2014-10-4 下午6:04:36
*
*/
public class JdbcUtils_DBCP {
/**
* 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
* DBCP连接池就是java.sql.DataSource接口的一个具体实现
*/
private static DataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try{
//加载dbcpconfig.properties配置文件
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
//创建数据源
ds = BasicDataSourceFactory.createDataSource(prop);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} /**
* @Method: getConnection
* @Description: 从数据源中获取数据库连接
* @Anthor:孤傲苍狼
* @return Connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
//从数据源中获取数据库连接
return ds.getConnection();
} /**
* @Method: release
* @Description: 释放资源,
* 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
* @Anthor:孤傲苍狼
*
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
} if(conn!=null){
try{
//将Connection连接对象还给数据库连接池
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}

  测试DBCP数据源

 package me.gacl.test;

 import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import me.gacl.util.JdbcUtils_DBCP; public class DataSourceTest { @Test
public void dbcpDataSourceTest() {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
//获取数据库连接
conn = JdbcUtils_DBCP.getConnection();
String sql = "insert into test1(name) values(?)";
st = conn.prepareStatement(sql);
st.setString(1, "gacl");
st.executeUpdate();
//获取数据库自动生成的主键
rs = st.getGeneratedKeys();
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
JdbcUtils_DBCP.release(conn, st, rs);
}
}
}

3.3、C3P0数据源

  C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。

  c3p0与dbcp区别
  1. dbcp没有自动回收空闲连接的功能
  2. c3p0有自动回收空闲连接功能

3.4、在应用程序中加入C3P0连接池

  1.导入相关jar包
       c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.2-pre1.jar
  2、在类目录下加入C3P0的配置文件:c3p0-config.xml

    c3p0-config.xml的配置信息如下:

 <?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml必须位于类路径下面
private static ComboPooledDataSource ds;
static{
try {
ds = new ComboPooledDataSource("MySQL");
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
--> <c3p0-config>
<!--
C3P0的缺省(默认)配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">root</property>
<property name="password">XDP</property> <property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config> <!--
C3P0的命名配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy</property>
<property name="user">root</property>
<property name="password">XDP</property> <property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config> </c3p0-config>

  如下图所示:

  

  3、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

  测试C3P0数据源

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

四、配置Tomcat数据源

  在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可。要想让Tomcat服务器在启动的时候帮我们创建一个数据库连接池,那么需要简单配置一下Tomcat服务器。

4.1、JNDI技术简介

  JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
  
套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需
通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。

  Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,通过查看Tomcat文档,我们知道使用如下的方式配置tomcat服务器的数据源:

 <Context>
<Resource name="jdbc/datasource" auth="Container"
type="javax.sql.DataSource" username="root" password="XDP"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbcstudy"
maxActive="8" maxIdle="4"/>
</Context>

  服务器创建好数据源之后,我们的应用程序又该怎么样得到这个数据源呢,Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序。我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:第一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的。第二种就是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可。

  对于上面的name="jdbc/datasource"数据源资源,在应用程序中可以用如下的代码去获取

 Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/datasource");

  此种配置下,数据库的驱动jar文件需放置在tomcat的lib下

  

4.2、配置Tomcat数据源

  1、在Web项目的WebRoot目录下的META-INF目录创建一个context.xml文件

  如下图所示:

  

  2、在context.xml文件配置tomcat服务器的数据源

 <Context>
<Resource
name="jdbc/datasource"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="XDP"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbcstudy"
maxActive="8"
maxIdle="4"/>
</Context>

  3、将数据库的驱动jar文件需放置在tomcat的lib下

  

  4、在获取数据库连接的工具类(如jdbcUtils)的静态代码块中获取JNDI容器中的数据源

 package me.gacl.util;

 import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource; /**
* @ClassName: JdbcUtils_DBCP
* @Description: 数据库连接工具类
* @author: 孤傲苍狼
* @date: 2014-10-4 下午6:04:36
*
*/
public class JdbcUtils_JNDI { private static DataSource ds = null;
//在静态代码块中创建数据库连接池
static{
try{
//初始化JNDI
Context initCtx = new InitialContext();
//得到JNDI容器
Context envCtx = (Context) initCtx.lookup("java:comp/env");
//从JNDI容器中检索name为jdbc/datasource的数据源
ds = (DataSource)envCtx.lookup("jdbc/datasource");
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
} /**
* @Method: getConnection
* @Description: 从数据源中获取数据库连接
* @Anthor:孤傲苍狼
* @return Connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
//从数据源中获取数据库连接
return ds.getConnection();
} /**
* @Method: release
* @Description: 释放资源,
* 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
* @Anthor:孤傲苍狼
*
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
} if(conn!=null){
try{
//将Connection连接对象还给数据库连接池
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}

  写一个Servlet测试JNDI数据源

 package me.gacl.test;

 import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.gacl.util.JdbcUtils_JNDI; public class JNDITest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
//获取数据库连接
conn = JdbcUtils_JNDI.getConnection();
String sql = "insert into test1(name) values(?)";
st = conn.prepareStatement(sql);
st.setString(1, "gacl");
st.executeUpdate();
//获取数据库自动生成的主键
rs = st.getGeneratedKeys();
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
JdbcUtils_JNDI.release(conn, st, rs);
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

C3P0数据库连接池使用方法的更多相关文章

  1. springboot 使用c3p0数据库连接池的方法

    使用springboot开发时,默认使用内置的tomcat数据库连接池,经常碰到这种情况:运行时间一长,数据库连接中断了.所以使用c3p0连接池吧. 引入的maven依赖: <dependenc ...

  2. springboot 使用c3p0数据库连接池

    springboot 使用c3p0数据库连接池的方法  本文转自:http://www.cnblogs.com/xiaosiyuan/p/6255292.html 使用springboot开发时,默认 ...

  3. 【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】

    一.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: package day16.utils; import java.io.IOException; import java.lang.ref ...

  4. paip.提升稳定性---c3p0数据库连接池不能取到连接An attempt by a client to checkout a Connection has timed out

    paip.提升稳定性---c3p0数据库连接池不能取到连接An attempt by a client to checkout a Connection has timed out 作者Attilax ...

  5. [原创]java WEB学习笔记80:Hibernate学习之路--- hibernate配置文件:JDBC 连接属性,C3P0 数据库连接池属性等

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. c3p0数据库连接池(作用不重复)

    /* * c3p0数据库连接池: * 只被初始化一次 * connection对象进行close时,不是正的关闭,而是将该数据连接归还给数据库连接池 * * */ 四个架包 mysql-connect ...

  7. paip.c3p0 数据库连接池 NullPointerException 的解决...

    paip.c3p0 数据库连接池 NullPointerException 的解决... 程序ide里面运行正常..外面bat运行错误.. 作者Attilax  艾龙,  EMAIL:14665198 ...

  8. java配置数据库连接池的方法步骤

    java配置数据库连接池的方法步骤 java配置数据库连接池的方法步骤,需要的朋友可以参考一下   先来了解下什么是数据库连接池数据库连接池技术的思想非常简单,将数据库连接作为对象存储在一个Vecto ...

  9. c3p0 数据库连接池相关知识

    c3p0数据库连接池的配置文件放在eclipse的src目录下,代码就可以识别. c3p0的配置文件的内容如下: <!-- Uncomment and set any of the option ...

随机推荐

  1. AE 创建

    using System; using System.Drawing; using System.Runtime.InteropServices; using ESRI.ArcGIS.ADF; usi ...

  2. 关于uboot下data abort的问题

    在uboot下,常常会出现一些很让人揪心的问题. 解决这些问题的关键就是方法与方向.把握好这两点,一切问题都能够迎刃而解.同一时候也要自信.例如以下: 有时我们会遇到例如以下的出错信息,这时CPU会r ...

  3. JavaSE学习笔记--Item1 注解Annotation

    从 JDK 5.0 開始, Java 添加了对元数据(MetaData) 的支持, 也就是 Annotation(注解). 什么是Annotation,以及注解的作用? 三个主要的 Annotatio ...

  4. GPU 编程入门到精通(三)之 第一个 GPU 程序

    博主因为工作其中的须要.開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程,因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  5. Android 自己定义Activity基类

    我们在开发App的时候有时候碰到多个界面有一个共同点的时候.比方,都有同样的TitleBar.而且TitleBar能够设置显示的文字.TitleBar上的点击事件,假设给每个Activity都写一遍T ...

  6. 【转】Android使用XML Shape绘制带阴影效果的圆形按钮

    众所周知,在Android开发里,为了优化在各种分辨率设备上的显示效果,同一份图片素材往往要提供mdpi.hdpi.xhdpi三种(以前还有ldpi), 尤其是按钮类的素材,考虑到normal.pre ...

  7. createrepo -g /enp/comps.xml .

    cd /enp; createrepo -g /enp/comps.xml .

  8. MSP430 WDT

    MSP430 WDT 有两种模式:1,看门狗  2,定时器 我们这次只用定时器模式,注意有两个决定定时时间的地方:1,时钟源选择  2,间隔时间选择 时钟源可以为:SMCLK 或者 ACLK 时间间隔 ...

  9. MVVMLight消息通知实现机制详解(二)

    接上文 MVVMLight消息通知实现机制详解(一) 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型.Key值.Action.Target(订阅对象本身) 在发生订阅事 ...

  10. hebernate基础学习2---属性

    ---------------------------------------------------------------------------------------------------- ...