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
", 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("
----- 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.
See Question&Answers more detail:
os