Skip Headers
Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2)
Part No. B15901-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

OracleAS TopLink Support for Java Data Objects (JDO)

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:

Understanding the JDO API

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.

Figure 4-12 Understanding the JDO API

Description of jdo_api.gif follows
Description of the illustration jdo_api.gif

JDO Implementation

OracleAS TopLink implements the PersistenceManagerFactory, PersistenceManager, and Transaction interfaces, and extends the query functionality to include the complete OracleAS TopLink query framework.

JDOPersistenceManagerFactory

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.

Creating a JDOPersistenceManagerFactory

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());

Obtaining PersistenceManager

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.

Reference

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()

setIgnoreCache(boolean ignoreCache)

Query mode that specifies whether cached instances are considered when evaluating the filter expression.

The default is set to FALSE.

getNontransactionalRead()

setNontransactionalRead(boolean nontransactionalRead)

Transaction mode that allows you to read instances outside a transaction.

The default is set to FALSE.

getConnectionUserName()

setConnectionUserName(String userName)

getConnectionPassword()

setConnectionPassword(String password)

getConnectionURL()

setConnectionURL(String URL)

getConnectionDriverName()

setConnectionDriverName(String driverName)

Available settings if the factory is constructed from an OracleAS TopLink project.

Derives the default user name, password, URL, driver from project login.

getPersistenceManager()

getPersistenceManager(String userid, String password)

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

JDOPersistenceManager

The JDOPersistenceManager class is the factory for the Query interface and contains methods to access transactions, and manage the persistent life cycle instances.

Inserting JDO objects

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);

Updating JDO Objects

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();

Deleting Persistent Objects

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();

Obtaining Query

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 different newQuery() 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.

Reference

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)

deletePersistentAll(Collection objects)

deletePersistentAll(java.lang.Object[] objects)

Deletes objects.
evict(Object object)

evictAll()

evictAll(Collection objects)

evictAll(Object[] objects)

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)

getTransactionalObjectId(Object object)

Obtains transactional state of object.
isClosed() Closes the PersistenceManager instance.
makePersistent(Object object)

makePersistentAll(Collection objects)

makePersistentAll(Object[] objects)

Inserts persistent objects.
makeTransactional(Object object)

makeTransactionalAll(Collection objects)

makeTransactionalAll(Object[] objects)

Registers objects to Unit of Work, making them subject to transactional boundaries.
newQuery()newQuery(Class queryClass) Creates new query factory.
refresh(Object object)

refreshAll()

refreshAll(Collection objects)

refreshAll(Object[] objects)

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)

readAllObjects(Class domainClass)

readObject(Class domainClass, Expression expression)

Reads objects

JDOQuery

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.

Customizing the Query Using the OracleAS TopLink Query Framework

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);

Reference

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()

execute(Object arg1)

execute (Object arg1, Object arg2)

execute(Object arg1, Object arg2, Object arg3)

executeWithArray(java.lang.Object[] arg1)

executeWithMap(Map arg1)

Executes query.
getIgnoreCache()

setIgnoreCache(boolean ignoreCache)

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()

asReadObjectQuery()

asReportQuery()

Converts the query.
getQuery()

setQuery(DatabaseQuery newQuery)

Accesses the OracleAS TopLink query.

The default is set to ReadAllQuery.

acquireLocks()

acquireLocksWithoutWaiting()

addJoinedAttribute(String attributeName)

addJoinedAttribute(Expression attributeExpression)

addPartialAttribute(String attributeName)

addPartialAttribute(Expression attributeExpression)

checkCacheOnly()

dontAcquireLocks()

dontRefreshIdentityMapResult()

dontRefreshRemoteIdentityMapResult()

getExampleObject()

getExpressionBuilder()

setQueryByExampleFilter(Object exampleObject)

setQueryByExamplePolicy(QueryByExamplePolicy policy)

setShouldRefreshIdentityMapResult(boolean shouldRefreshIdentityMapResult)

shouldRefreshIdentityMapResult()

ReadObjectQuery, ReadAllQuery, ReportQuery
checkCacheByExactPrimaryKey()

checkCacheByPrimaryKey()

checkCacheThenDatabase()

conformResultsInUnitOfWork()

getReadObjectQuery()

ReadObjectQuery
addAscendingOrdering(String queryKeyName)

addDescendingOrdering(String queryKeyName)

addOrdering(Expression orderingExpression)

addBatchReadAttribute(String attributeName)

addBatchReadAttribute(Expression attributeExpression)

addStandardDeviation(String itemName)

addStandardDeviation(String itemName,Expression attributeExpression)

addSum(String itemName)

addSum(String itemName, Expression attributeExpression)

addVariance(String itemName)

addVariance(String itemName, Expression attributeExpression)

getReadAllQuery()

useCollectionClass(Class concreteClass)

useCursoredStream()

useCursoredStream(int initialReadSize, int pageSize)

useCursoredStream(int initialReadSize, int pageSize, ValueReadQuery sizeQuery)

useDistinct()

useMapClass(Class concreteClass, String methodName)

useScrollableCursor()

useScrollableCursor(int pageSize)

ReadAllQuery
addAttribute(String itemName)

addAttribute(String itemName, Expression attributeExpression)

addAverage(String itemName)

addAverage(String itemName, Expression attributeExpression)

addCount()

addCount(String itemName)

addCount(String itemName, Expression attributeExpression)

addGrouping(String attributeName)

addGrouping(Expression expression)

addItem(String itemName, ExpressionattributeExpression)

addMaximum(String itemName)

addMaximum(String itemName, Expression attributeExpression)

addMinimum(String itemName)

addMinimum(String itemName, Expression attributeExpression)

getReportQuery()

Query arguments
addArgument(String argumentName)

bindAllParameters()

cacheStatement()

cascadeAllParts()

cascadePrivateParts()

dontBindAllParameters()

dontCacheStatement()

dontCascadeParts()

dontCheckCache()

dontMaintainCache()

dontUseDistinct()

getQueryTimeout()

getReferenceClass()

getSelectionCriteria()

refreshIdentityMapResult()

setCall(Call call)

setEJBQLString(String ejbqlString)

setFilter(Expression selectionCriteria)

setQueryTimeout(int queryTimeout)

setSQLString(String sqlString)

setShouldBindAllParameters(booleanshouldBindAllParameters)

setShouldCacheStatement(booleanshouldCacheStatement)

setShouldMaintainCache(booleanshouldMaintainCache)

shouldBindAllParameters()

shouldCacheStatement()

shouldCascadeAllParts()

shouldCascadeParts()

shouldCascadePrivateParts()

shouldMaintainCache()

DatabaseQuery

JDOTransaction

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.

Read Modes

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 API release() method, commit all changes to avoid losing the transaction.

To enable transactional read mode, set the setNontransactionalRead() flag to false.

Synchronization

You can register a Synchronization listener with the transaction. The transaction notifies the listener when the transaction is complete. Doing this returns the beforeCompletion and afterCompletion methods when the precommit and postcommit events of the Unit of Work trigger.