Principles | Requirements | Architecture | Features | Rules | Storable objects | String x Text |
Principles
JSO works as a persitence layer, encapsulating O-R mapping and database access, so that you don't have to worry about it. You should only code your classes (according to some rules) and let JSO do the rest. Persistence code in your application should be limited to calls to JSO's API, requesting the storage or the retrieval of objects.
You don't need to specify how your object model will be mapped to the database. JSO will inspect your classes in runtime (through Java's reflection API) and store them transparently. You don't even have to know how the database is modeled. In fact, you should not access the database directly, only through JSO. This runtime mapping forbids JSO accessing legacy data.
Before running your application you should create an empty database and grant permissions to a specific user. This database and user will be passed to JSO, through configuration (properties) files, which will initialize the database upon startup. After that, persistence services become available to the application. As your application request those services, storable classes are inspected and their definitions are stored in the database. Also, new tables are created to house their instances.
Requirements
JSO's major goal is to provide persistence to Java objects in relational databases, acting as persistence layer and handling the problem known as "impedance mismatch". This layer should exempt application developers from implementing persistence code (like SQL statements) or specifying mapping metadata (like XML descriptors). Some requirements were defined for this layer:
To be used with JSO, relational databases must fulfill some requirements:
Architecture
The persistence layer implemented by JSO is divided in two main modules:
net.sf.jso.StorageController
) has a central role in the layer.
It coordinates concurrent persistence operations and provides some specific
services like: object identification, storable classes schema, concurrency
control, notification of persistence operations and garbage collections.
The controller must be the first module started.net.sf.jso.StorageManager
) is the interface between the
application and the layer. The application requests persistence services
directly to the manager, which in turn accesses the database and communicates
to the controller. The manager must always connect to a controller and
register itself.Many kinds of configurations may be obtained with this architecture. The simplest one consists of the application program, the controller, the manager ant the database running on the same computer, with the first three running on the same Java virtual machine. This configuration is considered to be a local one, because the communication between the manager and the controller is made through local calls.
Local configuration
A more complex configuration could be obtained running the database and the controller in one node of a network and programs and managers in other nodes. This configuration is considered to be distributed, because the managers communicate to the controller through remote calls (RMI).
Distributed configuration
The many possible configurations are defined through a "storage
environment" (net.sf.jso.StorageEnvironment
). This environment
has the ability to start and stop local and distributed application programs,
connecting the managers to the controller.
When a distributed configuration is used the environment creates a "home" to the controller and registers it in the RMI registry of the node. The remote reference to the home may be acquired by a name specified by the developer. The remote reference to the controller may be acquired through the home, after an authentication process. The authentication consists of the validation of a user name and a password, also specified by the developer.
Distributed applications obtaining remote references to storage controllers
Features
The fulfillment of the requirements and the use of the architecture discussed above allow JSO to offer the following features:
Rules
JSO offers a great level of freedom to developers for the implementation of storable classes. In spite of that, some rules apply:
net.sf.jso.Storable
or be one of the following:
net.sf.jso.text.Text
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short
java.lang.String
java.util.Date
java.util.Collection
java.util.List
java.util.Map
java.util.Set
java.sql.Time
java.sql.Timestamp
net.sf.jso.Storable
interface is merely a marker and has
no fields or methods, like the java.io.Serializable
interface.Storable
class must have a public void
constructor.Storable
class must not have its qualified name started
by jso
(case insensitive) and must not have the character
'_
'.Storable
class must not be final
Storable
classes may be any of the Java primitive
types or a reference to any of the classes listed in item 1.final
, static
,
transient
or volatile
will not be stored.Storable
class must not have any fields named
oid
(case insensitive).public
.Collection
, List
or
Set
).Map
).Storable objects
Basically, storable objects are all instances of Storable
classes and all classes listed in the first rule (as seen
in the previous topic. Storable
classes (and objects), writen by
the developer, may also use additional features: object metadata, class
metadata and callback methods.
Besides its own value (values of fields), a storable object also has
storage metadata. This metadata represents information about the storage
process of an object. This information may be used by the application for
some purpose. Storable
classes my declare a field called
jsoMetadata
, of type net.sf.jso.StorableMetadata
,
and that field will be updated every time the storable object suffer the
action of the storage manager. Through the StorableMetadata
interface the developer may get the manager which performed the last
persistence operation on the object, object's identification (OID) and
if the object is a summary object.
A summary object is an object that has been retrieved from the database with only part of its value, more specifically only with the value of its summary fields. These fields may be specified through class metadata (as we will see below) and can be considered as a "projection" of the object's field set. The definition of these fields is optional and the lack of it makes the summary of the object equal to the complete set of fields. Nevertheless, using this feature may be very usefull. For example, when displaying the result of a query usually a list containing only some of the classe's fields is shown to the user. The fields shown in the list may be defined as the summary fields. The queries may then use summary objects as results to save resources.
To specify the summary fields, and other "storable" characteristics, of a
class, the developer may use class metadata. The first time a
Storable
class is presented to JSO it is inspected and some
information is obtained and stored in the database, for later use. At this
point an opportunity is given to the developer to supply more information
about how the class should be stored or used. A Storable
class
may implement the static method jsoClassMetadata()
(no
parameters or throws clauses) that returns an object of the type
net.sf.jso.schema.StorableClassMetadata
. When a class is
inspected this method is called (if it exists) and its result is used to
inform JSO about more class' characteristcs.
The StorableClassMetadata
class allows the developer inform
JSO:
Storable
objects are not collected unless the
developer says so.net.sf.jso.schema.StorableIndex
) may be created to inform
JSO to create indices on class' fields. Otherwise no indices are
created.Finally, Storable
objects may be aware of persistence events
(operations). Three callback methods may be declared in the
Storable
class:
jsoPreStore()
is called by JSO before an object is
stored.jsoPostRetrieve()
is called after an object is
retrieved.jsoPreDelete()
is called before an object is deleted
from the database.String x Text
In Java the java.lang.String
class is commonly used to
store strings of many sizes, from simple words to long texts. Storing strings
in a database, nevertheless, requires some distinguishment. The storage cost
of arbitrarily long strings is inevitably higher than that of short
strings.
In order to provide means for the developer making such distinguishment
JSO offers the class net.sf.jso.text.Text
. Short strings
(containing up to 255 characters) should be represented by the
String
class while long strings should be represented by the
Text
class. String
s are stored in the database as
columns of the VARCHAR
JDBC type while Text
s are
stored as columns of the LONGVARCHAR
JDBC type.
The Text
class works in a similar way to the
String
class. It is also immutable and offers a subset of the
String
class interface. The use of the concatenation operator
(+) is not possible though.