|
Side of Software Persistence Library 2.0 |
||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
public interface Database
A database of objects. This interface provides a way to add objects to a named database. When the client modifies these objects, the database is automatically updated. When the client no longer references these objects, they are automatically removed from the database.
This interface provides sophisticated database functionality through a simple, unobtrusive interface. It hides all of the details of a complex database management system. From a client's perspective, the database--or persistence layer--can be nearly transparent. Clients need not worry about database IDs or keys. There is no concept of a table or query, and there is no need for a mapping from an application class to a schema.
IllegalStateException.

create, open,
close, and delete apply to
the client side.
Object addObject( Object object ) throws TransactionAbortedException boolean containsObject( Object object )The method
addObject returns a proxy object.
The proxy object implements the same interfaces as the original object.
After calling addObject, the client should
not retain any references to the original
object; it should reference the original object only through the returned proxy object.
Passing the proxy object to containsObject returns true.
Note: Clients do not need to invoke addObject on
immutable database objects.
A consequence of using proxies is that
ordinary methods may throw TransactionAbortedException as a result of
a database error or conflict. Even though this exception is a run-time exception,
it is intended to be caught.
create.
Like all other database objects, it should be referenced only through its
proxy object. The root's proxy object is returned in getRoot.The root object is typically a data structure, such as a map or index, and all database objects must be reachable (recursively) from this root.
Database interface supports nested
transactions that satisfy the ACID requirements.
In other words, they exhibit:
When the client wishes to treat a group of operations as atomic,
it should invoke startTransaction,
execute the operations, and then invoke commitTransaction.
This chunk of code must be executed by the same application thread,
and it should catch and handle a TransactionAbortedException. If
the client wishes to cancel a transaction programmatically, it should call
abortTransaction.
Oftentimes, this transaction block of code would correspond to a synchronization
block if the client weren't using this library. The startTransaction
corresponds to monitor acquisition and the commitTransaction
corresponds to the monitor release. With transactions, however, there
is no need to lock database objects in the application code. The
database handles the concurrency (and deadlock avoidance)
automatically.
InMemoryDatabase - Objects reside in main memory and do not persist across application runsFileDatabase - Objects reside in a file and persist across application runsInMemoryDatabase
for FileDatabase.
public class Application {
private Database db;
public Application() throws IOException {
db = new ...; // some Database implementation like FileDatabase
if( !db.exists() )
db.create( new HashMap() );
db.open( false );
}
private Person createPerson() {
Person person = new PersonImpl(); // some implementation of interface Person
person = (Person)db.addObject( person ); // immediately add object to database
return person; // return the proxy object
}
private void onCreatePerson() {
try {
db.startTransaction();
Person person = createPerson();
person.setFirstName( firstName );
person.setLastName( lastName );
db.commitTransaction();
}
catch( TransactionAbortedException tae ) {
Throwable cause = tae.getCause();
// inform the user that the operation failed
// The state of the database is the same as before
// the call to startTransaction. Specifically,
// no new Person has been added.
}
}
}
Thread-safety. The methods startTransaction,
commitTransaction, abortTransaction,
addObject, containsObject,
and getRoot are expected to be invoked by different threads.
No explicit synchronization is needed. The other methods, however, are not expected
to be executed by multiple threads; explicit synchronization is needed.
Transaction Policy. If possible, implementations
of this interface should delegate transactional
behavior, such as locking and deadlock avoidance, to an instance of
TransactionPolicy.
When a top-level transaction is started, the database should
invoke startTransaction on the underlying transaction policy.
Before a database accepts a new object (via addObject), it should invoke
registerObject on the transaction policy.
The database should let the transaction policy
carry out all method invocations on the actual object by invoking invoke.
Last, before a database automatically deletes an object, it should
invoke unregisterObject on the transaction policy.
Logging. Although it is not required, implementations of Database
should use Java's logging API to log database activity. It should log
activities in the "sos.db" logger, which, for convenience, is available as
the public static field logger.
FileDatabase,
InMemoryDatabase| Field Summary | |
|---|---|
static java.util.logging.Logger |
logger
The object that should be used to log database activity. |
| Method Summary | |
|---|---|
void |
abortTransaction()
Aborts all changes under the calling thread's current transaction. |
java.lang.Object |
addObject(java.lang.Object object)
Adds the specified object to this database and returns a proxy object that the client should use instead. |
void |
close()
Closes this database. |
void |
commitTransaction(Progress progress)
Commits all changes under the calling thread's current transaction. |
boolean |
containsObject(java.lang.Object object)
Returns true if this database contains the specified object. |
boolean |
create(java.lang.Object root)
Creates a new database if and only if it does not exist. |
boolean |
delete()
Deletes this database. |
boolean |
exists()
Returns true if this database exists. |
java.lang.String |
getName()
Returns the name of this database. |
java.lang.Object |
getRoot()
Returns the root object of this database. |
TransactionPolicy |
getTransactionPolicy()
Returns the transaction policy governing the transactions. |
boolean |
isOpen()
Returns true if this database is open and ready to accept
requests. |
void |
open(boolean readOnly)
Opens this database. |
void |
startTransaction()
Starts a new (potentially nested) transaction for the calling thread. |
int |
transactionDepth()
Returns the nesting depth of the transaction associated with the current thread. |
| Field Detail |
|---|
static final java.util.logging.Logger logger
| Method Detail |
|---|
void abortTransaction()
java.lang.IllegalStateException - if this database is not open
NoTransactionException - if the calling thread does not have an
active transactioncommitTransaction(sos.db.Progress),
startTransaction(),
isOpen()
java.lang.Object addObject(java.lang.Object object)
throws TransactionAbortedException
The proxy object will implement
the same interfaces as object. Specifically, the interfaces
returned by invoking getClass().getInterfaces()
on the proxy object will be (in order) the interfaces implemented
by the top-most superclass, the interfaces of the next lower superclass,
etc. down to the interfaces of the object's class. Also, an interface
will not be listed again if a superclass implements the same interface.
Any updates made to the proxy object will get propagated to the original object and the changes will automatically get saved in the database when the top-most transaction enclosing the updates commits.
The object will be automatically removed from this database after it becomes unreachable.
If there is no active transaction for the calling
thread, addObject is atomic only with itself. That is, it is
as if startTransaction is invoked immediately before the call to
addObject and commitTransaction immediately after.
object - object to add to the database
object
java.lang.IllegalStateException - if this database is not open or if this
database is open in read-only mode
java.lang.NullPointerException - if object is null
TransactionAbortedException - if this database cannot add object
and the transaction has been aborted as a result. The cause of the abort
can be obtained with getCause.
This exception is intended to be caught.containsObject(java.lang.Object),
isOpen(),
startTransaction(),
commitTransaction(sos.db.Progress)
void close()
throws java.io.IOException
java.io.IOException - if an I/O error occurs
void commitTransaction(Progress progress)
throws TransactionAbortedException
Callers of this method have a chance to follow the method's progress
and to suggest an abort in the middle of committing. A custom
Progress parameter can be passed in to update
a progress bar in the user interface or to respond to a cancel
button, for example. If the progress is canceled, this method
aborts with a TransactionAbortenulldException.
progress - an object to be updated and checked while the
commit is in progress (may be null to indicate that no updating/checking
is necessary)
java.lang.IllegalStateException - if this database is not open
NoTransactionException - if the calling thread does not have an
active transaction
TransactionAbortedException - if this database cannot commit
the transaction or if the progress is canceled. The cause of the abort
can be obtained with getCause.
This exception is intended to be caught.startTransaction(),
abortTransaction(),
isOpen()boolean containsObject(java.lang.Object object)
true if this database contains the specified object.
object must be a proxy object returned by
addObject in order for the method to return true.
If object is null, the method returns false.
If this database is closed, then the method throws
an IllegalStateException.
No transactions are used or created when checking for containment,
so TransactionAbortedException is never thrown.
object - the object to check for containment
true if this database contains object
java.lang.IllegalStateException - if this database is not openaddObject(java.lang.Object),
isOpen()
boolean create(java.lang.Object root)
throws java.io.IOException
The root object should be an index-type object (like a map) that will hold references to objects added to this database. The primary way to retrieve database objects is through this root object.
After the invocation of this method, clients should no longer
reference root. They should instead invoke getRoot
and reference the returned object.
root - the root of this database
true if this database does not exist and is successfully created;
false if this database already exists
java.io.IOException - if an I/O error occurs
java.lang.NullPointerException - if root is null and this
database does not allow a null rootgetRoot()
boolean delete()
throws java.io.IOException
true if this database is successfully deleted
java.lang.IllegalStateException - if this database is open
java.io.IOException - if an I/O error occursclose(),
isOpen()boolean exists()
true if this database exists. To exist, a database normally
has to have been initialized with create. Normally,
when a database exists, a call to open will put it
in a state where it is ready to accept database operations
such as addObject and getRoot.
true if this database existsopen(boolean)java.lang.String getName()
java.lang.Object getRoot()
throws TransactionAbortedException
This object may not be the same object provided in the original
invocation of create; however, it will implement
the same interfaces and forward any requests to the original object.
null)
java.lang.IllegalStateException - if this database is not open
TransactionAbortedException - if the root object cannot
be retrieved and the transaction has been aborted as a result.
The cause of the abort
can be obtained with getCause.
This exception is intended to be caught.create(java.lang.Object),
isOpen()TransactionPolicy getTransactionPolicy()
boolean isOpen()
true if this database is open and ready to accept
requests.
true if this database is openopen(boolean),
close()
void open(boolean readOnly)
throws java.io.IOException
open puts it into a state where it can accept database operations
such as addObject and getRoot.
If this database does not exists, this method throws
an IllegalStateException.
If this database is already open, no change to the database occurs.
readOnly - true if database updates are not allowed
java.io.IOException - if an I/O error occursexists()
void startTransaction()
throws TransactionAbortedException
commitTransaction or abortTransaction
by the same thread.
A call to startTransaction by the same thread before the
transaction finishes starts a nested transaction with the original
transaction as its parent. Nested transactions are started
and stopped in a stack-like fashion.
All operations on database objects during a transaction are treated
as a single atomic operation with respect to this database. An
application should use transactions like it would the
synchronized statement.
java.lang.IllegalStateException - if this database is not open
TransactionAbortedException - if the transaction cannot
be started. The cause of the exception
can be obtained with getCause.
This exception is intended to be caught.abortTransaction(),
commitTransaction(sos.db.Progress),
isOpen()int transactionDepth()
java.lang.IllegalStateException - if this database is not open
|
Side of Software Persistence Library 2.0 |
||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||