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
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.
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
References:
Archives