James Ahlborn Jackcess Cookbook

This cookbook will attempt to familiarize the reader with the various nooks and crannies of the Jackcess API. The API is large due to the large feature-set that an Access Database provides, so this cookbook will by no means be exhaustive. However, this will hopefully give the reader enough useful building blocks such that the rest of the API can be discovered and utilized as necessary.

This cookbook is a cross between a tutorial and a reference, so the reader should be able to skip to relevant sections without needing to read the entire preceding text.

While this cookbook strives to present best practices for both the Jackcess API and Java programming in general, at times, the code may be trimmed for the sake of brevity. For the same reason, pseudo-code may be used in places where the actual code is not relevant to the example.

So you have an Access Database and you want to do something with it. You want to use Java, and you may not even be running on Windows (or you tried the JDBC/ODBC bridge and it failed miserably). Through some Google-fu, you landed here at the Jackcess project. Now what?

Well, the first thing you need to do is open the database. The entry point class in the Jackcess API is, suprisingly enough, the Database class.

Database db = Database.open(new File("mydb.mdb"));

That's it, now you have a Database instance (maybe this isn't that difficult after all).

Important note, always make sure you close a Database instance when you are finished with it (preferably in a finally block like any other important resource). Failure to close the Database instance could result in data loss or database corruption.

Okay, so you have a Database instance, now what? Since pretty much everything in an Access database lives in a table, grabbing a Table would be the logical next step.

Table table = db.getTable("Test");

Where's the data? While a Cursor is the best way to interact with the data in a Table, for the sake of simplicity when just getting started, we will use the simplified iteration provided by the Table class itself. When reading row data, it is generally provided as a Map<String,Object> where the keys are the column names and the values are the strongly typed column values.

for(Map<String,Object> row : table) { System.out.prinln("Look ma, a row: " + row); }

So, what's in a row? Well, let's assume your "Test" table is defined in the following way in Access:

Field NameData Type
IDAutoNumber (Long Integer)
NameText
SalaryCurrency
StartDateDate/Time

Then, given a row of data, we could inspect the various Columns and their values like so:

Map<String,Object> row = ...; for(Column column : table.getColumns()) { String columnName = column.getName(); Object value = row.get(columnName); System.out.println("Column " + columnName + "(" + column.getType() + "): " + value + " (" + value.getClass() + ")"); } // Example Output: // // Column ID(LONG): 27 (java.lang.Integer) // Column Name(TEXT): Bob Smith (java.lang.String) // Column Salary(MONEY): 50000.00 (java.math.BigDecimal) // Column StartDate(SHORT_DATE_TIME): Mon Jan 05 09:00:00 EDT 2010 (java.util.Date)

As you can see in this example (and as previously mentioned), the row values are strongly typed Java objects. In Jackcess, the column types are represented by a Java enum named DataType. The DataType javadoc details the Java types used to return row values as well as the value types which are acceptable inputs for new rows (more on this later). One other thing to note in this example is that the column names in the row Map are case sensitive strings (although other parts of the API strive to mimic Access's love of case-insensitivity).

Awesome, so now we can read what's already there. Of course, lots of tools can do that. Now we want to write some data.

The main hurdle to writing data is figuring out how to get the data in the right columns. The primary method for adding a row to a Table is the addRow(Object...) method. This method should be called with the appropriate, strongly typed Java object values in the order of the Columns of the Table. The order of the Columns on the Table instance may not be the same as the display order of the columns in Access. (Re-read those last two sentences again, as it will save you a lot of grief moving forward).

Additionally, when adding rows, we never provide a value for any "auto" columns. You can provide a value (any value in fact), but it will be ignored (in the example below, we use a useful constant which makes the intent clear to any future developer).

So, assuming that the order of the Columns on the Table instance is "ID", "Name", "Salary", and "StartDate", this is how we would add a row to the "Test" table:

String name = "bob"; BigDecimal salary = new BigDecimal("1000.00"); Date startDate = new Date(); table.addRow(Column.AUTO_NUMBER, name, salary, startDate);

There you have it, a new row in your Access database.

While updating existing content is nice, and necessary, many times we want to create an entire new Database. While Jackcess doesn't support everything you may need when creating a new database, it does support a wide range of functionality, and adds more all the time. (If you started using Jackcess a while ago, you should definitely keep tabs on the release notes, as your knowledge of what is possible may be out of date).

As of version 1.2.10, Jackcess supports:

  • Creating databases for Access all versions 2000-2010
  • Creating columns for all simple data types
  • Creating tables with single-table Indexes

Some notable gaps:

  • Cannot currently create (index backed) foreign-key constraints
  • Cannot currently create "complex" columns (attachment, multi-value, versioned memo)

As long as your needs fall into the