0

I have an old program from college that I am trying to get to work so I can adapt and use it for something new. This program uses a MySQL database, and using the JDBC framework I add data to my DB. I am using Xampp/PHPMyAdmin to support the database in a web browser format on macOS 11.1.

When I try to compile the driver program for the program using "javac -cp mysql-driver.jar Driver.java", it throws a "cannot find symbol" error for one of the classes being used.

When I tried to compile the driver program with the regular "javac Driver.java", it compiles, and it runs with the "java Driver" command. However, after running it like this, when it comes time to connect to the database it throws a "ClassNotFoundException: com.mysql.jdbc.Driver."

Here is a code snippet for Connecting to the Database:

try{
    Class.forName("com.mysql.jdbc.Driver");
    String dbconn = "jdbc:mysql://" + db.getHostName() +
        "/" + db.getDBName();
    conn = DriverManager.getConnection(dbconn, db.getUsername(), db.getPassword());
    stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
    String query1 = "select * from " + db.getTableName();
        rset = stmt.executeQuery(query1);
.
. 
.
}

I know it needs the driver file to be in the class path so it can actually connect to the DB, but it isn't compiling with the driver file in the class path.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
tzzzy6
  • 1
  • Your question is garbled. The title says that your app won't compile with a `-cp`, and will run without a -cp. The body says that it won't run. Please read your entire question again and correct the contradictions. – Stephen C Jan 11 '21 at 04:10
  • Also, instead of saying "it throws a "cannot find symbol" error for one of the classes being used" ... tell us which class it cannot find. – Stephen C Jan 11 '21 at 04:12
  • Note that when you use `-cp mysql-driver.jar` to set the classpath, the class path does not include the current directory ... or whatever `$CLASSPATH` is set to. This could be the root cause of your compilation problems. The solution *might* be `javac -cp .:mysql-driver.jar ...` – Stephen C Jan 11 '21 at 04:15
  • Sorry for how garbled may question was, however the last answer you gave me was the solution to my problem. Basically, the program would compile and run if I just used "javac Driver.java" then "java Driver," but It wouldn't connect to my database, and when I used "javac -cp mysql-driver.jar" it would say that it couldn't find the symbol for the class that was called by the driver, "ControlFrame.java". The use of "javac -cp .:mysql-driver.jar Driver.java" allows it to actually compile. Thank you. – tzzzy6 Jan 11 '21 at 12:17

1 Answers1

0

There are two key points to understanding what is causing this.

First point is that most JDBC applications need the JDBC driver JAR to be on the runtime classpath, but not the compile time classpath. That is why your (unfortunately named!) Driver class can be compiled like this:

  javac Driver.java

but this fails:

  java Driver

The second point is understanding how the Java tools figure out what the effective classpath is:

  • If you are using java -jar ... to launch an executable JAR, then the classpath is determined solely by what is in the JAR itself.

  • If you are using java or javac with a -cp or -classpath option, then that option gives the classpath.

  • If neither of the above options are used, the CLASSPATH environment variable (if set) provides the classpath.

  • If none of the above define a classpath, then the default classpath is "."; i.e. current directory.

So, when you compiled your class using javac Driver.java, you were most likely compiling with the current directory as the classpath, and the Java compiler was able to find classes that you previously compiled from the current directory.

But when you compiled your class using javac -cp mysql-driver.jar Driver.java, the current directory was NOT the classpath, and the compiler couldn't find the other classes.

Similarly, at runtime java YourMain was not able to find the MySQL driver classes, but java -cp mysql-driver.jar YourMain was not able to find the YourMain class.

The solution is straight-forward: put both the current directory AND the driver JAR on the classpath ... if both are required; e.g.

java -cp .:mysql-driver.jar YourMain.

There are a final point to be made about your "Driver.java" code. You do not need to use Class.forName to load the JDBC driver:

  • The JDBC code in the JVM will find all drivers that are on the classpath, and will automatically load the one that is a provider for the database type in the JDBC url.

  • By hard-wiring the database driver classname into your code, you are making your code database driver specific. In the case of MySQL, the "com.mysql.jdbc.Driver" classname is only correct for the "MySQL Connector/J 5.x" drivers. For the "MySQL Connector/J 8.x" drivers, the correct classname is different.

(Check the documentation if you need to know what the 8.x classname is. But you shouldn't need to know: see above.)

Unfortunately, the internet is full of old examples, and too many people just copy stuff rather than reading the official documentation.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216