I have worked with Apache Derby before, but I have never used it in a Gradle Project. I have created a simple Derby Database in the root of my project using ij Derby tool by running the following commands:
connect 'jdbc:derby:MyDbTest;create=true';
CREATE TABLE Hashes (
string_id int,
RandString varchar(255)
);
INSERT INTO Hashes (string_id, RandString) values (1, 'sdfdsfsw');
SELECT * FROM Hashes;
After this, my Java Code in Main.java looks like:
package com.company;
import java.io.File;
import java.sql.*;
public class Main {
public static void main(String[] args) {
System.out.println("Current working directory : "+ new File(".").getAbsolutePath());
try {
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
} catch (Exception e) {
e.printStackTrace(); //Does not get executed!
}
Connection conn = null;
try
{
conn = DriverManager.getConnection("jdbc:derby:MyDbTest"); //Exception here!!
System.out.println("Connected to database MyDbTest");
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(
"select string_id, RandString from Hashes");
while(rs.next()) {
int string_id = rs.getInt("string_id");
String randString = rs.getString("RandString");
System.out.printf("string_id: %s, RandString: %s\n", string_id, randString);
}
}
catch (SQLException sqle)
{
printSQLException(sqle);
} finally {
try {
if (conn != null) {
conn.close();
DriverManager.getConnection("jdbc:derby:;shutdown=true;deregister=false");
}
} catch (SQLException sqle) {
printSQLException(sqle);
}
}
}
public static void printSQLException(SQLException e)
{
//According to this page:
//https://db.apache.org/derby/papers/DerbyTut/embedded_intro.html
//" A clean shutdown always throws SQL exception XJ015, which can be ignored."
if(e.getSQLState().equals("XJ015")) return; //Ignore
// Unwraps the entire exception chain to unveil the real cause of the
// Exception.
while (e != null)
{
System.err.println("\n----- SQLException -----");
System.err.println(" SQL State: " + e.getSQLState());
System.err.println(" Error Code: " + e.getErrorCode());
System.err.println(" Message: " + e.getMessage());
// for stack traces, refer to derby.log or uncomment this:
e.printStackTrace(System.err);
e = e.getNextException();
}
}
}
I seem to be able to load the ClientDriver initially, but then when I try to get a connection to the Database I get the Exception. The first line ensures the Current Working Directory is the root of my project where the MyDbTest database is located.
My build.gradle file looks like:
apply plugin: 'java'
apply plugin:'application'
mainClassName = "com.company.Main"
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'org.apache.derby', name: 'derbyclient', version: '10.14.1.0'
compile group: 'org.apache.derby', name: 'derbytools', version: '10.14.1.0'
runtime group: 'org.apache.derby', name: 'derbyclient', version: '10.14.1.0'
runtime group: 'org.apache.derby', name: 'derbytools', version: '10.14.1.0'
}
A gradle run gives me:
Current working directory : /Users/<myname>/Documents/sources/tempFive/.
----- SQLException -----
SQL State: 08001
Error Code: 0
Message: No suitable driver found for jdbc:derby:MyDbTest
java.sql.SQLException: No suitable driver found for jdbc:derby:MyDbTest
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at com.company.Main.main(Main.java:25)
I have made sure that my Derby Client and my version of the Derby Database is the same. I'm on Mac OSX 10.12 using IntelliJ 2017.3 and Java 8 update 151 if that helps.
EDIT: Why this question is different
I have worked with Apache Derby before and I can get this code to work without Gradle. The two causes of this exception mentioned in the answer to the other question are:
The driver is not loaded. . - If this is true, then why do I not get an exception at the top where I try to load the ClientDriver (Or should I try to load some other class to exclude this possibility.)
The JDBC URL is malformed. - I don't have a problem with this JDBC URL in a non-Gradle Project, so I don't think my URL is wrong. Please correct me if this is incorrect though.
EDIT: Solution (Thanks to Mark Rotteveel)
I was apparently unaware that I was using the Embedded Driver and not the Client Driver. When I used this without Gradle, I used to put all the jars in the entire Derby Lib directory in the classpath without bothering about what was used and what wasn't. My bad. So the first thing to change would be delete the try catch in my main() method:
try {
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
} catch (Exception e) {
e.printStackTrace(); //Does not get executed!
}
The ClientDriver is never used, so there is no point in loading it. Next, as Mark Rotteveel pointed out I only need to depend on org.apache.derby:derby. This was my real mistake, so I put below the complete corrected build.gradle file:
apply plugin: 'java'
apply plugin:'application'
mainClassName = "com.company.Main"
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'org.apache.derby', name: 'derby', version: '10.14.1.0'
}
This is all I needed.
You are using the wrong Derby driver, by using derbyclient, you specify that you want to use the Derby (network) client driver, which supports the URL:
jdbc:derby://server[:port]/databaseName[;URLAttributes=value[;...]]
Your URL doesn't match, so it is rejected by the driver, and eventually java.sql.DriverManager will report that it didn't find a suitable driver.
Instead you need to use the dependency org.apache.derby:derby, as you seem to want to use the Derby Embedded driver. This driver is included in the full derby package, which also includes the Derby database itself, but not in derbyclient. This driver supports URL format:
jdbc:derby:databaseName;URLAttributes
Alternatively you do want to connect to an externally running Derby server, and in that case you are using the wrong URL.
See also Libraries provided by Derby and Database connection URL.
Related
I tried to connect with my PostgreSQL database using the following connection string:
"jdbc:postgresql://localhost:5432/test_stock_game"
I got an error:
No suitable driver found for "jdbc:postgresql://localhost:5432/test_stock_game"
I tried both downloading the driver manually (and setting it as a Gradle dependency) and just adding a dependency for Gradle to download.
This is my build.gradle file:
plugins {
id 'java'
}
group 'org.stock_game'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
//implementation 'org.postgresql:postgresql:42.5.2'
implementation files("libs/postgresql-42.5.2")
}
test {
useJUnitPlatform()
}
I tried the two last lines from "dependencies", but got the same error, although I have the driver in Gradle's libs directory (which is in build directory).
Does anyone know what could be the issue here?
This is the code I am using to connect to the database, if that is helpful:
private DBConnection() {
String jdbcConnectionString = "\"jdbc:postgresql://localhost:5432/test_stock_game\"";
String user = "postgres";
String password = "root";
try {
connection = DriverManager.getConnection(jdbcConnectionString, user, password);
} catch (SQLException e) {
System.err.println("Failed to establish database connection");
e.printStackTrace();
}
}
For some reason I constructed the connection string with quotation marks inside, thinking i needed to include them.
It was like this:
"\"jdbc:postgresql://localhost:5432/test_stock_game\""
Changing it to this:
"jdbc:postgresql://localhost:5432/test_stock_game"
made it work.
Thanks Mark Rotteveel, who spotted that it was an issue.
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.
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.
I'm trying to write a custom Gradle task that would source mysql create and insert statements from a .sql file. This is what I've come up with :-
task initdb() {
def mysql = buildscript.configurations.classpath.find { it.toString().contains("mysql-connector-java") }
// URLClassLoader loader = GroovyObject.class.classLoader
def db = [url: "jdbc:mysql://127.0.0.1/",
user: "root", password: "admin", driver: 'com.mysql.cj.jdbc.Driver']
def sql = groovy.sql.Sql.newInstance(db.url, db.user, db.password, db.driver)
}
I'm getting an error saying Driver class not found. What am I doing wrong here?
The classpath of a Gradle task and the classpaths of your project are not the same thing.
Also the configuration and the execution of a Gradle task are two different things.
You would need the following:
buildscript {
repositories {
mavenCentral() // assuming your driver can be found there, if not, a custom repository
}
dependencies {
// Add the driver, and its dependencies, to the buildscript classpath
classpath "<driver dependency coordinates>"
}
}
task initdb() {
doLast {// Make sure the code is run during execution phase and not configuration phase
def mysql = buildscript.configurations.classpath.find { it.toString().contains("mysql-connector-java") }
// URLClassLoader loader = GroovyObject.class.classLoader
def db = [url: "jdbc:mysql://127.0.0.1/",
user: "root", password: "admin", driver: 'com.mysql.cj.jdbc.Driver']
def sql = groovy.sql.Sql.newInstance(db.url, db.user, db.password, db.driver)
}
}
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.