背景:今天要运行之前存在而且可以执行的老项目,这个老项目已经存在很久了,而且上个月运行的时候还是正常的,但是今天一运行就总是报错。主要就是数据源无法连接。
想了一下,主要原因是数据库的地址已经改了,所以只要找到数据库的地址并进行修改应该就可以了。
在我的项目下面有一个配置文件:config.properties。看到这个文件下面有如下的信息:
db.datasource=java:comp/env/jdbc/onecard
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1/onecard?useUnicode=true&characterEncoding=GBK
db.username=root
db.password=
果断地把url地址改了!再一看,密码也不对,也把密码修改了。修改完了之后,把服务器重启了一下,发现问题还是存在。
为什么我把url和密码都修改正确了还是报错?(这个问题纠结了小半天)
难道修改的地方不对吗?
耐下心来看代码,嗯,确实是修改的地方不对。
看到代码里初始化时有这样的代码片段:
jdbc = new JDBC();
jdbc.startTransaction();
(下面的JDBC方法是JDBC的对象的一个无参构造函数)
public JDBC() {
this.jndi = SystemBasicInfo.DATASOURCE;
use_DATASOURCE_OR_DRIVER_AND_URL = 1;
}
(下面的方法是JDBC对象的一个方法,上面引用到了)
public void startTransaction() {
try {
if (conn == null || conn.isClosed()) {
this.init();
}
this.conn.setAutoCommit(false);
} catch (Exception e) {
MyOutput.error("startTransaction Error:" + e.getMessage());
}
}
(下面的方法也是JDBC对象里的一个方法,在startTransaction方法中有引用)
public void init() throws SQLException {
try {
/**
* 使用连接池的方式
*/
if(use_DATASOURCE_OR_DRIVER_AND_URL == 1){
if (SystemBasicInfo.dbmodeflag) {
Context initCtx = new InitialContext();
ds = (DataSource) initCtx.lookup(this.jndi);
if (ds != null) {
conn = ds.getConnection();
}
} else {
conn = DBCP.getInstance().getConn();
}
}
/**
* 直接连接的方式
*/
if(use_DATASOURCE_OR_DRIVER_AND_URL == 2){
Class.forName(this.driver);
conn = DriverManager.getConnection(url, user, password);
DatabaseMetaData dbmd = conn.getMetaData();
System.out.println("Driver = " + dbmd.getDriverName() + "_" + dbmd.getDriverVersion());
}
if (conn != null) {
if (this.toBeManaged)
ConnectionObjectsManager.getInstance().beManaged(conn);
}
} catch (SQLException e) {
MyOutput.error("Connection Error:" + e.getMessage());
throw e;
} catch (NamingException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
(SystemBasicInfo对象里有这样的代码片段)
ResourceBundle bundle = ResourceBundle.getBundle("conf");
DB_MODE = bundle.getString("db.mode");
if (DB_MODE.equals("jndi")) {
dbmodeflag = true;
MyOutput.debug("Connection mode is:jndi");
MyOutput.debug("Datasource is:" + DATASOURCE);
} else if (DB_MODE.equals("dbcp")) {
dbmodeflag = false;
MyOutput.debug("Connection mode is:dbcp");
MyOutput.debug("Db DRIVER is:" + DB_DRIVER);
MyOutput.debug("Db URL is:" + DB_URL);
MyOutput.debug("Db USERNAME is:" + DB_USERNAME);
MyOutput.debug("Db PASSWORD is:" + DB_PASSWORD);
MyOutput.debug("Db MAXACTIVE is:" + DB_MAXACTIVE);
MyOutput.debug("Db MAXIDLE is:" + DB_MAXIDLE);
MyOutput.debug("Db MAXWAIT is:" + DB_MAXWAIT);
MyOutput.debug("Db Type is:" + DB_TYPE);
} else {
MyOutput.error("无效的数据库连接方式!");
}
( 在config.properties配置文件中有这样的代码片段)
db.mode=jndi
db.datasource=java:comp/env/jdbc/onecard
根据这一段代码:
Context initCtx = new InitialContext();
ds = (DataSource) initCtx.lookup(this.jndi);
这段代码我刚开始的时候也没注意到什么意思的,后来百度了一下,百度参考:http://zhidao.baidu.com/link?url=a3YfTZR6kQHWYTw9U9H0aSFm0OIGN8v7EnJOJGtxJab_QlA7_n4uSMEl1Qr6Pm32STrNlD7I04ptAO-CD_0Etq
感谢这位热心的朋友tiehualong。
从这里可以看到实际上,我们的数据源是使用tomcat配置文件的comp/env/jdbc/onecard这个数据源。
关于java:comp/env/jdbc/onecard的解释,可以参考我们论坛的“feiy08”的小议java:comp/env
http://blog.csdn.net/feiy08/article/details/3482190
最终在配置tomcat的配置文件:server.xml中找到了相关的配置项:
<Resource name="jdbc/onecard" type="javax.sql.DataSource"
password="onecard" driverClassName="com.mysql.jdbc.Driver" maxIdle="2"
maxWait="10000" username="root" url="jdbc:mysql://192.168.226.128:3328/onecard?useUnicode=true&characterEncoding=utf-8&reConnect=true"
maxActive="50" />
<Context
docBase="onecard" path="/onecard"
privileged="true">
<ResourceLink name="jdbc/onecard" global="jdbc/onecard" type="javax.sql.DataSource"/>
</Context>
在这里修改数据源jdbc/onecard的url路径,然后重启tomcat就可以了!
在这次的学习中发现了一个很致命的问题,那就是以经验为准。由于之前的项目数据源什么的都是在配置文件里面写的,很少在tomcat中使用,所以自然而然的,看到配置文件中有一个相关或者类似的配置项,就想当然的去进行修改了。这是一种错误的经验。
我们做项目,不要以经验为主导,而以实际的代码是主体。在拿到项目之后,先打断点进行调试,看看所有的参数和方法都是周末调用的,从整体上去了解整个系统,把握住整个系统的脉络,之后,再去做一些修改