Spring's data access abstraction as a whole — and hence its support for O/R mapping tools — is designed to be extensible. It's possible to plug in additional persistence APIs, while providing consistent programming models to developers working with Spring. As we have already learned, the two main areas are implementation of data access objects and transaction management: All integration packages are supposed to follow the usual Spring patterns in those respects.
In principle, it is possible to implement support for any O/R mapping framework — or arbitrary persistence framework. Implementations can build on generic base classes such as org.springframework.transaction.support.AbstractPlatformTransactionManager and use existing support packages as a starting point. However, sophisticated integration is still a significant effort, which usually requires in-depth knowledge about the semantics of the respective persistence tool.
As outlined in the introduction of OJB at the beginning of this chapter, OJB offers multiple data access APIs. Spring just includes dedicated support for OJB's PersistenceBroker API; support for OJB's ODMG layer is not planned because ODMG is an old API that predates the Java collections framework and is also dated in other respects. OJB's third API, the JDO plugin, can be used via Spring's JDO support, without special facilities.
The PersistenceBroker API offers full-fledged querying and full access to OJB's mapping power. However, it does not perform automatic change detection; it rather relies on explicit store calls for primary persistent objects (which might automatically store dependent objects too). Handling a PersistenceBroker is significantly less complex than working with Hibernate or JDO because there are no strict lifecycle requirements imposed by automatic change detection. A PersistenceBroker is particularly suitable for detached objects, which need to be explicitly stored in any case.
The facilities offered by Spring's support for the OJB PersistenceBroker are:
org.springframework.orm.ojb.PersistenceBrokerTemplate: A data access class to be used in DAOs, seamlessly handling OJB PersistenceBrokers in the background. It automatically participates in Spring-driven transactions and converts PersistenceBrokerExceptions into Spring's generic DataAccessException hierarchy.
org.springframework.orm.ojb.PersistenceBrokerTransactionManager: A local transaction strategy, executing transactions on a single target database (that is, a single PersistenceBroker key). This strategy works in any environment, in contrast to JtaTransactionManager, which depends on a J2EE server (or a standalone JTA implementation).
org.springframework.orm.ojb.support.PersistenceBrokerDaoSupport: A convenient base class for DAO implementations, taking a PersistenceBroker key and providing a PersistenceBrokerTemplate instance for it.
org.springframework.orm.ojb.support.LocalDataSourceConnectionFactory: An OJB ConnectionFactory that allows you to use a Spring-managed DataSource bean as a connection pool. Needs to be defined in OJB configuration.
In contrast to Hibernate and JDO, OJB does not use a factory instance as a central configuration point. Instead, it uses a singleton that initializes on first access and enables it to create PersistenceBrokers for a specific database configuration. A specific configuration is identified by a PersistenceBroker key; this is what the Spring-provided support classes need to work with. The OJB team plans to introduce instance-based configuration in OJB 1.1; in the meantime, OJB configuration is driven by the central OJB.properties file even in a Spring environment.
Spring's support for TopLink is a recent addition to Spring's O/R mapping support; as of early 2005, it is available from Oracle's OTN. It was largely developed by the TopLink team at Oracle, following Spring's consistent architectural approach, and with the support of the Spring team. At the time of this writing, Oracle plans to donate the code to the Spring project, under Spring's Apache license, so that it can be shipped with Spring 1.2.
TopLink is a sophisticated, full-fledged O/R mapping solution, which dates back to 1997 (for its first Java implementation) and 1994 (for its genesis in Smalltalk). It offers a sophisticated Mapping Workbench UI to support development and offers a particularly wide range of object-relational mappings. TopLink is usable either in a J2EE or J2SE environment.
TopLink has some significant semantic differences to both Hibernate and JDO. The biggest differentiator is its change detection mechanism. TopLink uses snapshot comparisons, but only for objects that have been explicitly registered with a TopLink UnitOfWork; objects loaded by a plain TopLink Session are strictly read-only. While this allows for efficient use of cached persistent objects — sharing a single instance for multiple Sessions — it imposes some restrictions on the handling of persistent objects. Application code must take care to modify only references returned by a UnitOfWork; accidental modifications to objects returned by a Session will lead to side effects and cache corruption. It is possible that future releases of the Spring TopLink integration will conceal this requirement from the application developer, making using TopLink with Spring even more compelling for TopLink users: Please check the TopLink website for details. The upside of this design decision is that TopLink can deal more efficiently than Hibernate with very large numbers of persistent objects in memory, at least as long as only a minority are modified.
It is beyond the scope of this chapter to discuss TopLink and its capabilities in detail. Please refer to Oracle's documentation (www.oracle.com/technology/products/ias/toplink/index.html) for more details.
The facilities offered by Spring's TopLink support are:
org.springframework.orm.toplink.TopLinkTemplate: A data access class to be used in DAOs, seamlessly handling TopLink Sessions in the background. It automatically participates in Spring-driven transactions and converts TopLink exceptions into Spring's generic DataAccessException hierarchy.
org.springframework.orm.toplink.SessionFactoryBean: A convenient way to set up a TopLink SessionFactory in a Spring context. SessionFactory references can then be passed to DAOs, typically via Spring bean references.
org.springframework.orm.toplink.TopLinkTransactionManager: A local transaction strategy, executing transactions on a single target SessionFactory. This strategy works in any environment, in contrast to JtaTransactionManager, which depends on a J2EE server (or a standalone JTA implementation).
org.springframework.orm.toplink.support.TopLinkDaoSupport: A convenient base class for DAO implementations, taking a SessionFactory reference and providing a TopLinkTemplate instance for it.
Essentially, the usage model of the TopLink support closely follows Spring's Hibernate and JDO support. However, as with the differences between Hibernate and JDO, the application needs to be aware of the special semantics involved in TopLink usage, in particular regarding modifications to loaded instances.
For further information, see the page on Spring/TopLink integration on the TopLink website at www.oracle.com/technology/products/ias/toplink/preview/spring/index.html.
TopLink support rounds out Spring's support for leading O/R mapping technologies. TopLink is and is likely to remain an important O/R mapping product, especially among enterprise-class users, and hence it is important for Spring to support it fully. The fact that the TopLink integration was developed at Oracle, in response to requests from TopLink users, is proof that Spring's data access integration is becoming recognized as a significant integration platform.
A key benefit of the Spring data access abstraction is that the consistent approach it offers helps to localize differences between persistence tools in DAO implementation classes. For example, in presentations on Spring, we often find that attendees can quickly come to grips with, say, the TopLink implementation of the PetClinic, even if they have no previous experience with TopLink. This would probably not be the case if they saw an implementation of the same functionality using TopLink without Spring.
During the editing of this book, the developers of the open source Cayenne O/R mapping project (www.objectstyle.org/cayenne/) developed Spring support for their product. Please refer to the Cayenne website for further information. As in the case of TopLink, this resulted from interest within their own community, and both communities benefit from the integration.
As you can see, this strong, proven conceptual basis makes it easy for Spring to integrate with additional — or emerging — persistence technologies.
The most important emerging persistence technology is the POJO persistence specification to be delivered by the JSR-220 (EJB 3.0) expert group. Note that this specification will not be tied to an EJB container. While the nature of this specification is still not entirely clear, the major inputs to its definition are coming from the developers of Hibernate, TopLink, and some JDO products, and it is clear that Spring's data access abstraction will work with the result, both inside or outside an EJB container.
If you wish to use JSR-220 persistence once it is available, using your O/R mapping framework via the Spring abstraction will ease the migration path. Not only does using Spring's data access abstraction make your job easier, whatever persistence technology you use, it also provides a unique partial decoupling from the underlying persistence API.
Spring will support JSR-220 as soon as final binaries are released. As of early 2005, there is no solid API documentation for JSR-220 yet, and no binaries have officially been released.