今天在做项目的时候碰到一些问题,自己想了想出现的原因,为了备忘,所以记录下。
我的项目是采用Struts、Spring以及jdbc,其中数据库连接池用的是proxool。在写dao实现层代码的时候,发现所有的方法都要用到数据库的操作类,于是就采用spring注入的方式将数据库操作类注入到dao实现层,具体代码如下:
package com.teabar.dao.impl;
import java.util.List;
import com.teabar.dao.BaseDao;
import com.teabar.db.util.DBOperation;
import com.teabar.db.util.DBRowProcessor;
import com.teabar.db.util.SqlGenerator;
public class BaseDaoImpl<T> implements BaseDao<T> {
public DBOperation dbOperate;
/**
* 保存
*/
public void save(T entity, String tableName) {
try {
dbOperate.executeUpdate(SqlGenerator.insertSql(tableName, entity));
} catch (Exception e) {
e.printStackTrace();
} finally {
dbOperate.close();
}
}
@SuppressWarnings("unchecked")
public T findBy(T entity, String tableName) {
T bean = null;
try {
bean = (T) DBRowProcessor.setToBean(
dbOperate.executeQuery(
SqlGenerator.selectSql(tableName, entity)), entity.getClass());
} catch (Exception e) {
e.printStackTrace();
} finally {
dbOperate.close();
}
return bean ;
}
public void delete(T entity, String tableName) {
try {
dbOperate.executeUpdate(SqlGenerator.deleteSql(tableName, entity));
} catch (Exception e) {
e.printStackTrace();
}
}
public void update(String sql) {
try {
dbOperate.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
dbOperate.close();
}
}
/**
* 根据传入的条件语句查找实体,返回相应的实体对象
*/
@SuppressWarnings("unchecked")
public T findBy(String tableName,T entity,String condition) {
T bean = null;
try {
bean = (T) DBRowProcessor.setToBean(
dbOperate.executeQuery(
SqlGenerator.selectSql(tableName, condition)), entity.getClass());
} catch (Exception e) {
e.printStackTrace();
} finally {
dbOperate.close();
}
return bean ;
}
/**
* 取得所有实体对象
*/
public List<T> getAll(String tableName, T entitym) {
return null;
}
/**
* 取得记录总数
*/
public int getTotalRecords(String tableName) {
return 0;
}
public void setDbOperate(DBOperation dbOperate) {
this.dbOperate = dbOperate;
}
}
以下是数据库操作类的代码:
package com.teabar.db.util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import com.teabar.db.DBConnectionManager;
import com.teabar.util.StringUtil;
public class DBOperation {
private DBConnectionManager connectManager;
private Connection connect;
private Vector<Statement> statementGroup;
private Vector<ResultSet> resultSetGroup;
public DBOperation(){
init();
}
public void init(){
this.connectManager = DBConnectionManager.getInstance();
this.connect = this.connectManager.getConnection();
this.statementGroup = new Vector<Statement>();
this.resultSetGroup = new Vector<ResultSet>();
}
public Connection getConnection() {
return this.connect;
}
public Statement getStatement() {
try {
return this.connect.createStatement();
} catch (SQLException e) {
}
return null;
}
public boolean getAutoCommit() throws SQLException{
return this.connect.getAutoCommit();
}
public void setAutoCommit(boolean autoCommit) {
try {
this.connect.setAutoCommit(autoCommit);
} catch (SQLException e) {
}
}
public ResultSet executeQuery(String queryString) throws SQLException{
if(StringUtil.checkNull(queryString))throw new SQLException("sql is null");
Statement localStatement = this.connect.createStatement();
ResultSet localResultSet = localStatement.executeQuery(queryString);
resultSetGroup.add(localResultSet);
statementGroup.add(localStatement);
return localResultSet;
}
public int executeUpdate(String queryString) throws SQLException {
if(StringUtil.checkNull(queryString))throw new SQLException("sql is null");
Statement localStatement = this.connect.createStatement();
this.statementGroup.add(localStatement);
return localStatement.executeUpdate(queryString);
}
public void close() {
try {
if(resultSetGroup!=null) {
for(int i=0; i<resultSetGroup.size(); i++) {
resultSetGroup.get(i).close();
}
resultSetGroup = new Vector<ResultSet>();;
}
if(statementGroup!=null) {
for(int i=0; i<statementGroup.size(); i++) {
statementGroup.get(i).close();
}
statementGroup = new Vector<Statement>();
}
this.connectManager.closeConnection(this.connect);
} catch (SQLException e) {
}
}
}
在spring的配置文件中我是这样配置的:
...... <bean id="dbOperate" class="com.teabar.db.util.DBOperation"/> <bean name="/login" class="com.teabar.web.user.action.LoginAction" scope="request"> <property name="menberService"> <ref bean="menberService"/> </property> </bean> <bean id="menberService" class="com.teabar.service.user.MenberService"> <property name="menberDao"> <ref bean="menberDao"/> </property> </bean> <bean id="menberDao" class="com.teabar.dao.impl.user.MenberDaoImpl"> <property name="dbOperate"> <ref bean="dbOperate"/> </property> </bean> ......
现在,问题就出来了,当我重新部署的时候,控制台报没有注册数据库实例的错误:Attempt to refer to a unregistered pool by its alias......。我仔细想想为什么出现这个错误。分析出以下原因,首先项目中spring的配置文件是以插件的方式加载的如下:
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/> </plug-in>
而struts的配置文件又是在tomcat启动时被加载的,这样就得出了所有的action实例以及bean实例都是在tomcat启动时初始和实例化的,而我取得数据库连接池的操作是在DBOperation 实现的:
......
public DBOperation(){
init();
}
public void init(){
this.connectManager = DBConnectionManager.getInstance();
this.connect = this.connectManager.getConnection();
this.statementGroup = new Vector<Statement>();
this.resultSetGroup = new Vector<ResultSet>();
}
......
而proxool数据库的连接池必须是通过加载它相关的配置文件后实例化得到的,也就是说在tomcat启动的时候加载proxool的配置文件,以下是proxool在web.xml的配置:
<servlet> <servlet-name>ServletConfigurator</servlet-name> <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF/proxool.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
也就是说只有当proxool.xml被加载到内存后,才能进行数据库连接池的操作。而spring的配置文件加载的时间和proxool.xml加载的时间几乎是同一时间,以下可以看出:
...... <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <!--加载顺序,值越小,优先级越高--> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>ServletConfigurator</servlet-name> <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class> <init-param> <param-name>xmlFile</param-name> <param-value>WEB-INF/proxool.xml</param-value> </init-param> <!--加载顺序,值越小,优先级越高--> <load-on-startup>1</load-on-startup> </servlet> ......
所以,struts的配置文件和proxool的配置文件同时被加载,在没有加载proxool配置文件之前就是用数据库的操作就会报没有注册数据库实例的错误。因此,解决错误的方法就是改变加载struts配置文件的优先级,将其改为2即可。
欢迎大家学习交流,有不对的地方望各位指正。