简体   繁体   English

驱动程序类第一次无法加载

[英]Driver class can't load for first time

I have one servlet class in which I established connection to MySQL database. 我有一个servlet类,我在其中建立了与MySQL数据库的连接。 This is my code for doGet() method. 这是我的doGet()方法的代码。

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
           //Class.forName("com.mysql.jdbc.Driver");    
        con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","rspl123#");
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    System.out.println(con);
    response.getWriter().write(request.getParameter("q"));

}

For above code, when the servlet is called for the first time, exception is thrown that No suitable driver found . 对于上面的代码,当第一次调用servlet时,会抛出异常, No suitable driver found But It runs and connection established successfully for the second time nd onwards. 但它第二次成功运行和连接成功。

java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test
at java.sql.DriverManager.getConnection(DriverManager.java:602)
at java.sql.DriverManager.getConnection(DriverManager.java:185)
at controller.FetchSuggestion.doGet(FetchSuggestion.java:44)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)

null
com.mysql.jdbc.JDBC4Connection@1b83048
com.mysql.jdbc.JDBC4Connection@1455d1c
com.mysql.jdbc.JDBC4Connection@1f51e5c

The above code works fine if I remove the comment from Class.forName() , but it won't work without it for first time and able to establish connection for the second time onwards. 如果我从Class.forName()删除注释,上面的代码工作正常,但如果没有它第一次它并且能够第二次建立连接将无法工作。 FYI : I already have MySQL JAVA connector in my class path. 仅供参考:我的班级路径中已经安装了MySQL JAVA连接器。

MySQL Java Connector version : 5.1.10 MySQL Java Connector版本:5.1.10
JDK : 1.6 JDK:1.6
IDE : MyEclipse for Spring IDE:MyEclipse for Spring

First of , you will need to include the mysql-connector.jar in your classpath. 首先,您需要在类路径中包含mysql-connector.jar You can download the jar from: 你可以从下载jar:

You can then configure your data source connection using the following statements: 然后,您可以使用以下语句配置数据源连接

  // This will load the MySQL driver, each DB has its own driver
  try
  {
  Class.forName("com.mysql.jdbc.Driver");
  }
  catch(ClassNotFoundException e)
  {
  e.printStackTrace();
  }

  // Now you can setup the connection with the DB
   Connection connection=null;
   try {
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/database","username", "password");
 } 
 catch (SQLException e) 
 {
    System.out.println("Connection Failed..!");
    e.printStackTrace();
}

Registering the DriverClassName is a vital step . 注册DriverClassName是至关重要的一步 Kindly do not skip it. 请不要跳过它。

EDIT: I think I found your problem. 编辑:我想我找到了你的问题。 Here's the analysis: 这是分析:

  • The reason your application worked with Class.forName is because you had specifically asked the DriverManager to load this Driver for you . 您的应用程序使用Class.forName的原因是您特意要求DriverManager为您加载此驱动程序
  • The reason that your application did not work for the first time is because you did not specify the Driver to be used. 您的应用程序第一次不起作用的原因是您没有指定要使用的驱动程序。

Let me elaborate on the second point : 让我详细说明第二点

You are absolutely right in saying that the application should work without Class.forName . 完全正确地说应用程序应该在没有Class.forName情况下工作 But aaahhh... There's a catch . 但是aaahhh ...... 有一个问题

  • When you don't specify Class.forName , the DriverManager will try to load as many drivers as it can find and then for any given connection request, it will ask each driver in turn to try to connect to the target URL. 如果未指定Class.forName ,则DriverManager将尝试加载尽可能多的驱动程序,然后对于任何给定的连接请求,它将依次要求每个驱动程序尝试连接到目标URL。

This means that you might have multiple Drivers in your application . 这意味着您的应用程序中可能有多个驱动程序 The DriverManager found these drivers and tried to establish a connection to the database . DriverManager找到了这些驱动程序,并尝试建立与数据库的连接 The connection was null because the first driver found wasn't the right one . 连接为null,因为找到的第一个驱动程序不正确 But wait, DriverManager is smart . 但等等, DriverManager很聪明 It knows it could not connect to the database, so now it uses the other driver found . 它知道它无法连接到数据库,所以现在它使用找到的其他驱动程序 And presto, the connection gets established. 并且,连接已建立。

Check the reference: Driver Interface . 检查参考: 驱动程序接口 It's mentioned in the documentation. 它在文档中提到。

Hope it helps. 希望能帮助到你。 :) :)

By looking at the source code for java.sql.DriverManager I see that the code for loading “initial” drivers (ie not explicitly loaded ones) is triggered by the first attempt to get a driver. 通过查看java.sql.DriverManager的源代码,我看到加载“初始”驱动程序的代码(即未明确加载的驱动程序)是由第一次尝试获取驱动程序触发的。 If another thread tries to get a driver then, the initialize() method does not wait for the ongoing initialization but returns immediately: 如果另一个线程尝试获取驱动程序,则initialize()方法不会等待正在进行的初始化,而是立即返回:

static void initialize() {
    if (initialized) {
        return;
    }
    initialized = true;
    loadInitialDrivers();
    println("JDBC DriverManager initialized");
}

So it's a race condition. 所以这是一场竞争条件。 The second thread will skip the initialization without finding a driver but surely complete before the first thread as not doing the initialization takes lesser time. 第二个线程将跳过初始化而不查找驱动程序但在第一个线程之前肯定完成,因为不进行初始化需要较少的时间。 So it appears as if the first attempt fails but it is the second. 因此看起来好像第一次尝试失败但是第二次失败。

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

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