注:有些java类是JDK没有的,请到 http://www.findjar.com/index.x 中查找对应的jar包
1. 数据库配置文件 (放在工程的 classpath 下)
database.properties
## oracle ## #c3p0.driver=oracle.jdbc.driver.OracleDriver #c3p0.url=jdbc:oracle:thin:@192.168.1.49:1523:DB02 ## DB2 ## c3p0.driver=com.ibm.db2.jcc.DB2Driver c3p0.url=jdbc:db2://172.20.15.174:50000/test c3p0.user=admin c3p0.password=admin c3p0.initialPoolSize=15 #连接池中保留的最大连接数 c3p0.maxPoolSize=20 #连接池中保留的最小连接数 c3p0.minPoolSize=10 #最大空闲时间,n秒内未使用则连接被丢弃。若为0则永不丢弃 c3p0.maxIdleTime=60 #获得连接的最大等待毫秒数(两次连接中间隔时间) c3p0.acquireRetryDelay=1000 #当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 c3p0.acquireIncrement=15 #定义在从数据库获取新连接失败后重复尝试的次数 c3p0.acquireRetryAttempts=30 #连接关闭时默认将所有未提交的操作回滚 c3p0.autoCommitOnClose=false #连接池内单个连接所拥有的最大缓存statements数 c3p0.maxStatementsPerConnection=100 #通过多线程实现多个操作同时被执行 c3p0.numHelperThreads=10 ### DPCP ### #最大等待秒数,单位为毫秒, 超过时间会报出错误信息 dpcp.maxwait=60000
2. 配置文件解析类
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.log4j.Logger;
/**
* @ClassName: ParsePropertiesFile
* @Description: 解析属性文件(*.properties)
* @author
* @company
* @date 2012-11-8
* @version V1.0
*/
public final class ParsePropertiesFile {
private static final Logger LOG = Logger
.getLogger(ParsePropertiesFile.class);
private static final ParsePropertiesFile instance = new ParsePropertiesFile();
private ParsePropertiesFile() {
}
public static ParsePropertiesFile getInstance() {
return instance;
}
/**
* @Title: getConfig
* @Description: 解析并读取属性文件(*.properties)
* @param propFile
* 属性文件路径
* @return:Map
* @author
* @date 2012-11-8
*/
public Map<String, String> getConfig(String propFile) {
InputStream is = null;
try {
is = this.getClass().getClassLoader().getResourceAsStream(propFile);
Properties prop = new Properties();
prop.load(is);
Set<Entry<Object, Object>> set = prop.entrySet();
Iterator<Entry<Object, Object>> it = set.iterator();
String key = null, value = null;
Entry<Object, Object> entry = null;
while (it.hasNext()) {
entry = it.next();
key = String.valueOf(entry.getKey()).trim();
value = String.valueOf(entry.getValue()).trim();
CommonConstants.propMap.put(key, value);
}
} catch (IOException e) {
LOG.error("parse properties file '"+propFile+"' fail!", e);
} catch (Exception e) {
LOG.error("parse properties file '"+propFile+"' fail!", e);
}
IOUtil.closeStream(is, null);
return CommonConstants.propMap;
}
}
3. IOUtil
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import org.apache.log4j.Logger;
public final class IOUtil {
private static final Logger LOG = Logger.getLogger(IOUtil.class);
private IOUtil() {
}
public static void closeReader(Reader reader) {
if (null != reader) {
try {
reader.close();
reader = null;
} catch (IOException e) {
LOG.error("close reader faile!", e);
}
}
}
public static void closeStream(InputStream is, OutputStream os) {
if (null != is) {
try {
is.close();
is = null;
} catch (IOException e) {
LOG.error("close InputStream fail!", e);
}
}
if (null != os) {
try {
os.close();
os = null;
} catch (IOException e) {
LOG.error("close OutputStream fail!", e);
}
}
}
}
4. CommonConstants
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @ClassName: CommonConstants
* @Description: 公共常量类
* @author wenjianhai
* @company 广州市道一信息技术有限公司
* @date 2012-11-8
* @version V1.0
*/
public final class CommonConstants {
private CommonConstants() {
}
/** 存放属性配置文件(*.properties)中的key-value */
public static Map<String, String> propMap = new ConcurrentHashMap<String, String>(16);
}
5. 初始化配置文件
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.log4j.Logger;
/**
* @ClassName: InitServlet
* @Description: 服务启动时需要初始化
* @author
* @company
* @date 2012-11-8
* @version V1.0
*/
public class InitServlet extends HttpServlet {
/**
* @Fields serialVersionUID : 序列化id
*/
private static final long serialVersionUID = -283273527502774557L;
private static final Logger log = Logger.getLogger(InitServlet.class);
@Override
public void init() throws ServletException {
log.info("Start to init InitServlet.");
// 必须要调用父类的初始化方法
super.init();
// 解析并读取属性文件
ParsePropertiesFile.getInstance().getConfig("database.properties");
log.info("End to init InitServlet.");
}
}
6. 在 web.xml 中配置servlet
<!-- 初始化 --> <servlet> <servlet-name>initServlet</servlet-name> <servlet-class>cn.com.do1.component.init.InitServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>initServlet</servlet-name> <url-pattern>/initServlet</url-pattern> </servlet-mapping>
7. 数据库连接池
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Vector;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.time.StopWatch;
import org.apache.log4j.Logger;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* @ClassName: ConnectionPool
* @Description: 数据库连接池,用于获取第三方数据库的连接
* @author
* @company
* @date 2012-11-15
* @version V1.0
*/
public final class ConnectionPool {
private Vector<Connection> pool;
private int poolSize;// 连接池大小
private static final Logger log = Logger.getLogger(ConnectionPool.class);
// 线程局部变量
protected static ThreadLocal<Connection> threadLocalCon = new ThreadLocal<Connection>();
private static final ConnectionPool instance = new ConnectionPool();
private static DataSource dataSource;
/*
* 私有构造方法,禁止在外部创建本类的对象,要想获得本类的对象,统一通过getInstance()方法。
* 在构造方法中,完成数据池配置文件的加载以及数据池的创建。
*/
private ConnectionPool() {
try {
this.poolSize = Integer.parseInt(CommonConstants.propMap
.get("c3p0.maxPoolSize"));
if (dataSource == null) {
initDataSource();
}
if (null == pool) {
// 根据配置信息创建连接池
pool = new Vector<Connection>(poolSize);
pool = addConnection(poolSize);
}
} catch (Exception e) {
log.error("Init Connection Pool fail!", e);
}
}
/*
* 获取本类的对象
*/
public static ConnectionPool getInstance() {
return instance;
}
/*
* 释放一条连接到连接池中。
*/
public synchronized void release(Connection conn) {
// 重新设置成自动提交(使用事务时,会设置为不自动提交,所以释放连接时,重置成事务自动提交)
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
log.error("set auto commit fail!", e);
} catch (Exception e) {
log.error("set auto commit fail!", e);
}
// 重新放入连接池中
pool.add(conn);
// 从线程变量中移除
threadLocalCon.set(null);
}
/*
* 从连接池中获取一个连接
*/
public Connection getConnection() {
Connection con = threadLocalCon.get();
try {
if (con == null || con.isClosed()) {
while (pool.size() == 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error(e);
}
}
synchronized (this) {
con = pool.get(0);
threadLocalCon.set(con);
}
}
} catch (Exception e1) {
log.error("Get Connection fail!", e1);
}
return con;
}
/*
* 根据传入的参数,在连接池中新建num个连接。
*/
private Vector<Connection> addConnection(int num) {
StopWatch sw = new StopWatch();
sw.start();
Connection conn = null;
try {
// Class.forName(driverClassName);
for (int i = 0; i < num; i++) {
// conn = DriverManager.getConnection(url, username, password);
conn = dataSource.getConnection();
pool.add(conn);
}
} catch (Exception e) {
log.error("add Connection fail!", e);
}
sw.stop();
log.info("end add connection,the time-consuming is:" + sw.getTime());
return pool;
}
/*
* 清空连接池中所有连接。
*/
public synchronized void closePool() {
for (int i = 0; i < pool.size(); i++) {
try {
pool.get(i).close();
} catch (SQLException e) {
log.error("close Connection Pool fail!", e);
} catch (Exception e) {
log.error("close Connection Pool fail!", e);
}
pool.remove(i);
}
}
/*
* 获取当前连接池中可用连接数
*/
public int getAvailableConnectNumber() {
return pool.size();
}
/**
* @Title: initDataSource
* @Description:初始化数据源,使用 DPCP
* @author
* @date 2012-11-16
*/
public static void initDataSourceDpcp() {
// DPCP 连接池
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(CommonConstants.propMap.get("c3p0.driver"));
ds.setUrl(CommonConstants.propMap.get("c3p0.url"));
ds.setUsername(CommonConstants.propMap.get("c3p0.user"));
ds.setPassword(CommonConstants.propMap.get("c3p0.password"));
// 设置从数据源中返回的连接是否采用自动提交机制
ds.setDefaultAutoCommit(Boolean.parseBoolean(CommonConstants.propMap
.get("c3p0.autoCommitOnClose")));
// 最大连接数据库连接数,设置为0时,表示没有限制
ds.setInitialSize(Integer.parseInt(CommonConstants.propMap
.get("c3p0.initialPoolSize")));
// 最大连接数
ds.setMaxActive(Integer.parseInt(CommonConstants.propMap
.get("c3p0.maxPoolSize")));
// 在不新建连接的条件下,池中保持空闲的最少连接数
ds.setMinIdle(Integer.parseInt(CommonConstants.propMap
.get("c3p0.minPoolSize")));
// 最大等待秒数,单位为毫秒, 超过时间会报出错误信息
ds.setMaxWait(Integer.parseInt(CommonConstants.propMap
.get("dpcp.maxwait")));
dataSource = ds;
}
/**
* @Title: initDataSource
* @Description:初始化数据源,使用C3P0
* @author
* @date 2012-11-16
*/
public static void initDataSource() {
// C3P0 连接池
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass(CommonConstants.propMap.get("c3p0.driver"));
} catch (Exception e) {
log.error("load driver class fail!", e);
}
cpds.setUser(CommonConstants.propMap.get("c3p0.user"));
cpds.setPassword(CommonConstants.propMap.get("c3p0.password"));
cpds.setJdbcUrl(CommonConstants.propMap.get("c3p0.url"));
// 初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 initialPoolSize
cpds.setInitialPoolSize(Integer.parseInt(CommonConstants.propMap
.get("c3p0.initialPoolSize")));
// 连接池中保留的最大连接数。Default: 15 maxPoolSize
cpds.setMaxPoolSize(Integer.parseInt(CommonConstants.propMap
.get("c3p0.maxPoolSize")));
// 连接池中保留的最小连接数。
cpds.setMinPoolSize(Integer.parseInt(CommonConstants.propMap
.get("c3p0.minPoolSize")));
// 获得连接的最大等待毫秒数。Default: 1000 acquireRetryDelay
cpds.setAcquireRetryDelay(Integer.parseInt(CommonConstants.propMap
.get("c3p0.acquireRetryDelay")));
// 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 maxIdleTime
cpds.setMaxIdleTime(Integer.parseInt(CommonConstants.propMap
.get("c3p0.maxIdleTime")));
// 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 acquireIncrement
cpds.setAcquireIncrement(Integer.parseInt(CommonConstants.propMap
.get("c3p0.acquireIncrement")));
// 每60秒检查所有连接池中的空闲连接。Default: 0 idleConnectionTestPeriod
// cpds.setIdleConnectionTestPeriod(60);
// 连接关闭时默认将所有未提交的操作回滚。Default: false autoCommitOnClose
cpds.setAutoCommitOnClose(Boolean.parseBoolean(CommonConstants.propMap
.get("c3p0.autoCommitOnClose")));
// maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数
cpds.setMaxStatementsPerConnection(Integer
.parseInt(CommonConstants.propMap
.get("c3p0.maxStatementsPerConnection")));
// c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成,扩展这些操作可以有效的提升性能 .通过多线程实现多个操作同时被执行
cpds.setNumHelperThreads(Integer.parseInt(CommonConstants.propMap
.get("c3p0.numHelperThreads")));
// 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 acquireRetryAttempts
cpds.setAcquireRetryAttempts(Integer.parseInt(CommonConstants.propMap
.get("c3p0.acquireRetryAttempts")));
// 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。Default:
// null preferredTestQuery
// cpds.setPreferredTestQuery("select sysdate from dual");
// 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
// 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
// 等方法来提升连接测试的性能。Default: false testConnectionOnCheckout
// cpds.setTestConnectionOnCheckout(true);
// 如果设为true那么在取得连接的同时将校验连接的有效性。Default: false testConnectionOnCheckin
// cpds.setTestConnectionOnCheckin(true);
// JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default:
// 0
// cpds.setMaxStatements(1);
// 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
// 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
// 获取连接失败后该数据源将申明已断开并永久关闭。Default: false breakAfterAcquireFailure
// cpds.setBreakAfterAcquireFailure(false);
dataSource = cpds;
}
/**
* @Title: beginTransaction
* @Description: 开始事务
* @param conn
* :数据库连接
* @author
* @date 2012-11-16
*/
public static void beginTransaction(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
// 手动提交
conn.setAutoCommit(false);
}
}
} catch (SQLException e) {
log.error("set auto commit to false fail!", e);
} catch (Exception e) {
log.error("begin Transaction fail!", e);
}
}
/**
* @Title: commitTransaction
* @Description: 提交事务
* @param conn
* :数据库连接
* @author
* @date 2012-11-16
*/
public static void commitTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.commit();
}
}
} catch (SQLException e) {
log.error("commit transaction fail!", e);
} catch (Exception e) {
log.error("commit transaction fail!", e);
}
}
/**
* @Title: rollbackTransaction
* @Description: 事务回滚
* @param conn
* :数据库连接
* @author
* @date 2012-11-16
*/
public static void rollbackTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.rollback();
}
}
} catch (SQLException e) {
log.error("rollback transaction fail!", e);
} catch (Exception e) {
log.error("rollback transaction fail!", e);
}
}
/**
* @Title: resetConnection
* @Description: 事务重置
* @param conn
* :数据库连接
* @author
* @date 2012-11-16
*/
public static void resetConnection(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false);
} else {
conn.setAutoCommit(true);
}
}
} catch (SQLException e) {
log.error("reset transaction fail!", e);
} catch (Exception e) {
log.error("reset transaction fail!", e);
}
}
/**
* @Title: setAutoCommit
* @Description: 设置是否自动提交事务
* @param conn
* 数据库连接
* @param autoCommit
* :是否自动提交
* @author
* @date 2012-11-16
*/
public static void setAutoCommit(Connection conn, boolean autoCommit) {
if (conn != null) {
try {
conn.setAutoCommit(autoCommit);
} catch (SQLException e) {
log.error("set Auto Commit fail!", e);
} catch (Exception e) {
log.error("set Auto Commit fail!", e);
}
}
}
}
8. 调用 (DAO层)
/**
* @Title: findExpireNotice
* @Description: 查找2个月后到期的许可证、工商执照
* @param isAll
* 0:查找所有已到期的,1:查找2个月后到期的
* @return List
* @throws Exception
* @see cn.com.do1.component.business.licencenotice.dao.ILicencenoticeDAO#findExpireNotice(int)
* @author
*/
@Override
public List<RmLicense> findExpireNotice(YcBusinessMessagePO bm, int isAll)
throws Exception {
// 获取中间库连接
Connection conn = null;
try {
conn = ConnectionPool.getInstance().getConnection();
} catch (Exception e) {
logger.error("连接中间库失败!", e);
throw new Exception("连接中间库失败!");
}
List<RmLicense> list = new ArrayList<RmLicense>();
String sql = null;
if (0 == isAll) {
// 查找所有已到期的
sql = "select b.license_code,a.CUST_NAME,a.CORPORATION_NAME,"
+ "a.MANAGER,a.MANAGER_TEL "
+ "from rm_cust a,rm_license b where a.cust_id=b.cust_id "
+ " and status='1' and INVALIDATION_DATE<=current date";
} else if (1 == isAll) {
// 查找bm.getWarningLimit()天后到期的
sql = "select b.license_code,a.CUST_NAME,a.CORPORATION_NAME,"
+ "a.MANAGER,a.MANAGER_TEL "
+ "from rm_cust a,rm_license b where a.cust_id=b.cust_id "
+ " and status='1' "
+ " and INVALIDATION_DATE=(current date + "
+ bm.getWarningLimit() + " days)";
}
logger.info("查找2个月后到期的许可证、工商执照,the sql is:\r\n" + sql);
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
RmLicense license = null;
while (rs.next()) {
license = new RmLicense();
license.setLicenseCode(rs.getString("license_code"));
license.setCustName(rs.getString("CUST_NAME"));
license.setCorporationName(rs.getString("CORPORATION_NAME"));
license.setManager(rs.getString("MANAGER"));
license.setManagerTel(rs.getString("MANAGER_TEL"));
list.add(license);
}
ps.close();
ConnectionPool.getInstance().release(conn);
return list;
}