Database application development is a feature of JBuilder Professional and Enterprise. Distributed application development is a feature of JBuilder Enterprise.
JBuilder makes it easy to write a custom provider for your data when you are accessing data from a custom data source, such as SAP, BAAN, IMS, OS/390, CICS, VSAM, DB2, etc.
The retrieval and update of data from a data source, such as an Oracle or Sybase server, is isolated to two key interfaces: providers and resolvers. Providers populate a data set from a data source. Resolvers save changes back to a data source. By cleanly isolating the retrieval and updating of data to two interfaces, it is easy to create new provider/resolver components for new data sources. JBuilder currently provides implementations for standard JDBC drivers that provide access to popular databases such as support for Oracle, Sybase, Informix, InterBase, DB2, MS SQL Server, Paradox, dBASE, FoxPro, Access, and other popular databases. These include:
You can create custom provider/resolver component implementations for EJB, application servers, SAP, BAAN, IMS, CICS, etc.
An example project with a custom provider and resolver is located in the /samples/DataExpress/CustomProviderResolver directory of your JBuilder installation. The sample file TestFrame.java is an application with a frame
that contains a JdbTable
and a JdbNavToolBar
. Both visual components are connected to a TableDataSet
component where data is provided from a custom Provider
(defined in the file ProviderBean.java), and data is saved with a custom Resolver
(defined in the file ResolverBean.java).
This sample application reads from and saves changes to the text file
data.txt, a simple non-delimited text file. The structure of data.txt is
described in the interface file DataLayout.java.
This topic discusses custom data providers, and how they can be used as providers
for a TableDataSet
and any DataSet
derived from TableDataSet
.
The main method to implement is provideData(com.borland.dx.dataset.StorageDataSet dataSet, boolean toOpen)
. This method accesses relevant metadata and loads the actual data into the data set.
Column
components for each column in the StorageDataSet
, and in the StorageDataSet
itself.
When you obtain data from a data source, and store
it in one of the subclasses of StorageDataSet
, you typically obtain not only rows of data
from the data source, but also metadata. For example, the first time that you ask a QueryDataSet
to
perform a query, by default it runs two queries: one for metadata discovery and the second for fetching rows of data that your application displays and manipulates.
Subsequent queries performed by that instance of QueryDataSet
only do row data fetching. After discovering the metadata, the QueryDataSet
component then creates Column
objects
automatically as needed at run time. One Column
is created for every query result column that is not already in the QueryDataSet
. Each Column
then gets some
of its properties from the metadata, such as columnName
,
tableName
, rowId
, searchable
,
precision
, scale
, and so on.
When you are implementing the abstract provideData()
method from the Provider
class, the columns from the data provided may need to be added to your DataSet
. This can be done by calling the ProviderHelp.initData()
method from inside your provideData()
implementation. Your provider should build an array of Columns
to pass to the ProviderHelp.initData()
method. The following is a list of Column
properties that a Provider
should consider initializing:
columnName
dataType
and optionally:
sqlType
precision
(used by DataSet)
scale
(used by DataSet)
rowId
searchable
tableName
schemaName
serverColumnName
The optional properties are useful when saving changes back to a data source. The precision
and scale
properties are also used by DataSet
components for constraint and display purposes.
The arguments to the ProviderHelp.initData(com.borland.dx.dataset.StorageDataSet dataSet, com.borland.dx.dataset.Column[] columns, boolean updateColumns, boolean keepExistingColumns, boolean emptyRows) method are explained below.
dataSet
is the StorageDataSet
we are providing to
metaDataColumns
is the Column
array created with the proper properties that do not need to be added/merged into the Columns
that already exist in DataSet
updateColumns
specifies whether to merge columns into existing persistent columns that have the same columnName
property setting
keepExistingColumns
specifies whether to keep any non-persistent columns
If keepExistingColumns
is true
, non-persistent columns are also retained. Several column properties in the columns array are merged with existing columns in the StorageDataSet
that have the same name
property setting. If the number, type, and position of columns is different, this method may close the associated StorageDataSet
.
The metaDataUpdate
property on StorageDataSet
is investigated when ProviderHelp.initData
is called. This property controls which Column
properties override properties in any persistent columns that are present in the TableDataSet
before ProviderHelp.initData
is called. Valid values for this property are defined in the MetaDataUpdate
interface.
Certain key DataSet
methods cannot be used when the Provider.provideData
method is called to open a DataSet
, while the DataSet
is in the process of being
opened, including the StorageDataSet.insertRow()
method.
In order to load the data, use the StorageDataSet.startLoading
method. This method returns an array of Variant
objects for all columns in a DataSet
. You set the value in the array (the ordinal values of the columns are returned by the ProviderHelp.initData
method), then load each row by calling the StorageDataSet.loadRow()
method, and finish by calling the StorageDataSet.endLoading()
method.
maxRows
and maxDesignRows
properties on StorageDataSet
. The values for these properties are:
Value | Description |
---|---|
0 | provide metadata information only |
-1 | provide all data |
n |
provide maximum of n rows |
To determine if the provideData()
method was called while
in design mode, call
java.beans.Beans.isDesignTime()
.
The Provider.provideData
method is called
StorageDataSet
is initially opened (toOpen
is true)
StorageDataSet.refresh()
is called
fetchAsNeeded
property set to true
needs to be loaded
When a detail data set with the fetchAsNeeded
property set to true
needs to be loaded, the
provider ignores provideData
during the opening of the data, or just
provides the metadata. The provider also uses the values
of the masterLink
fields to provide the rows for a specific detail data set.