In the Java Persistence API, the query would use an
explicit join clause to navigate the employee-project
relationship:
SELECT e FROM Employee e, JOIN e.projs as p
WHERE e.weeklySalary > :salary
AND e.dept.name = :dptname AND p.name = :prjname
PERFORMANCE ISSUES
The domain object model, the mapping, and the database
schema can affect the performance that an application
can obtain by using an ORM tool. Furthermore, the quality of the provider implementation is as important as the
quality of the application program.
One factor in performance is how the persistence provider performs change detection. When the application
uses the API to commit a transaction, the provider sends
an update request to the database for each instance that
was changed.
Some providers iterate the cache of instances and
compare the current value to the value as it was retrieved
from the database. Other providers dynamically track
changes as the application modifies the instances.
Applications that retrieve a large number of instances
and change only a few can see a significant performance
difference.
Another factor in performance is how to retrieve
exactly the data needed for an application, no more and
no less. A significant difference between a low-level API
such as JDBC and a high-level API used by ORM is the
control over the actual data that is retrieved from the
database when the application executes. When using a
domain model, the same classes can be reused in several
applications, and different use-cases might require different columns to be retrieved.
For example, if an application use-case examines all
Employees in a specific Department, a single query can
retrieve a subset of columns from both the EMPLOYEE and
DEPARTMENT tables. The challenge is for the application
to inform the persistence provider which columns to
retrieve and which part of the object model to instantiate
for this use-case.
One common technique is to statically declare certain
fields in the domain model as eager fetch, so that whenever an instance is retrieved, the related instances are
also fetched. A highly optimized persistence provider
can determine the exact SQL needed to accomplish the
retrieval with the best performance.
A somewhat more dynamic alternative approach has
the domain query itself specify the retrieval of a complete
collection of instances. In this case, the application would
write a separate query for each use-case, specifying the
navigational path to follow for the query.
A more general approach is to define access patterns
that specify a collection of fields and navigational paths,
and for the application to choose the access pattern
needed for a particular use-case. For example, the application can define fields in the Employee class and fields in
the Department class to be part of a fetch group named
empdept, and at runtime tell the persistence provider to
use fetch group empdept. Whenever a query is done for
either Department or Employee, the empdept fetch group
controls the exact columns and join conditions executed
by the provider.
MULTITHREADING ISSUES
Aside from roll-your-own frameworks, programmers are
likely to encounter multithreading in two areas: GUI
applications and Ajax (asynchronous JavaScript and XML)
applications.
To maintain liveliness, GUI applications handle trivial
requests in the main thread and delegate longer-running
requests to one or more background threads. If using an
MVC (model-view-controller) approach, then reading the
value of a model object field in order to interact with the
view object might appear to be a trivial request. If the
field is persistent and not currently loaded, however, it
becomes a database request. Other requests, such as querying the database by means of a dialog box, are clearly
longer running and should be executed by a background
thread. If a single Session is used for both tasks, then
threading becomes an issue.
Similarly, when running Ajax applications with most
Java Web frameworks, the same server session state is
used for all of the requests from the same Web page. If a
longer-running request is still executing when another
request from the same page arrives, multiple threads are
used to service the requests. If there is a single-persistence
Session instance for the Web session, multithreading
conflicts can occur.
Handling multithreading in an application is not
trivial. Some of the considerations include whether to
allow all threads to see the same view of the domain
model and whether to commit all changes immediately
or defer commit until some user action occurs (e.g., pushing a Save button). These decisions affect the application’s
transaction model.
To allow for the flexibility needed by applications,
some persistence providers permit the programmer
to specify the level of multithreading for the Session