The DataSet API
In the last section, you learned how to perform data binding. In many cases, you will need to pull data out from a database before doing data binding. In this section, you will learn how to use the JDNC DataSet API to simplify data encapsulation -- loading data from a database, record caching, and so on.
In JDNC, a DataSet is the top-level container for data. It may contain DataTables, DataRelations, and DataRelationTables. A DataTable contains a homogeneous set of data records -- you can treat it as representing a table in the database. A DataRelation represents the relationship between two DataTables. A DataRelationTable is a table view. You use a DataProvider to retrieve and send data from and to the database. The DataRow and DataColumn are at the bottom of the JDNC DataSet "food chain." A DataRow represents a record in a table and a DataColumn represents a field in a record.
Figure 22 illustrates the main participating classes in the JDNC DataSet API.
Figure 22. The JDNC DataSet API
In the following panels, I will show you how to use the JDNC DataSet API with examples. But if you're going to follow along at home, you need to set up a database first.
Because JDBC abstracts underlying database implementations, you can use any database as long as it has a proper JDBC driver. Here, we will use Apache Derby as the database engine for our sample applications. Derby is a fully functional relational database engine licensed under the Apache open source license. If you want to know more about Derby, you can visit the links provided in Resources.
The code in Listing 31 creates two tables in the database.
Listing 31. Creating our database tables
CREATE TABLE category ( CATEGORY_ID VARCHAR(40),
PRIMARY KEY (CATEGORY_ID) );
CREATE TABLE book ( BOOK_ID INT NOT NULL GENERATED
ALWAYS AS IDENTITY (START WITH 1),
CATEGORY_ID VARCHAR(40),
TITLE VARCHAR(100),
AUTHOR VARCHAR(40),
ISBN VARCHAR(20),
COVERIMAGEURL VARCHAR(100),
PRIMARY KEY (BOOK_ID) );
|
Figure 23 illustrates the entity relationship.
Figure 23. Entity relationship in our database
For this sample database, the driver class name and the connection string are org.apache.derby.jdbc.EmbeddedDriver and jdbc:derby:books;create=true, respectively.
In the next few panels, you'll see how to use the JDNC DataSet API to access this sample database.
In the last panel, we prepared the database. Now, we want to load the data from the database into a DataSet. First, we need to create an instance of DataSet:
DataSet dataSet = new DataSet(); |
Before we create a data provider to load data, we need an SQL database connection. We establish one in Listing 32.
Listing 32. Creating a database connection
JDBCDataConnection dataConnection =
new JDBCDataConnection("org.apache.derby.jdbc.EmbeddedDriver",
"jdbc:derby:books;create=true", (Properties)null);
dataConnection.setConnected(true);
|
In the code in Listing 32, we use dataConnection.setConnected(true) to open the database connection. In Listing 33, we create a data provider for our first table: category.
Listing 33. Creating a data provider
SQLDataProvider dataProvider = new SQLDataProvider("category");
dataProvider.setDataConnection(dataConnection);
|
Then, in Listing 34, we can create a data table for the category table and add its column.
Listing 34. Creating a data table and adding its column
DataTable tableCategory = dataSet.createTable();
tableCategory.setDataProvider(dataProvider);
tableCategory.setName("category");
tableCategory.createColumn("CATEGORY_ID");
|
Similarly, we can create a data table for the book table, as shown in Listing 35.
Listing 35. Creating a data table
final DataTable tableBook = dataSet.createTable();
tableBook.setDataProvider(dataProvider);
tableBook.setName("book");
tableBook.createColumn("BOOK_ID");
tableBook.createColumn("CATEGORY_ID");
tableBook.createColumn("TITLE");
tableBook.createColumn("AUTHOR");
|
Now, we start to load the data:
tableCategory.load(); tableBook.load(); |
Alternatively, you can use the dataSet.load() method, which will start loading data for every data table it contains.
In the next panel, you will see how to create a data model from a data set.
Creating data models from a data set
In the last panel, we created a data set containing two tables. Now we want to display the book information to the user, as illustrated in Figure 24.
Figure 24. Displaying book information to the user
The code in Listing 36 creates a data model from the book table model.
Listing 36. Creating a data model for the table model
final DataSelector selector =
dataSet.getTable("book").createSelector("current");
DataModelAdapter dataModelAdapter =
new DataModelAdapter(selector);
|
A DataSelector acts as a cursor pointing to a record in the table. Then we can use a JForm to bind the data model, as in Listing 37.
Listing 37. Binding the data model
JForm form = new JForm(dataModelAdapter);
JButton button = new JButton("Next >");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
// navigate to next.
int index = -1;
if(selector.getRowIndices() !=
null && selector.getRowIndices().size() != 0) {
index =
((Integer) selector.getRowIndices().get(0) ).intValue();
}
index += 1;
if(index == tableBook.getRows().size())
index = 0;
selector.setRowIndices(new int[] {index});
}
});
|
Note that we add a button for the user to navigate between records. The setRowIndices() method is used to set the index of the record that the data selector points to.
In the last panel, we created a data model for a data selector and displayed one record on the screen at a time. Now, we want to display all the records in a table, as shown in Figure 25.
Figure 25. Displaying all records in a table
Thanks to the JDNC DataSet API, you do not need to write a lot of code to implement this functionality. Listing 38 contains the lines to display a data table in a JNTable.
Listing 38. Displaying a data table in a JNTable
TabularDataModelAdapter dataModelAdapter =
new TabularDataModelAdapter(dataSet.getTable("book"));
JNTable table = new JNTable();
new DirectTableBinding(table.getTable(), dataModelAdapter);
|
First, we create a tabular data model from the book table. Then we create a JNTable. The DirectTableBinding is used to bind the table control with the tabular data model we created.
DataRelation and DataRelationTable
In previous panels, we created a dataset with two tables. Now we want to set up the relationship between the category table and the book table. In JDNC, a relationship is represented by a DataRelation. A DataRelation maps a data row in the parent table to a list of data rows in the child table. Listing 39 sets up the relationship between the two data tables we have created.
Listing 39. Creating a relationship between two tables
DataRelation categoryBookRelation = dataSet.createRelation();
categoryBookRelation.setName("categoryBookRelation");
categoryBookRelation.setParentColumn(dataSet.getTable
("category").getColumn("CATEGORY_ID"));
categoryBookRelation.setChildColumn(dataSet.getTable
("book").getColumn("CATEGORY_ID"));
|
As in SQL, we set up the relationship in terms of the data columns in the tables. A DataRelationTable is essentially a data table filtering its content based on the data relation and a data selector of the parent table. Listing 40 creates a data relation table.
Listing 40. Creating a data relation table
DataRelationTable relationTable = dataSet.createRelationTable();
relationTable.setName("booksUnderCategory");
relationTable.setRelation(categoryBookRelation);
DataSelector selectorCurrentCategory =
dataSet.getTable("category").createSelector("currentCategory");
relationTable.setParentSelector(selectorCurrentCategory);
|
In the next panel, you will see how to use this data relation table.
Master/Detail information display with DataRelationTable
The Master/Detail design pattern (see Resources) provides an accessible UI navigation model. The master view summarizes the data in list form, while the detail view presents the data items in the master view in more depth. In this panel, we'll create the Master/Detail display shown in Figure 26.
Figure 26. Master/Detail display
The user can select a category in the list located at the right the panel. The books under the selected category will be shown in the table.
First, we create the UI components with the code in Listing 41.
Listing 41. Creating the UI components
JList list = new JList();
JNTable table = new JNTable();
|
Then we create a tabular data model based on the category data table. A SelectionModelAdapter is created for the selector. Next, we bind both the TabularDataModelAdapter and SelectionModelAdatper to a list control. We do all this in Listing 42.
Listing 42. Creating a table model and binding its adapters to a list control
TabularDataModelAdapter dataModelAdapter = new
TabularDataModelAdapter(dataSet.getTable("category"));
SelectionModelAdapter sm = new
SelectionModelAdapter(dataSet.getTable
("category").getSelector("currentCategory"));
new DirectListBinding(list, dataModelAdapter, "CATEGORY_ID", sm);
|
Now, in Listing 43, we create a tabular model from the data relation table and bind it to a table control.
Listing 43. Binding our tabular model to a table control
TabularDataModelAdapter booksModel = new
TabularDataModelAdapter(dataSet.getTable("booksUnderCategory"));
new DirectTableBinding(table.getTable(), booksModel);
|
The SelectionModelAdapter triggers an update on the selector when the user changes selection on the list. Updating on the selector results in an update of the data relation table.


