简体   繁体   English

无法通过Spring加载数据库驱动程序,但可以在类路径上手动找到它

[英]Unable to load database driver via Spring, but can manually find it on the classpath

I'm getting a ClassNotFoundException on a database driver class when attempting to create a data source using Spring running under Tomcat. 尝试使用在Tomcat下运行的Spring创建数据源时,我在数据库驱动程序类上收到ClassNotFoundException。 I am, however, able to load the driver class directly from the same data access component (both via Class.forName and getClass().getClassLoader().loadClass() ). 但是,我能够直接从相同的数据访问组件(通过Class.forNamegetClass().getClassLoader().loadClass() )加载驱动程序类。 The driver jar is only installed in one place ( $CATALINA_HOME/lib ). 驱动程序jar仅安装在一个位置( $CATALINA_HOME/lib )。

The data source definition in the Spring config file: 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>

The DAO definition in the Spring config file: Spring配置文件中的DAO定义:

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

The DAO itself: 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());
    }
}

The stack trace: 堆栈跟踪:

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)

The jar should not be in $CATALINA_HOME/lib . jar不应位于$CATALINA_HOME/lib It should be in WEB-INF/lib of your web app. 它应该在您的Web应用程序的WEB-INF/lib中。 I believe $CATALINA_HOME/lib will be used to load and run Tomcat , but your app classpath dependencies are loaded from WEB-INF/lib . 我相信$CATALINA_HOME/lib将用于加载和运行Tomcat ,但是您的应用程序类路径依赖项是从WEB-INF/lib加载的。

If you are developing in an IDE and running your program in it, you might also have to add the jar to your project build path. 如果要在IDE中进行开发并在其中运行程序,则可能还必须将jar添加到项目构建路径中。

As @Sotirios Delimanolis mentioned (+1) try to put the jar under WEB-INF/lib of your application. 正如@Sotirios Delimanolis提到的(+1),请尝试将jar放在应用程序的WEB-INF/lib下。

The fact that the class is found using your manual code and cannot be found via Spring signals that the problem is in class loader. 该类是使用您的手动代码找到的,而不能通过Spring找不到的事实表明问题出在类加载器中。 When you call Class.forName() you are definitely using the system class loader, so the class is loaded from catalina lib directory. 当您调用Class.forName()您肯定是在使用系统类加载器,因此该类是从catalina lib目录中加载的。 I cannot explain why it works when you are calling getClass().getClassLoader().loadClass() from you DAO: it in this case the same application class loader should be used. 当您从DAO调用getClass().getClassLoader().loadClass()时,我无法解释为什么它起作用:在这种情况下,应使用相同的应用程序类加载器。 But probably I do not know deeply enough how does Spring itself play with class loaders. 但是可能我不太了解Spring本身如何与类加载器一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM