The most obvious way to connect to a data source using the Java programming language is by making use of the JDBC API. MonetDB supplies a 100% pure Java JDBC driver (type 4) which allows to connect and work with a MonetDB database server from a Java program without any other libraries needed.
This document gives a short description how to use the MonetDB JDBC driver in Java applications. Familiarity with the Java JDBC API is required to fully understand this document. Please note that you can find the complete JDBC API on Oracle's web site.
The latest release of the MonetDB JDBC driver has implemented most of the JDBC 4.2 API classes and methods. If you make extensive use of JDBC API and semantics and rely on its features, please report any missing functionality on our Github Java repository.
In order to use the MonetDB JDBC driver in Java applications you need (of course) a running MonetDB/SQL server instance mserver5 process running, preferably using monetdbd.
You can download the latest MonetDB JDBC driver from our MonetDB Java Download Area. You will find a jar file called "monetdb-jdbc-3.X.jre8.jar" where X is the minor version number. It also contains a release notes text file with important information on the JDBC driver release and a ChangeLog with information on what has changed since previous release. In the subdirectory archive you find older releases and a complete ChangeLog-Archive.
This download area also contains the "jdbcclient.jre8.jar" file. This is the JdbcClient user program, a command line program (similar but not equal to mclient) written in Java using the JDBC API, see Jdbc Client for more information.
If you prefer to build the JDBC driver yourself, make sure you acquire the
MonetDB Java repository from monetdb java.
The Java sources are built using Apache's Ant tool
and require JDK 1.8 or higher. For convenience there is also a Makefile
.
Simply issuing the command make
should be sufficient to compile and
build the jar files in the subdirectory called jars
.
There are no dependencies on any external jars or packages.
To use the MonetDB JDBC driver, the monetdb-jdbc-3.X.jre8.jar
java-archive file name has to be in the Java classpath setting. Make
sure this is actually the case. The main MonetDB JDBC Driver class name
is org.monetdb.jdbc.MonetDriver
.
The previous MonetDB JDBC Driver class name nl.cwi.monetdb.jdbc.MonetDriver
has been deprecated and will be removed in a future release, so do NOT use it anymore.
From Febr2021 release (monetdb-jdbc-3.0.jre8.jar) the MonetDB JDBC Driver only works with Java 8 (or higher) JVMs. For Java 7 you can use previous stable release (monetdb-jdbc-2.29.jre7.jar) available from the archive directory.
Using the MonetDB JDBC driver in your Java program:
import java.sql.Connection;
import java.sql.DriverManager;
// request a Connection to a MonetDB server running on 'localhost' (with
// default port 50000) for database demo for user and password monetdb
Connection con = DriverManager.getConnection("jdbc:monetdb://localhost/demo", "monetdb", "monetdb");
The MonetDB JDBC Connection URL string format passed to the
getConnection()
method is defined as:
jdbc:monetdb://<hostname>[:<portnr>]/<databasename>[?<property>=<value>[&<property>=<value>]...]
where elements between <
and >
are required and elements between [
and ]
are optional.
Following optional connection properties are allowed:
user=<login name>
password=<secret value>
debug=true
logfile=<name logfile>
fetchsize=<nr of rows>
so_timeout=<time in milliseconds>
treat_blob_as_binary=false
treat_clob_as_varchar=false
autocommit=false
language=mal
hash=<sha512 or sha384>
For more information see: MonetDB Java release notes text file.
import java.sql.*;
/*
* This example assumes there exist tables a and b filled with some data.
* On these tables some queries are executed and the JDBC driver is tested
* on it's accuracy and robustness against 'users'.
*
* @author Fabian Groffen
*/
public class MJDBCTest {
public static void main(String[] args) throws Exception {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
String con_url = "jdbc:monetdb://localhost:50000/mydb?so_timeout=10000";
// make a connection to the MonetDB server using JDBC URL starting with: jdbc:monetdb://
con = DriverManager.getConnection(con_url, "monetdb", "monetdb");
// make a statement object
st = con.createStatement();
// execute SQL query which returns a ResultSet object
String qry = "SELECT a.var1, COUNT(b.id) AS total" +
" FROM a JOIN b ON a.var1 = b.id" +
" WHERE a.var1 = 'andb'" +
" GROUP BY a.var1" +
" ORDER BY a.var1, total";
rs = st.executeQuery(qry);
// get meta data and print column names with their type
ResultSetMetaData md = rs.getMetaData();
final int colCount = md.getColumnCount();
for (int i = 1; i <= colCount; i++) {
System.out.print(md.getColumnName(i) + ":" + md.getColumnTypeName(i) + "\t");
}
System.out.println("");
// now print the data: only the first 5 rows, while there probably are
// a lot more. This shouldn't cause any problems afterwards since the
// result should get properly discarded when we close it
for (int i = 0; rs.next() && i < 5; i++) {
for (int j = 1; j <= colCount; j++) {
System.out.print(rs.getString(j) + "\t");
}
System.out.println("");
}
// close (server) resource as soon as we are done processing resultset data
rs.close();
rs = null;
// tell the driver to only return 5 rows for the next execution
// it can optimize on this value, and will not fetch any more than 5 rows.
st.setMaxRows(5);
// we ask the database for 22 rows, while we set the JDBC driver to
// 5 rows, this shouldn't be a problem at all...
rs = st.executeQuery("select * from a limit 22");
int var1_cnr = rs.findColumn("var1");
int var2_cnr = rs.findColumn("var2");
int var3_cnr = rs.findColumn("var3");
int var4_cnr = rs.findColumn("var4");
// read till the driver says there are no rows left
for (int i = 0; rs.next(); i++) {
System.out.println(
"[" + rs.getString(var1_cnr) + "]" +
"[" + rs.getString(var2_cnr) + "]" +
"[" + rs.getInt(var3_cnr) + "]" +
"[" + rs.getString(var4_cnr) + "]" );
}
// close (server) resource as soon as we are done processing resultset data
rs.close();
rs = null;
// unset the row limit; 0 means as much as the database sends us
st.setMaxRows(0);
// we only ask 10 rows
rs = st.executeQuery("select * from b limit 10;");
int rowid_cnr = rs.findColumn("rowid");
int id_cnr = rs.findColumn("id");
var1_cnr = rs.findColumn("var1");
var2_cnr = rs.findColumn("var2");
var3_cnr = rs.findColumn("var3");
var4_cnr = rs.findColumn("var4");
// and simply print them
while (rs.next()) {
System.out.println(
rs.getInt(rowid_cnr) + ", " +
rs.getString(id_cnr) + ", " +
rs.getInt(var1_cnr) + ", " +
rs.getInt(var2_cnr) + ", " +
rs.getString(var3_cnr) + ", " +
rs.getString(var4_cnr) );
}
// close (server) resource as soon as we are done processing resultset data
rs.close();
rs = null;
// perform a ResultSet-less statement (with no trailing ; since that
// should be possible as well and is JDBC standard)
int updCount = st.executeUpdate("delete from a where var1 = 'zzzz'");
System.out.println("executeUpdate() returned: " + updCount);
} catch (SQLException se) {
while (se != null) {
System.out.println(se.getSQLState() + ": " + se.getMessage());
se = se.getNextException();
}
} finally {
// when done, close all (server) resources
if (rs != null) try { rs.close(); } catch (Exception e) { }
if (st != null) try { st.close(); } catch (Exception e) { }
if (con != null) try { con.close(); } catch (Exception e) { }
}
}
}
it is no longer required (or recommended) to include code line:
Class.forName("org.monetdb.jdbc.MonetDriver");
as the MonetDriver
class registers itself with the JDBC DriverManager automatically when
the monetdb-jdbc-3.X.jre8.jar file is loaded.