Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2) Part No. B15901-01 |
|
Previous |
Next |
Java Data Objects (JDO) is an API for transparent database access. The JDO architecture is a standard API for data, both in local storage systems and enterprise information systems. It unifies access to heterogeneous systems, such as mainframe transaction processing and database systems. JDO enables programmers to create Java code that accesses the underlying data store transparently and does not require database-specific code.
OracleAS TopLink provides basic JDO support based on the JDO specification. OracleAS TopLink support includes much of the JDO API, but does not require you to enhance or modify the class to leverage JDO.
This section includes information on:
The JDO API includes four main interfaces:
The PersistenceManagerFactory is a factory that generates PersistenceManagers
. It has a configuration and login API.
The PersistenceManager is the main point of contact from the application. It provides an API for accessing the transaction, queries, and object life cycle API (makePersistent
, makeTransactional
, deletePersistent
).
The Transaction defines a basic begin, commit, roll back API.
The Query defines the API to configure the query (filter, ordering, parameters, and variables) and to execute the query.
OracleAS TopLink implements the PersistenceManagerFactory
, PersistenceManager
, and Transaction
interfaces, and extends the query functionality to include the complete OracleAS TopLink query framework.
To create a JDOPersistenceManagerFactory
, call the constructor and include a session name string, or an OracleAS TopLink session or project. If you construct the factory from a project, then OracleAS TopLink creates a new database session and attaches it to the PersistenceManager
every time you obtain the PersistenceManager
with the getPersistenceManager
method.
The PersistenceManager
is not multi-threaded. In a multi-threaded application, assign each thread its own PersistenceManager
. In addition, construct the JDOPersistenceManagerFactory
from a server session, rather than a database session or project. Doing this enables you to use the lightweight client session and more scalable connection pooling.
Example 4-50 illustrates how to create a factory from an OracleAS TopLink session named jdoSession
. A session manager manages a singleton instance of the OracleAS TopLink server session or database session.
For more information, see "Session Manager".
Example 4-50 Creating a JDOPersistenceManagerFactory
JDOPersistenceManagerFactory factory= new JDOPersistenceManagerFactory("jdoSession"); /*Create a persistence manager factory from an instance of OracleAS TopLink ServerSession or DatabaseSession that is managed by the user */ ServerSession session = (ServerSession) project.createServerSession(); JDOPersistenceManagerFactory factory= new JDOPersistenceManagerFactory(session); /* Create a persistence manager factory with ties to a DatabaseSession that is created from OracleAS TopLink project */ JDOPersistenceManagerFactory factory= new JDOPersistenceManagerFactory(new EmployeeProject());
To create new PersistenceManagers, call the getPersistentManager
method. If you construct the factory from a Project instance, use the getPersistentManager(String userid, String password)
method to configure the userid
and password
.
Table 4-18 summarizes the most common public methods for PersistenceManagerFactory
. For more information about the available methods for PersistenceManagerFactory
, see the Oracle Application Server TopLink API Reference.
Table 4-18 Elements for Persistence Manager Factory
Method Name | Description |
---|---|
JDOPersistenceManagerFactory()
|
Constructs a factory from a session manager session |
JDOPersistenceManagerFactory(String sessionName)
|
Constructs a factory from the named session |
JDOPersistenceManagerFactory(Session session)
|
Constructs a factory from a user session |
JDOPersistenceManagerFactory(Project project)
|
Constructs a factory from a project |
getIgnoreCache()
|
Query mode that specifies whether cached instances are considered when evaluating the filter expression.
The default is set to FALSE. |
getNontransactionalRead()
|
Transaction mode that allows you to read instances outside a transaction.
The default is set to FALSE. |
getConnectionUserName()
|
Available settings if the factory is constructed from an OracleAS TopLink project.
Derives the default user name, password, URL, driver from project login. |
getPersistenceManager()
|
Accesses PersistenceManager , and sets the user ID and password if the factory is constructed from an OracleAS TopLink project (uses default values in the absence of a project).
Derives the default user ID, password from session login, or project login. |
getProperties()
|
Nonconfigurable properties |
supportedOptions()
|
Collection of supported option String |
The JDOPersistenceManager
class is the factory for the Query
interface and contains methods to access transactions, and manage the persistent life cycle instances.
To make new JDO objects persistent, use the makePersistent()
or makePersistentAll()
method. If you do not manually begin the transaction, then OracleAS TopLink begins and commits the transaction when you invoke either makePersistent()
or makePersistentAll()
. If the object is already persisted, then calling these methods has no effect.
Example 4-51 Persist a New Employee Named Bob Smith
Server serverSession = new EmployeeProject().createServerSession(); PersistenceManagerFactory factory = new JDOPersistenceManagerFactory(serverSession); PersistenceManager manager = factory.getPersistenceManager(); Employee employee = new Employee(); employee.setFirstName("Bob"); employee.setLastName("Smith"); manager.makePersistent(employee);
To modify JDO objects within a transaction context, begin and commit a transactional object manually. A transactional object is an object that is subject to the transaction boundary. Use one of the following methods to obtain transactional objects:
Use getObjectById()
Execute a transactional-read query
Use the OracleAS TopLink extended API getTransactionalObject()
OracleAS TopLink executes the transactional-read query when the nontransactionalRead
flag of the current transaction is false. To obtain the current transaction from the PersistenceManager
, call currentTransaction()
.
Example 4-52 Update an Employee
This example illustrates how to add a new phone number to an employee object, modify the address, and increase the salary by 10 percent.
Transaction transaction = manager.currentTransaction(); if(!transaction.isActive()) { transaction.begin(); } // Get the transactional instance of the employee Object id = manager.getTransactionalObjectId(employee); Employee transactionalEmployee = manager.getObjectById(id, false); transactionalEmployee.getAddress().setCity("Ottawa"); transactionalEmployee.setSalary((int) (employee.getSalary() * 1.1)); transactionalEmployee.addPhoneNumber(new PhoneNumber("fax", "613", "3213452")); transaction.commit();
To delete JDO objects, use either deletePersistent()
or deletePersistentAll()
. The objects need not be transactional. If you do not manually begin the transaction, then OracleAS TopLink begins and commits the transaction when you invoke either deletePersistent ()
or deletePersistentAll ()
.
Deleting objects using deletePersistent()
or deletePersistentAll()
is similar to deleting objects using a Unit of Work. When you delete an object, you also automatically delete its privately owned parts, because they cannot exist without their owner. At commit time, OracleAS TopLink generates SQL to delete the objects, taking database constraints into account.
When you delete an object, set references to the deleted object to null or remove them from the collection, and modify references to the object using its transactional instance. This ensures that the object model reflects the change.
Example 4-53 Deleting a Team Leader from a Project
Transaction transaction = manager.currentTransaction(); if(!transaction.isActive()) { transaction.begin(); } Object id = manager.getTransactionalObjectId(projectNumber); Project transactionalProject = (Project) manager.getObjectById(id); Employee transactionalEmployee = transactionalProject.getTeamLeader(); // Remove team leader from the project transactionalProject.setTeamLeader(null); // Remove owner that is the team leader from phone numbers for(Enumeration enum = transactionalEmployee.getPhoneNumbers().elements(); enum.hasMoreElements();) { ((PhoneNumber) enum.nextElement()).setOwner(null); } manager.deletePersistent(transactionalEmployee); transaction.commit();
Example 4-54 Deleting a Phone Number
Transaction transaction = manager.currentTransaction(); if(!transaction.isActive()) { transaction.begin(); } Object id = manager.getTransactionalObjectId(phoneNumber); PhoneNumber transPhoneNo = (PhoneNumber) manager.getObjectById(id); transPhoneNo.getOwner().getPhoneNumbers().remove(transPhoneNo); manager.deletePersistent(phoneNumber); transaction.commit();
OracleAS TopLink does not support the JDO Query language, but includes support within JDO for the more advanced OracleAS TopLink query framework.
For more information about the OracleAS TopLink query framework, see Chapter 6, "Queries".
A key difference is that the JDO query language requires returned results to be a collection of candidate JDO instances (either a java.util.Collection
, or an Extent). Conversely, the return type in OracleAS TopLink depends on the type of query. For example, if you use a ReadAllQuery
, the result is a Vector
.
The following APIs support for the query factory:
Standard API:
newQuery(); newQuery(Class persistentClass);
OracleAS TopLink extended API:
newQuery(Class persistentClass, Expression expressionFilter);
Note: If you obtain Query from a differentnewQuery() API, this can result in a JDOUserException , or the creation of the query from the supported API.
|
You create a ReadAllQuery
with the query instance by default.
Table 4-19 and Table 4-20 summarize the most common public methods for the Query API and OracleAS TopLink extended API. For more information about the available methods for the Query API and OracleAS TopLink extended API, see the Oracle Application Server TopLink API Reference.
Table 4-19 Elements for Query API
Method Name | Description |
---|---|
close()
|
Releases resource to allow garbage collection. |
currentTransaction()
|
Specifies current transaction. |
deletePersistent(Object object)
|
Deletes objects. |
evict(Object object)
|
Marks objects as no longer needed in the cache. |
getExtent(Class queryClass, boolean readSubclasses)
|
Specifies extent. |
getIgnoreCache()setIgnoreCache(boolean ignoreCache)
|
Sets cache mode for queries.
The default is set to ignore cache from the persistence manager factory. |
getObjectById(Object object, boolean validate)
|
Obtains transactional state of object. |
isClosed()
|
Closes the PersistenceManager instance.
|
makePersistent(Object object)
|
Inserts persistent objects. |
makeTransactional(Object object)
|
Registers objects to Unit of Work, making them subject to transactional boundaries. |
newQuery()newQuery(Class queryClass)
|
Creates new query factory. |
refresh(Object object)
|
Refreshes objects. |
Table 4-20 Elements for OracleAS TopLink Extended API
Method Name | Description |
---|---|
getTransactionalObject(Object object)
|
Obtains transactional object |
Query(Class queryClass, Expression expression)
|
Creates query factory |
readAllObjects(Class domainClass)
|
Reads objects |
The JDOQuery
class implements the JDOQuery
interface. It defines the API to configure the query (filter, ordering, parameters, and variables) and to execute the query. OracleAS TopLink extends the query functionality to include the full OracleAS TopLink query framework.
For more information about the OracleAS TopLink query framework, see Chapter 6, "Queries".
You can customize the query to use advanced features, such as batch reading, stored procedure calls, partial object reading, and query by example. OracleAS TopLink does not support the JDO query language, but you can employ either SQL or EJB QL in the JDOQuery
interface.
Each JDOQuery
instance is associated with an OracleAS TopLink query. To obtain a JDOQuery
from the PersistenceManager
, call a supported newQuery
method. OracleAS TopLink creates a new ReadAllQuery
and associates it with the query. Call asReadObjectQuery()
, asReadAllQuery()
, or asReportQuery
to set the JDO Query OracleAS TopLink query to a specific type.
The OracleAS TopLink query framework provides most of its functionality as a public API. To create a customized OracleAS TopLink query and associate it with the JDO Query, call the setQuery()
method to build complex functionality into your queries.
Customized OracleAS TopLink queries give you the complete functionality of the OracleAS TopLink query framework. For example, use a DirectReadQuery
with custom SQL to read the ID column of the employee.
Note: OracleAS TopLink extended APIs support a specific OracleAS TopLink query type. To avoid exceptions, match the API to the correct query type. See Table 4-21 for correct usage. |
Example 4-55 Use a ReadAllQuery to Read All Employees Who Live in New York
Expression expression = new ExpressionBuilder().get("address").get("city").equal("New York"); Query query = manager.newQuery(Employee.class, expression); Vector employees = (Vector) query.execute();
Example 4-56 Use a ReadObjectQuery to Read the Employee Named Bob Smith
Expression exp1 = new ExpressionBuilder().get("firstName").equal("Bob"); Expression exp2 = new ExpressionBuilder().get("lastName").equal("Smith "); JDOQuery jdoQuery = (JDOQuery) manager.newQuery(Employee.class); jdoQuery.asReadObjectQuery(); jdoQuery.setFilter(exp1.and(exp2)); Employee employee = (Employee) jdoQuery.execute();
Example 4-57 Use a ReportQuery to Report Employee's Salary
JDOQuery jdoQuery = (JDOQuery) manager.newQuery(Employee.class); jdoQuery.asReportQuery(); jdoQuery.addCount(); jdoQuery.addMinimum("min_salary",jdoQuery.getExpressionBuilder().get("salary")); jdoQuery.addMaximum("max_salary",jdoQuery.getExpressionBuilder().get("salary")); jdoQuery.addAverage( "average salary",jdoQuery.getExpressionBuilder().get("salary") ); // Return a vector of one DatabaseRow that contains reported info Vector reportQueryResults = (Vector) jdoQuery.execute();
Example 4-58 Use a Customized DirectReadQuery to Read Employee 's id column
DirectReadQuery TopLinkQuery = new DirectReadQuery(); topLinkQuery.setSQLString("SELECT EMP_ID FROM EMPLOYEE"); JDOQuery jdoQuery = (JDOQuery) manager.newQuery(); jdoQuery.setQuery(topLinkQuery); // Return a Vector of DatabaseRows that contain ids Vector ids = (Vector)jdoQuery.execute(query);
Table 4-21 and Table 4-22 summarize the most common public methods for the JDO Query API and OracleAS TopLink extended API. For more information about the available methods for the JDO Query API and OracleAS TopLink extended API, see the Oracle Application Server TopLink API Reference.
Table 4-21 Elements for JDO Query API
Method Name | Description |
---|---|
close(Object queryResult)
|
Closes cursor result. |
declareParameters(String parameters)
|
Declares query parameters. |
execute()
|
Executes query. |
getIgnoreCache()
|
Sets cache mode for query result. |
getPersistenceManager()
|
PersistenceManager |
setClass(Class queryClass)
|
ReadObjectQuery, ReadAllQuery, ReportQuery |
setOrdering(String ordering)
|
ReadAllQuery |
Table 4-22 Elements for OracleAS TopLink Extended JDO API
Method Name | Description |
---|---|
asReadAllQuery()
|
Converts the query. |
getQuery()
|
Accesses the OracleAS TopLink query.
The default is set to |
acquireLocks()
|
ReadObjectQuery, ReadAllQuery, ReportQuery |
checkCacheByExactPrimaryKey()
|
ReadObjectQuery |
addAscendingOrdering(String queryKeyName)
|
ReadAllQuery |
addAttribute(String itemName)
|
Query arguments |
addArgument(String argumentName)
|
DatabaseQuery |
The JDOTransaction
class implements the JDOTransaction
interface. It defines the basic begin, commit, and roll back APIs, and synchronization callbacks within the Unit of Work. It supports the optional nontransactional read JDO feature.
Set the read mode of a JDO transaction by calling the setNontransactionalRead()
method.
Note: To avoid exceptions, do not change the read mode while the transaction is active. |
Here are the available read modes:
Nontransactional Read: Nontransactional reads provide data from the database, but do not attempt to update the database with changes at commit time. This transaction mode is the PersistenceManagerFactory
default. Nontransactional reads support nested Units of Work.
When you execute queries in nontransactional read mode, their results are not subject to the transactional boundary. To update objects from the query results, modify objects in their transactional instances.
To enable nontransactional read mode, set setNontransactionalRead()
to true.
Transactional Read: Transactional reads provide data from the database and write any changes to the database at commit time. When you use transactional read, OracleAS TopLink uses the same Unit of Work for all data store interactions (begin, commit, roll back). Because this can cause the cache to grow large over time, use this mode only with short-lived PersistenceManager instances. Doing this allows garbage collection on the Unit of Work.
When you execute queries in transactional read mode, the results are transactional instances, subject to the transactional boundary. You can update objects from the result of a query that is executed in transactional mode.
Because you use the same Unit of Work in this mode, the transaction is always active. You must release it when you change the read mode from transactional read to nontransactional read.
Note: Before you call the OracleAS TopLink extended APIrelease() method, commit all changes to avoid losing the transaction.
|
To enable transactional read mode, set the setNontransactionalRead()
flag to false.