2013-02-20 103 views
0

当尝试使用在Tomcat下运行的Spring创建数据源时,我在数据库驱动程序类上收到ClassNotFoundException。但是,我可以直接从相同的数据访问组件(通过Class.forNamegetClass().getClassLoader().loadClass())加载驱动程序类。驱动程序jar只安装在一个地方($CATALINA_HOME/lib)。无法通过Spring加载数据库驱动程序,但可以在类路径中手动找到它

在Spring配置文件中的数据源定义:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</bean> 

在Spring配置文件中的DAO定义:

<bean id="countryDao" class="com.mycompany.pmo.dao.CountryDao"> 
    <constructor-arg ref="dataSource"/> 
</bean> 

的DAO本身:

public class CountryDao { 
    private NamedParameterJdbcTemplate jdbcTemplate; 

    public CountryDao(DataSource dataSource) { 
     jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); 
    } 

    public List<Country> getCountries() { 
     //I can manually load the driver class here 
     String sql = "select * from ref.country"; 

     Map<String, Object> namedParameters = new HashMap<String, Object>(); 
     //next line is line 34, where the stack trace starts 
     return jdbcTemplate.query(sql, namedParameters,new CountryMapper()); 
    } 
} 

堆栈跟踪:

Feb 20, 2013 2:18:35 PM org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/PMO] threw exception [Request processing failed; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '"com.microsoft.sqlserver.jdbc.SQLServerDriver"'] with root cause 
java.lang.ClassNotFoundException: "com.microsoft.sqlserver.jdbc.SQLServerDriver" 
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714) 
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) 
    at org.apache.commons.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1420) 
    at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371) 
    at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) 
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) 
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:662) 
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:702) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:166) 
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:172) 
    at com.mycompany.pmo.dao.CountryDao.getCountries(CountryDao.java:34) 

回答

4

jar不应该在$CATALINA_HOME/lib。它应该在您的网络应用程序的WEB-INF/lib中。我相信$CATALINA_HOME/lib将用于加载并运行Tomcat,但是您的应用程序类路径依赖项从WEB-INF/lib加载。

如果您正在IDE中开发并在其中运行程序,则可能还需要将该jar添加到项目构建路径中。

+0

感谢您的回应 - 也尝试了一路。行为完全一样。 – Shaun 2013-02-20 19:51:16

+0

只是要清楚 - 我试图从$ CATALINA_HOME/lib中完全删除它,并将它放在WEB-INF/lib中,而不是同时放在两个地方。 – Shaun 2013-02-20 19:52:05

+0

尝试将它添加到构建路径中,例如,如果您使用的是eclipse。 – 2013-02-20 19:52:43

2

As @Sotirios Delimanolis提到(+1)尝试将该jar放在您的应用程序的WEB-INF/lib下。

事实上,该类是使用您的手动代码找到的,并且无法通过Spring找到,表明问题出在类加载器中。当你调用Class.forName()时,你肯定使用了系统类加载器,所以该类从catalina lib目录加载。我无法解释为什么它在你调用getClass().getClassLoader().loadClass()时起作用DAO:在这种情况下,应该使用相同的应用程序类加载器。但是,我可能并不知道Spring是如何与类加载器一起玩的。

+0

在这种情况下,Spring使用Catalina WebappClassLoader,所以问题可能不在于Spring。我建议恢复到新鲜的Tomcat安装,看看是否能解决问题。 Jail在WEB-INF/lib中绝对可以被Catalina classloader接收,除非配置已经被更改。 – rootkit 2013-02-20 21:23:21

相关问题