The documentation tells us to load JDBC driver like so
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
https://db.apache.org/derby/papers/DerbyTut/embedded_intro.html
But it works fine without and getting the connection straight away
connection = DriverManager.getConnection("jdbc:derby:" + pathDerby + ";create=true");
Why is that?
Version from the log: Booting Derby version The Apache Software Foundation - Apache Derby - 10.13.1.1 - (1765088)
EDIT:
Actually it is needed if you shut down the Derby engine and want to open it again in the same JWM process (I do this all the time in my integration tests)
After shut down
DriverManager.getConnection("jdbc:derby:;shutdown=true");
You should reopen like this
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
connection = DriverManager.getConnection("jdbc:derby:" + pathDerby + ";create=true");
From official 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 explicitly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.
Related
I have a library method that can be used to connect to a database and then build a document using data from the database.
When they run this app with no parameters, I want to list out all available sql vendor connections. Based on this question I'm guessing its done using ServiceLoader but it's not clear to me exactly how to do this.
And critical to this is I'd like to get the class "com.mysql.jdbc.Driver", and I must get the "jdbc:mysql:" start of the connection string syntax.
So, how can I get the class (optional) and connection string start (necessary) of all JDBC connectors in the classpath?
There is no way defined in JDBC to automatically discover the JDBC URL format of a driver.
You will need to keep a registry of JDBC URL formats yourself (eg linked to one or more drivers), and then using the ServiceLoader or DriverManager, discover the available drivers and use that to determine which URL formats you can use.
Be aware that JDBC allows multiple drivers to use the same JDBC URL format (the first driver to successfully connect 'wins'), and a single driver can have more than one JDBC URL format.
To discover the JDBC drivers on the classpath, you can use
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
for (Driver driver : loadedDrivers) {
// do something with Driver
}
Be aware that using for-each might not be the best solution. Explicitly using the iterator might be better as then you can explicitly handle the ServiceConfigurationError thrown if a specific driver fails to load.
Alternatively, you can use
Enumeration<Driver> drivers = DriverManager.getDrivers();
And let DriverManager take care of discovering the drivers.
Maybe you can use a framework, which abstracts the layer of data access i.e. all the talking to the database?
I could recommend you Spring Data JDBC. https://spring.io/projects/spring-data-jdbc
But there are more frameworks that you could find as OR-Mapper which could help you.
I already know from on JDBC 4.0. and JDK 6, drivers those are found in classpath are automatically loaded. This is the reason we are used to ignoring that Class.forName(dbDriver); line of code when creating JDBC connection.
But recently I installed MySQL Server 8.0.11 and I updated the driver to mysql-connector-java:8.0.11 in my simple Servlet project that runs on tomcat 8.5.30. But it gives me the infamous exception
java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost:3306/mysql at ...
But all my code was working and fine before. So then I added the Class.forName("com.mysql.jdbc.Driver");
And it works. I think I didn't miss anything. Can anyone explain to me what it might be the reason?
The JDBC 4.0 (and higher) automatic driver loading works only if the driver jar is on the initial (system) class path of the application. If you are using Tomcat, the driver would have to be in the <catalina-home>/lib folder.
If you deploy the driver together with your application, then the driver is on the context classpath of that specific application, and it will need to be explicitly loaded using Class.forName.
But in practice, you should not be using DriverManager.getConnection to create connections in a web application. You should be using a data source (preferably with connection pooling), either created and initialized in code, or in the context or server configuration of Tomcat. In that case this problem wouldn't even surface, because either the data source already knows how to get the driver, or you have to explicitly configure it with the driver to use anyway.
From the Java documentation
In previous versions of JDBC, to obtain a connection, you first had to initialize your JDBC driver by calling the method Class.forName.
Any JDBC 4.0 drivers that are found in your class path are automatically loaded. (However, you must manually load any drivers prior to JDBC 4.0 with the method Class.forName.)
I have a jersey Webservice which connects to SQL Server Express 2016. It has sqljdbc42.jar which is 4.2 driver, in the CLASSPATH
However, if I omit the Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver") call, my DriverManager.getConnection throws a SQLException(No suitable driver found for jdbc:sqlserver://localhost:1433; ....")
The getConnection starts succeeding once I add the Class.forName call.
I am on Java 8.
What am I missing?
UPDATE: I just tried a command line program and it works without the forName. However, from my Eclipse IDE where I am running my REST service as a Tomcat 8.0 Server on localhost, it doesn't work.
The drivers are automatically initialized when the class DriverManager is itself initialized thanks to SPI (Service Provider Interface). Which means that internally it will try to find any file META-INF/services/java.sql.Driver available in the context class loader and for each file found, it will create an instance of the class that is defined in the file which in this case is actually the FQN of the JDBC driver, this is how JDBC drivers are automatically initialized starting from JDBC 4.0.
But this can only work, if your driver is available from the context class loader while initializing the class DriverManager. A good way to ensure that is to make your driver available from a Class Loader high enough in the hierarchy. In your case you should put your driver in tomcat/lib. Indeed, this way your driver will be available from the Common CL which should be high enough. More details about the CL hierarchy in Tomcat here.
I am trying to connect to a db2 database from my domino application without using the extension library.
I have created a managed bean that it only connects to the db2 and prints a message on the console.
I call the method of the managed bean from a button on an xpage.
The code in the bean is this:
Class.forName("com.ibm.db2.jcc.DB2Driver");
String url = "jdbc:db2://10.0.1.49:50000/AVIN";
String user = "db2admin";
String password = "ibmdb2";
con = DriverManager.getConnection(url, user, password);
System.out.println("Successful TEST JDBC Connection!!");
I have also configured my build path and added the db2jcc.jar library.
The problem is that i am getting
java.lang.ClassNotFoundException for com.ibm.db2.jcc.DB2Driver
Why is this happening?
Is the DB2 JDBC driver available to your application? I suspect not.
You may need to package the driver in a plugin - within the NSF it will probably hit Java security issues and not work. More recent versions of the Extension Library (the Designer update site install) provide a menu option to Domino Designer to allow you to easily package up a JDBC driver as a plugin, which can then be deployed to your Update Site database.
I strongly recommend using the Extension Library. It will provide robust connection pooling amongst other things. Without it, you may well hit problems already considered and resolved by the experience of the Extension Library developers. If you do hit problems, you may struggle to find anyone with the experience to help you.
Can any one tell the driver name for derby 10.7 in memory mode?
We are using below for in-memory:
org.apache.derby.jdbc.EmbeddedDriver
and below for filesystem based (for previous derby version):
org.apache.derby.jdbc.ClientDriver
I found that for 10.7 , file-system based, driver name should be:
org.hibernate.dialect.DerbyTenSevenDialect
So is there any change for in-memory driver name?
You can access an in-memory database via the embedded driver or the network driver if the in-memory db is exposed to the network. You have to specify the JDBC connection URL correctly though.
http://db.apache.org/derby/docs/10.11/devguide/cdevdvlpinmemdb.html
I don't understand your terminology. Derby has two different environments in which it can run: Embedded, and Client/Server. See: http://db.apache.org/derby/docs/10.8/getstart/cgsquck70629.html
The JDBC driver names that you have (EmbeddedDriver and ClientDriver) are correct. http://db.apache.org/derby/docs/10.8/getstart/rgsquck35368.html
It looks like you are including Hibernate in your application, as DerbyTenSevenDialect is a Hibernate class, not a Derby class. You need to consult the Hibernate community and documentation for Hibernate information.