Java not giving Error! - java

Here is my code - i am simply checking my MySQL database connection.
But first i have compiled and run the program successfully. but then i have commented the line Class.forName .
Still when i compile it runs successfully, without any error.Why?
import java.sql.Connection;
import java.sql.DriverManager;
public class FirstJbdc {
public static void main(String[] args) {
Connection cn=null;
try {
//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("Driver loaded successfully");
cn=DriverManager.getConnection("jdbc:odbc:myDSN","root", "java");
System.out.println("Database connected successfully....");
System.out.println(cn);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

I throws an error, alright. It's just that the
catch (Exception e){
// here the exception is instantiated, but nothing is done about it
}
clause silently swallows your exception.
Try a
System.out.println( e.getMessage() );
in the catch clause

Java 1.6 can find JDBC driver even without using Class.forName.
Here is relevant part of documentation:
The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry:
my.sql.Driver
Applications no longer need to explictly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.

NOTE: this only applies to pre-JDBC 4.0 Drivers.
JDBC drivers are meant to have a static section that registers them with the java.sql.DriverManager when the class is loaded, hence the Class.forName(String) is required.
It's detailed here: http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/drivermanager.html

try {
//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("Driver loaded successfully");
cn=DriverManager.getConnection("jdbc:odbc:myDSN","root", "java");
System.out.println("Database connected successfully....");
System.out.println(cn);
} catch (Exception e) {
// add the following statement
System.out.println(e.getMessage());
}
If you add the statement inside the catch block, then compile and run, you should see the error message like-
[Some Com][Some Driver Manager] Data source name not found and no default driver specified

Without Class.forName(), the JDBC-ODBC bridge driver is not loaded. By JDBC specification, getConnection() returns null if no driver is found for the URL, no exception is thrown. So this is expected behavior.

Related

JDBC No suitable driver found (Minecraft Fabric modding) [duplicate]

This question already has answers here:
Connect Java to a MySQL database
(14 answers)
Closed 1 year ago.
EDIT (fixed):
I found out how to fix this issue, it apperently had something to do with the fact I used gradle to build my project (which is standard for modding with FabricMC). Because of that, I had to add the MySQL Connector/J to the dependencies in the build.gradle file. After that I built another project and the SQL connection worked!
I didn't need to add it as a library or dependency afterward. I also didn't have to load the driver using Class.forName();
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
implementation 'mysql:mysql-connector-java:8.0.27'
}
Im writing a Minecraft mod using the Fabric API in Intellij Idea and need to communicate with a database that's on another server (which is using DirectAdmin).
I've tried a lot of solutions suggested from different questions, like loading the driver first or installing the Database Manager plugin. Those sadly don't seem to solve the problem.
I have also quadruple-checked if I'm using the correct path to the database, which I seem to be doing.
(Im using Java 16, in case that helps)
I tried make the connection, but keep getting the same error:
java.sql.SQLException: No suitable driver found for jdbc
I have included the mysql-connector-java-8.0.27.jar library and am still getting the error.
After that I also added it as a dependency, but it still doesn't work.
Am I missing something here? I've been reading a lot of these posts but none of the solutions seem to work.
Something I'm suspecting is that I have to add some sort of library to the server the database is on as well, but I don't know how I would do that.
This is the code I use to make the connection. I call the connect() method from my Main class, which is in a try/catch
package nl.egelblad.tutorial.sql;
import java.sql.*;
public class MySQL {
private String host = "185.102.34.56";
private String port = "3306";
private String database = "my_db";
private String username = "db_username";
private String password = "db_password";
private Connection connection;
public boolean isConnected() {
return (connection == null ? false : true);
}
public void connect() throws ClassNotFoundException, SQLException {
if (!isConnected()) {
connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false&autoReconnect=true", username, password);
}
}
public void disconnect() {
if (isConnected()) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public Connection getConnection() {
return connection;
}
}
You have to load driver at the beginning (only one time) :
try {
Class.forName("com.mysql.cj.jdbc.Driver");
// Or "com.mysql.jdbc.Driver" for some old mysql driver
} catch(ClassNotFoundException e) {
getLogger().error("Failed to load driver");
e.printStackTrace();
}
Then, you should check that the given jar is exported with good dependencies. Depending or your minecraft version, maybe it's already include. But it's possible that it's not.
So, you have to change your export settings to include the jar mysql-connector-java-8.0.27.jar in your own.

groovy: Caught: java.sql.SQLException: No suitable driver found even if use #GrabConfig(systemClassLoader=true)

I have this test code to connect to a SQL Server:
#GrabConfig(systemClassLoader=true)
#Grab(group='com.microsoft.sqlserver', module='mssql-jdbc', version='9.2.1.jre8')
import groovy.sql.Sql
def server = '10.6.6.1'
def port = '1433'
def user = 'sa'
def password = 'somepassword'
def url = "jdbc:sqlserver://${server}:${port};databaseName=master;"
Sql.withInstance(url, user, password) { sql ->
def serverName = sql.firstRow('SELECT ##SERVERNAME')
assert serverName[0]
}
if I run it I get:
Caught: java.sql.SQLException: No suitable driver found for jdbc:sqlserver://10.6.6.1:1433;databaseName=master;
java.sql.SQLException: No suitable driver found for jdbc:sqlserver://10.6.6.1:1433;databaseName=master;
at test.run(test.groovy:12)
the jar for the driver is downloaded by Grape for sure because inside subdirectories in .groovy/ directory in my home dir I can find it.
But no way I am not able to connect to the server.
I am using groovy 3.0.9 but I tried with older versions and it's the same.
Edit:
If I add to the code before connecting:
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
It works, but it's very strange, I was sure that this is not necessary anymore.
If someone can explain.
it still required to register sql driver in java.sql.DriverManager
every jdbc driver contains approximately the following code usually in XyzDriver class:
static {
try {
java.sql.DriverManager.registerDriver( new XyzDriver() )
} catch (SQLException e) {
...
}
}
the same for microsoft sql driver: https://github.com/microsoft/mssql-jdbc/blob/09d35bfc2338f1fc7c41a958d1e627fa0d6a2b65/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java#L732
that's why you have to call a code like Class.forName("XyzDriver") to make driver self-register in DriverManager
UPD: JDBC 4.0 / java8+
from javadoc: https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html
JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver ...
When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from amongst those loaded at initialization and those loaded explicitly using the same classloader as the current applet or application.
mssql-jdbc-9.2.1.jre8.jar is 4.0 compatible. it contains com.microsoft.sqlserver.jdbc.SQLServerDriver in META-INF/services/java.sql.Driver file
however let's check DriverManager code and how it looks up for drivers:
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/sql/DriverManager.java#l100
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
DriverManager tries to find drivers at the moment it's loaded. so, jdbc driver must be present in classpath at app startup to be auto-registered.
and it's not the case with #Grab in code.
as workaround after grab you could do this to call self-register for all drivers:
ServiceLoader.load(java.sql.Driver.class).iterator().findAll()

Cant connect Java to MariaDB

I cant connect java to MariaDB .I saw all similar questions answers but none has solved my problem. Here is my code :
/** To change this license header, choose License Headers in Project
* Properties. * To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mariadbtest;
import java.sql.*;
/**
*
* #author AAAA
*/
public class MariaDBTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args){
try {
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
String url = "jdbc:MariaDB://localhost:3306/customer"; // url to access the DB
String user = "root";
String pwd="password";
Connection connection = DriverManager.getConnection(url,user,pwd);
System.out.println("Connected to MariaDB");
}
catch (SQLException e) {
System.out.println("SQL Exception: "+ e.toString());
}
catch (ClassNotFoundException cE) {
System.out.println("Class Not Found Exception: "+ cE.toString());
}
catch (Exception ex) {
System.out.println("Exception: "+ ex.toString());
}
// TODO code application logic here
}
}
Note the following :
I am using the connector mysql-connector-java-8.0.22.
I have the latest java version.
MariaDB version is 10.3.27.
I have copied the connector to the lib directory in java folder in program files .
I have added the connector JAR file to my project through properties --> Libraries --> Add JAR/Folder.
MariaDB has the service name MariaDB.
The database name is customer.
error :
SQL Exception: java.sql.SQLException: No suitable driver found for jdbc:MariaDB://localhost:3306/customer
BUILD SUCCESSFUL (total time: 3 seconds)
I think that the problem is that you are using a MySQL Connector/J JDBC driver with a URL that it doesn't recognize. This URL
jdbc:MariaDB://localhost:3306/customer
says to look for a driver from a "MariaDB" provider. But apparently the MySQL drivers don't advertise themselves (via SPI) as being MariaDB drivers.
Solution
First of you should get rid of this:
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
It is not needed, and you are hard-wiring a driver classname into your code. Get rid of the associated exception handler clauses too. (This is all Voodoo Programming stuff. It might have been needed 20 years ago ... but not anymore.)
You can fix the driver resolution problem in two ways:
Change the URL to this:
jdbc:mysql://localhost:3306/customer
According to the MariaDB documentation, the MySQL Connector/J driver is compatible with MariaDB. But use of "MariaDB" in the JDBC url not mentioned in the MySQL Connector/J documentation.
Switch to the MariaDB Connector/J driver. According to the documentation, this should support
jdbc:mariadb://localhost:3306/customer
or
jdbc:mysql://localhost:3306/customer
It is not clear from the docs whether the case of the "protocol" part matters. However, syntax specification in the MariaDB doc uses "mariadb" not "MariaDB", so I would recommend lower-case for stylistic consistency.

DriverManager cant be found, underlines red and prompts me to create class DriverManager

protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException
{
//define the fields
String username = "root";
String password = "Otiwah0771";
String jdbcURL = "jdbc:mysql://localhost:3306/employeedirectory";
String driver = "com.mysql.jdbc.Driver";
try
{
//Get the Print Writer object
PrintWriter out = response.getWriter();
out.println("Connecting to databace"+jdbcURL);
//load the Driver
Class.forName(driver);
//Get the connection
Connection connection = DriverManager.getConnection(jdbcURL,username,password);
//Close the connection
connection.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
** Using Netbeans 11.2 **
I have added mysql connector jar and yet the issue persists (DriverManager symbol cant be found)
Your problem of not being able to import DriverManager can be explained if you have created a modular project, and did not explicitly require the java.sql module. If you don't explicitly require java.sql, you don't get access to the JDBC API, even though it is included with Java.
To fix this, edit module-info.java in the default package (or: the root of your source packages) and add the following line to the body of the module:
requires java.sql;
For example
module examplemodule {
requires java.sql;
}
You should now be able to import java.sql.DriverManager.
Alternatively, don't use a modular project (ie use a project without module-info.java).
As an aside, your code seems to be a servlet, it is generally a bad practice to use DriverManager directly in a web application. Instead use a javax.sql.DataSource backed by a connection pool to create and reuse connections.
Newer drivers of MySQL use the com.cj.mysql.jdbc.Driver class. Class.forname() is no longer required in these newer versions as the connection object will find it itself but see what works for you
The issue is jdbc-api-1.4.jar is not part of the libraries and therefore cannot import java.sql.Driver.class. download jdbc-api-1.4.jar fromjdbc api
- add it to the libraries and it works

Why is java.sql.DriverManager.getConnection() still working after removing the SQLite database JAR?

I'm having difficulties in Java with an SQLITE database provided in a separate JAR file.
Surprisingly, the sqlite database seems to be accessed even after removing the JAR file, exiting and restarting the program and even after rebooting the machine.
I'm using the Xerial driver sqlite-jdbc-3.7.2.jar (for org.sqlite.JDBC).
EDIT: very same issue with sqlite-jdbc-3.8.6.jar.
Xerial JDBC driver is published here:
https://bitbucket.org/xerial/sqlite-jdbc
I'm really puzzled. Is there some kind of persistent cache for this particular JDBC driver? or is it something I missed regarding JDBC in general?
CODE SAMPLE:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqliteJDBCTest {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet rs = null;
try {
Class.forName("org.sqlite.JDBC");
connection = DriverManager.getConnection("jdbc:sqlite::resource:jar:file:doesntexistJAR.jar!/doesntexistDB.sqlite");
System.out.println("connection = " + connection);
statement = connection.createStatement();
System.out.println("statement = " + statement);
rs = statement.executeQuery(" SELECT * FROM nonexistentTable WHERE key = 'nonexistentKey'");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
The above code sample shows the first step of the problem: on the first run, DriverManager.getConnection(..) throwed an exception as expected:
$ java -jar sqliteJDBCTest.jar
java.sql.SQLException: failed to load jar:file:doesntexistJAR.jar!/doesntexistDB.sqlite: java.io.FileNotFoundException: doesntexistJAR.jar (Aucun fichier ou dossier de ce type)
at org.sqlite.Conn.open(Conn.java:92)
at org.sqlite.Conn.<init>(Conn.java:57)
at org.sqlite.JDBC.createConnection(JDBC.java:77)
at org.sqlite.JDBC.connect(JDBC.java:64)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at SqliteJDBCTest.main(SqliteJDBCTest.java:18)
But, since then, for each run I get the following output:
>java -jar sqliteJDBCTest.jar
connection = org.sqlite.Conn#3fee733d
statement = org.sqlite.Stmt#5acf9800
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such table: nonexistentTable)
at org.sqlite.DB.newSQLException(DB.java:383)
at org.sqlite.DB.newSQLException(DB.java:387)
at org.sqlite.DB.throwex(DB.java:374)
at org.sqlite.NativeDB.prepare(Native Method)
at org.sqlite.DB.prepare(DB.java:123)
at org.sqlite.Stmt.executeQuery(Stmt.java:121)
at SqliteJDBCTest.main(SqliteJDBCTest.java:23)
In this example, the SQLException "SQL error or missing database" is not the error we're expecting!
Not only is the database missing, but even the JAR file supposed to contain it!
So how come getConnection() doesn't throw an exception in the first place?
Short answer: because of a bug in the Xerial JDBC driver.
When one requests the Xerial driver a connection by calling DriverManager.getConnection(jdbc:sqlite::resource:jar:file:<local_location_of_JAR>!/<name_of_database_file>), the driver creates a copy of the database file on the temporary directory specified by the Java system property java.io.tmpdir and then operates on this copy.
The problem is that when the original JAR is removed, the driver loads the copy the next time(s) one uses the same getConnection() call. For me, this is a bug; the driver should at least check that the (possibly remote) JAR file pointed to by the URL is still there...
Second problem (the one described in the CODE SAMPLE of this post): when the original JAR file doesn't exist, a "copy" of the (non-existent) database is created, and the next time(s) getConnection() is called with the same parameters, the driver directly returns a phantom connection to this empty database that was never found...
I submitted this story in a bug report on the Xerial JIRA website:
https://bitbucket.org/xerial/sqlite-jdbc/issue/158/drivermanagergetconnection-not-returning

Categories