Answer: DataStore is a high-performance, small-footprint, 100% Pure Java multifaceted
data storage solution.
It is:
A zero-administration embedded relational database, with both JDBC and DataExpress
interfaces, that supports non-blocking transactional multi-user access with
crash recovery.
An object store, for storing serialized objects, tables, and other file streams.
A JavaBean component that can be manipulated with visual bean builder tools
like JBuilder.
Answer: Yes, JDataStore is written totally in Java.
Answer: JDataStore is available for all platforms where a Java Virtual Machine implements correctly the Java Specification.
Answer: JDataStore supports JDBC, Object Serialization, RMI, JavaBeans, and related standards.
Answer: In JBuilder 3 Enterprise we have local and remoteType 4 JDBC drivers for JDataStore.
SQL support is a subset of entry level SQL92.
Answer: JDataStore is multi-user and multi-threaded when used in the same process.
To use it multi-user in separate processes, start the JDataStore server and
use the remote JDataStore JDBC driver to connect.
The store should be “served” by the DataStore Server (Tools | DataStore Server).
You can connect to it using the RemoteConnection driver. The server can also be
launched standalone.
Answer: Yes, Transactions are supported by JDataStore.
Robust applications require some level of transaction isolation. Not only do transactions
ensure that you are not reading dirty or phantom data, but you can also undo changes
made during a transaction. Transaction support also enables automatic crash recovery,
and is required for JDBC access.
A transaction’s lifecycle begins with any read or write operation through a connection.
The DataStore uses stream locks to control access to resources. To read a stream
or make a change to any part of a stream (a byte in a file, a row in a table),
you must be able to acquire a lock on that stream. Once a connection acquires
a lock, it will hold on to it until the transaction is committed or rolled back.
Answer: Yes. JDataStore has support for automatic recovery of the more common failures
like abnormal application
termination, operating system crash, and power failure.
Answer: JBuilder 3 Enterprise includes JDataStore.
Answer: Databases can be 8.7 terabytes per JDataStore file with default blocking factor.
Maximum number of rows per table is 2 billion.
Answer: JDataStore is included with the JBuilder 3 Enterprise edition.
When installing JBuilder 3, it will also install JDataStore to that system.
Answer: JDataStore makes use of several components, among them DataStore. The DataStore
component implements a database with support for storing Java objects as columns
in a table or as a separate file inside the DataStore (DataStore has a built-in
file system with a directory that can store tables or arbitrary application files
and Java objects). The database uses a single file storage. Separate files are
used for
transaction logging.
JDataStore can be accessed using JDBC drivers or by using Java Bean components.
The Java Bean access is surfaced using the DataExpress DataSet components.
The DataSet components have plugable storage. By default the use in memory storage
(MemoryStore).
With two simple property settings, a DataSet can be used to open, navigate, and
edit a JDataStore table directly.
Note that the DataSet and JDBC access methods are both transactional.
Answer: To use the DataStore:
1. Drop a DataStore component into your DataModule or Frame and set its FileName
property.
2. Set the Store property of your QueryDataSet or ProcedureDataset to the DataStore.
3. Set the StoreName property of your QueryDataSet or ProcedureDataset to some
meaningful name.
Answer: DataStore dataStore = new DataStore();
TxManager tx = new TxManager();
String dataStoreName = “myDataStore.jds”;
dataStore.setFileName(dataStoreName);
dataStore.setTxManager(tx);
dataStore.setUserName("userName");
dataStore.create();
Answer: Use the DataStoreConnection component. DataStore derives from it, so if you only
want one connection, you already have it.
Answer: Yes. But you should upgrade it using DataStore Explorer in order to make full
use of
its functionality, like transactional support and JDBC Drivers.
Answer: MFurther discussion on JDataStore, along with tutorials, can be found in the “JDataStore Programmers Guide.”
Answer: From JBuilder 3 select Tools | DataStore Explorer.
At DSX select Tools | Upgrade DataStore.
This will create a backup version of the JDataStore file.
Answer: The DataStore JDBC driver supports a subset of the ANSI/ISO SQL-92 standard.
Answer: Please refer to the section “SQL Reference” of the “JDataStore Programmer’s Guide”
for a complete answer to this.
The DataStore JDBC driver supports a subset of the ANSI/ISO SQL-92 standard. In
general, it provides:
Some Data Definition Language for managing tables and indexes, but no schema,
domain, views, or security elements.
Data manipulation and selection with INSERT, UPDATE, DELETE, and SELECT; but no
cursors.
No subqueries or JOINs (equi-joins are supported).
Answer: JDataStore offers partial support for JDBC 2.0
Answer: In JBuilder 3 Enterprise we have local and remote Type 4 JDBC drivers for JDataStore.
The driver class name is: com.borland.datastore.jdbc.DataStoreDriver
The URL will determine if you want to connect to a local or remote store.
Answer: Using the JDBC API:
String driverName = "com.borland.datastore.jdbc.DataStoreDriver";
String dataStoreName = "fileName.jds";
String url = "jdbc:borland:dslocal:" + dataStoreName;
Class.forName(driverName);
Connection con = DriverManager.getConnection(url, "userName", "");
DataExpress users will be familiar with the code snippet below.
Part of it can be generated automatically while setting up the Connection property
of a Database component:
ConnectionDescriptor con =
new ConnectionDescriptor("jdbc:borland:dslocal:storeName.jds",
"userName",
"pwd",
false,
"com.borland.datastore.jdbc.DataStoreDriver");
db.setConnection(con);
db.openConnection();
For Remote stores, the URL should be in the format below:
"jdbc:borland:dsremote://hostName/path/storeName.jds"
For example, on a Windows system you could use the following URL to access a store
in your own machine using the remote JDBC DataStore driver:
"jdbc:borland:dsremote://localhost/c:/stores/myStore.jds"
Answer: There are two JDBC Drivers for JDataStore: LocalConnection and RemoteConnection.
Both require a transactional store. If you want to connect to a non-transactional
store, set the "readonly" property to "true" on your JDBC connection.
Answer: DSX assumed an URL like "jdbc:borland:dslocal:c:\dir\storeName.jds" while creating
the store. The path was persisted for the Log files. That setting now conflicts
with
the UNC format that you are trying to use to connect to the same store.
To workaround this, set the LOGA property of the TxManager to \\machine\drive\dir
while creating the store. You can also reset its persisted properties by modifying
the TxManager settings and reopening the store.
Answer: Set the extended property of the JDBC Connection using JDBC Explorer.
You can also create a Property class and add value-pair elements like:
user=sysdba,password=masterkey,charset=SJIS
Answer: Some operations on a store are locked for a certain amount of time; you can increase
the DataStore.setLockWaitTime(n) value to try to avoid the error. You should also
commit
pending transactions.
Answer: In JBuilder 2.01 there was a known problem with setting an InputStream column
with a java.io.BufferedInputStream.
The BufferedInputStream did not always return the number of bytes requested even
when it was not at the end of the file. This behavior was unanticipated by the
InputStream handling logic in DataStore.
The work around was to avoid BufferedInputStream or any stream that behaves in
this fashion. The problem is fixed in JBuilder 2.0.
Answer: Transaction support is provided by the com.borland.datastore.TxManager class.
A DataStore may be transactional when it is first created; or you can add transaction
support later. In either case, you assign a TxManager object to the txManager
property of the DataStore object before calling the create or open method.
The properties of the TxManager object determine various aspects of the transaction
manager. When instantiated, the TxManager has usable default settings for these
properties. If you want to change any of these settings, it must done before creating
or opening the DataStore.
The first time the now-transactional DataStore opens, it stores its transactional
settings internally. The next time you open the DataStore, you do not have to
assign a TxManager; the DataStore will automatically instantiate a TxManager with
the settings it has stored.
To open (or create) a transactional DataStore, you must also set the DataStoreConnection.userName
property.
Answer: Instantiate a TxManager and set it to the datastore before or after its creation.
TxManager tx = new TxManager();
DataStore ds = new DataStore();
ds.setFileName("TxStore");
ds.setTxManager(tx);
ds.setUserName("user");
ds.create();
ds.close();
Answer: Yes, (assuming that you already upgraded to version 3.0)
you can set a new TxManager before opening the store.
TxManager tx = new TxManager();
DataStore ds = new DataStore();
ds.setFileName("TxStore");
ds.setTxManager(tx);
ds.setUserName("user");
ds.open();
ds.close();
Answer: Yes, set TxManager.Enabled property to false before opening the store.
If you plan to send the store file (.jds) to someone, a better option is
to disable the TxManager first. To re-enable, set the same property to
true.
TxManager tx = new TxManager();
DataStore ds = new DataStore();
tx.setEnabled(false);
ds.setFileName("TxStore");
ds.setTxManager(tx);
ds.setUserName("user");
ds.open();
ds.close();
Answer: If you are accessing table streams inside a DataStore, use a Java bean
that extends from StorageDataSet (such as Query/Procuedure/TableDataSet).
Make sure you set the StorageDataSet.StoreName property to the table
stream name and the StorageDataSet.Store property to a DataStore or
DataStoreConnection component first.
Transactions are automatically started the first time a read or write
operation is attempted against a JDataStore table or file. To commit the
transaction call DataStoreConnection.commit(). To rollback the
transaction, call DataStoreConnection.rollback.
Answer: The JDBC auto commit mode, java.sql.Connection.commit(), and
java.sql.Connection.rollback() work as defined by the JDBC standard.
Answer: The LogManager found a conflict between the original log files left in the previous
directory while trying to create new ones in its new location. It can’t assume
that
you don’t want those Log files so it is telling you to either rename/remove the
old
log files or to also move all of them to the new location.
Answer: No, each store should have its own TxManager instance associated with it.
Answer: When transaction support is enabled, I have found the JDBC driver and DataExpress
to
be of similar performance. DataExpress is slightly faster for simple insert/update/delete
operations
When transaction support is disabled (DataStore.TxManager property is null or
DataStore.TxManager.Enabled property is false), only DataExpress can be used (we
may support non- transactional JDBC in the future). This is usually at least twice
as fast as using a Transactional DataStore. Note that to disable a DataStore that
is already transactional, you must either:
For changes to be persistent there are two cases to consider:
Whether or not a DataStore is transactional, we always know if the DataStore was
shut down properly. There is a Response event that can be wired via the
DataStore.addResponseListener, that will tell you lots of interesting things,
including the fact that a DataStore was not shutdown properly (i.e., system or
application crash). With a transactional DataStore, crash recovery will proceed
to
repair the DataStore and rollback uncommitted transactions. With a non-transactional
DataStore, you can run StreamVerifier.verify() on the DataStore. If there are
errors, you could use DataStoreConnection.copyStreams() to repair the DataStore.
Use transactional DataStore for for JDBC SQL access, crash recovery, and
transactional semantics (commit/rollback).
Use non-transactional DataStore for higher performance with a small chance of
data
loss (no crash recovery). You may want to primarily run with transaction support
enabled, but disable transaction support to quickly perform a time-consuming batch
operation. The drawback to such an optimization is that a failure during the long-running
batch
operation could leave your DataStore file in a damaged state.
Answer: Crash recovery is automatic. The system should automatically recover (when it
is reopened) from all failures except media failures.
A media failure in the database file itself (*.jds) could be recovered if:
Since we are a low administration embeddable database, we mostly focus on
automatic recovery of the more common failures like abnormal application
termination, operating system crash, and power failure. Recovery from damaged
media can be accomplished, but requires more administration.
Answer: Crash recovery is automatic. The system should automatically recover (when it
is reopened) from all failures except media failures. You can prevent the
automatic recovery by wiring the DataStore.ResponsEvent.
A media failure in the database file itself (*.jds) could be recovered if:
Since the DataStore.ResponseEvent also sends out notifications when it is about
to drop logfiles that are not needed for active transactions or for system crash
recovery, you could wire this to archive off old log files. In this case, you
are implementing a log archive manager for a DataStore.
Since we are a low administration embeddable database, we mostly focus on
automatic recovery of the more common failures like abnormal application
termination, operating system crash, and power failure. Recovery from damaged
media can be accomplished, but requires more administration.
If a DataStore is not transactional or some log files are lost, you can:
You can dump the contents of a txlog by calling DataStoreConnection.dumpTxLog().
It’s mostly for auditing purposes. It was actually added to debug—it is the
whole history with user names and time stamps.
Answer: Yes, you can open the store as read-only by setting JDBC connection
properties.
java.util.Properties props = new java.util.Properties();
props.setProperty("readonly","true");
db.setConnection(new ConnectionDescriptor("jdbc:borland:dslocal:"+fileName
,"userName","pwd",false,"com.borland.datastore.jdbc.DataStoreDriver",props));
Answer: Yes, you can. But it will be ignored at this time.
Answer: A damaged JDataStore file can be diagnosed using the StreamVerifier. This can
be executed by opening the JDataStore database inside the DataStore explorer and
pressing the verify button. There is also a StreamVerifier class with several
options that can be called programatically.
The typical cause of a JDataStore file damage occurs when using a non-transactional
JDataStore. If a non-transactional JDataStore is not closed or its modified cache
blocks have not all been saved to disk when System.exit() is called or the computer
is shutdown, the database can be left in an inconsistent state.
Transactional JDataStores have built-in crash recovery. If there is a power failure
or System.exit() is called before the JDataStore has been shut down, then all
changes from uncommited transactions will be rolled back when the JDataStore is
opened again. This recovery will leave the JDataStore in a consistent state.
The following measures can prevent JDataStore file damage:
Make the JDataStore database transactional (supported since JBuilder 3.0). Transactional
Databases The DataStore Explorer can be used to make a JDataStore database transactional.
You can also set the DataStore.TxManager property to make a JDataStore transactional.
Update operations are slower with a transactional JDataStore, but you get the
safety and consistency guarantees of transactional operation with crash recovery
support.
If you use a non-transactional JDataStore, make sure you close (shutdown() since
JBuilder 3.0) the JDataStore before calling System.exit(1). Note that JDataStore
Daemon thread looks for modified cache blocks to save every 100 milliseconds.
So the only way to corrupt such a DataStore is for the System or Application to
abruptly terminate before modified cache blocks are saved.
You can also set the DataStore.SaveMode property to 2. This causes all modified
cache blocks to be saved after any edit (insert/update/deleted) operation. This
slows things down a bit, but increases the frequency of cache block saves. Note
that DataStore.SaveMode property is ignored for Transactional JDataStores because
they have crash recovery support.
A damaged JDataStore can be partially or completely repaired by using the JDataStore
copyStreams facility. Use the DataStoreExplorer Tools|Copy DataStore to copy a
damaged JDataStore to a new JDataStore. You can also call this method programatically
via the DataStoreConnection.copyStreams() method.
Answer: To create a table in a JDataStore you can use any component that extends from
StorageDataSet, including Table/Query/ProcedureDataSet. See the sample below.
Note that although this example creates columns for a TableDataSet,
StorageDataSets with providers like QueryDataSet and ProcedureDataSets will
create columns as needed to retrieve the results from a provide operation. So
DataStore is an embeddable database that goes a long way in seamlessly
supporting the full semantics of the DataExpress data access components.
// === Create a DataStore with a Person table
{
DataStore dataStore = new DataStore();
dataStore.setFileName("/app/mydatastore.jds");
dataStore.create(); // It is now created and open for business.
TableDataSet dataSet = new TableDataSet();
Column name = new Column();
name.setDataType(Variant.STRING);
name.setColumnName("Name");
Column address = new Column();
address.setDataType(Variant.STRING);
address.setColumnName("Address");
dataSet.setColumns(new Column[] {name, address});
dataSet.setStore(dataStore); // If not set, DataSet defaults
// to using MemoryStore
dataSet.setStoreName("/app/Person"); // specify the name of the
// DataSet table in the DataStore.
dataSet.open();
dataStore.close(); // Will automatically close any DataSet using this
// DataStore.
}
// ======================== Open an existing DataStore with a Person table
{
DataStore dataStore = new DataStore();
dataStore.setFileName("/app/mydatastore.jds");
dataStore.open(); // Only works if DataStore already exists.
TableDataSet dataSet = new TableDataSet();
dataSet.setStore(dataStore);
dataSet.setStoreName("/app/Person"); // specify the name of the
// DataSet table in the DataStore.
dataSet.open();
}
Answer: If the application that terminates does not close any DataStore that is open,
any other process must verify that the DataStore is not still open. This takes
about eight seconds.
To avoid this delay, close all DataStores before exiting your application. For
applications that use frames, you can trigger this from the windowClosing event.
To wire this event:
If you are using a JdbTable or any other dbSwing control, you can drop a dbDisposeMonitor
on the same frame and set its dataAwareControl property to this.The monitor will
close the store for you. The Designer will come up quickly and the data will show
up soon after that.
Answer: To create a table in a DataStore you can use any component that extends from StorageDataSet,
including
TableDataSet, QueryDataSet, and ProcedureDataSet. See the sample below.
Refer to DS500 for a code example.
Answer: At design time, the StorageDataSet.MaxDesignTimeRows is set to 50. So if the query
was initially run in the designer, you got 50 rows. If you restart your application,
the StorageDataSet using the DataStore knows it already has data (the 50 rows
from design time), so the provider query does not need to be executed. To force
the query to be re-executed at run time, call QueryDataSet.executeQuery(), or
QueryDataSet.refresh().
MemoryStore actually behaves much the same way if you open/close/open a QueryDataSet:
it does not execute the query on the second open. The difference is that DataStore
remembers its data, so that when you restart the application it does not think
it needs to execute the query again, because it already has data.
Answer: Yes, there is. Swing components can be accessed only by one thread at a time.
For example, the code snippet below calls a thread that updates a JdbTable.
This will most probably fail:
public void refreshQueries()
{
Thread t=new Thread(new TRefreshQuery1());
t.start();
}
To have your runnable object put on a queue and be correctly dispatched to the
Swing event thread, modify the code as follows:
public void refreshQueries()
{
try {
Thread t=new Thread(new TRefreshQuery1());
javax.swing.SwingUtilities.invokeLater(t);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
For more information about the use of Threads with Swing refer to
http://java.sun.com/products/jfc/tsc/archive/tech_topics_arch/threads/threads.html
Answer: JBuilder includes DataStore Explorer, which has specific utilities like
store creation, adding/modifying transactional support, copying streams,
importing files and tables (as text, based on a .schema file) browsing of
table and file streams, verifying a DataStore file, etc.
You can also rename and delete streams. You can also copy streams between
stores. And upgrade stores (from version 2.0 to 3.0).
Answer: You can [a] create a query using DataStore Explorer (Tools | New SQL Query),
[b] through the Designer or [c] write some code to do it:
[b] Drop a Database, a QueryDataSet, a DataStore and a GridControl/JdbTable
component on a frame.
Set the Database connection to your ODBC source;
Set the FileName property of the DataStore;
Set The StoreName property in the QDS. This will be the streamName inside the
store.
Set the Store property of the QDS to the DataStore component.
Set the Query property of the QDS.
By the time you test your query, the store will be created.
Or if you didn't test it, it will be created by the time you
set the DataSet property of the visual control and the data
is displayed.
Don't forget that for an ODBC connection, you need first to create an Alias using
the ODBC Administrator and have the correct ODBC driver installed.
Answer: Yes, you will find a DataStore version of the Employee database at
\samples\com\borland\samples\dx\employee.jds.
There is also a DataStore version of the Intlemp, which uses a non-US character
set.
Answer: Perform commits only when needed. This operation forces the logfile entries up
to the commit point to disk. Use the saveMode property of the DataStore component
to control how often cache blocks are written to disk. This property applies only
to non-transactional DataStores;
Setting the DataStore.tempDirName property, used by the query engine, to a directory
on another (fast) disk drive may help;
Try setting the TxManager.checkFrequency higher. Higher values will result in
slower recovery;
Set the autoCommit property to true;
For transactions that are reading but not writing, significant performance improvements
can be realized by using a read-only transaction. The DataStoreConnection’s readOnlyTx
property controls whether a transaction is read-only. This property must be set
to true before the connection is open;
Make use of setSaveInterval(long interval) to control the checkpoint frequency.
Answer: If the DataStore is transactional, then the DataStoreConnection.commit() method or the java.sql.Connection.commit() method must be called before deleted streams from a transaction can have their space reclaimed.
Answer: Since JBuilder 2.0, JDataStore provides high-performance data caching and compact
persistence for DataExpress DataSets, files and Java Objects. The data store has
a hierarchical directory structure that allows a single DataStore to persist multiple
DataSets, files and objects.
The DataStore component can be used with any DataSet that extends from StorageDataSet
(TableDataSet, QueryDataSet, ProcedureDataSet). In addition, you can use Java
serialization support since JBuilder 2.0. The new DataSetData class can extract
edited or unedited rows from a DataSet. DataSetData implements java.io.Serialization
so it can be used as a parameter to an RMI method or manually streamed between
a client and server as a stream of bytes. DataSetData also has methods for loading
its contents back into a StorageDataSet.
Answer: Use the Deployment Wizard from the Wizards menu.
It will help you build a .jar or .zip file with all classes (and .gif images)
created by and/or included in your project.
You can also add classes manually, like dynamically loaded ones (see DS920 for
Deployment of JDBC Drivers).
Answer: The Deployment Wizard has no way to detect when classes are being loaded dynamically
in an application. That’s the case for the JDBC Drivers. An easy solution is to
create
an instance of the Driver class that you are using in your application and let
the
Wizard add it to the .jar/.zip file.
You can also add classes by hand while deploying the application/applet.
import com.borland.datastore.*;
LocalConnection lc = new LocalConnection();
RemoteConnection rc = new RemoteConnection();
DataStoreDriver dsd = new DataStoreDriver();
Çà äîïîëíèòåëüíîé èíôîðìàöèåé îáðàùàéòåñü â êîìïàíèþ Interface Ltd.
INTERFACE Ltd. |
|