diff --git a/spring-framework-reference/src/classic-spring.xml b/spring-framework-reference/src/classic-spring.xml
index 27f41258bdd..53a879f0e18 100644
--- a/spring-framework-reference/src/classic-spring.xml
+++ b/spring-framework-reference/src/classic-spring.xml
@@ -15,8 +15,7 @@
This section documents the classic usage patterns that you might
encounter in a legacy Spring application. For the currently recommended
- usage patterns, please refer to the chapter.
-
+ usage patterns, please refer to the chapter.
Hibernate
@@ -170,6 +169,93 @@
+
+ JDO
+
+ For the currently recommended usage patterns for JDO see
+
+
+ JdoTemplate and
+ JdoDaoSupport
+
+ Each JDO-based DAO will then receive the
+ PersistenceManagerFactory through
+ dependency injection. Such a DAO could be coded against plain JDO API,
+ working with the given
+ PersistenceManagerFactory, but will
+ usually rather be used with the Spring Framework's
+ JdoTemplate:
+
+ <beans>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="persistenceManagerFactory" ref="myPmf"/>
+ </bean>
+
+</beans>
+
+ public class ProductDaoImpl implements ProductDao {
+
+ private JdoTemplate jdoTemplate;
+
+ public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
+ this.jdoTemplate = new JdoTemplate(pmf);
+ }
+
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return (Collection) this.jdoTemplate.execute(new JdoCallback() {
+ public Object doInJdo(PersistenceManager pm) throws JDOException {
+ Query query = pm.newQuery(Product.class, "category = pCategory");
+ query.declareParameters("String pCategory");
+ List result = query.execute(category);
+ // do some further stuff with the result list
+ return result;
+ }
+ });
+ }
+}
+
+ A callback implementation can effectively be used for any JDO
+ data access. JdoTemplate will ensure that
+ PersistenceManagers are properly opened and
+ closed, and automatically participate in transactions. The template
+ instances are thread-safe and reusable, they can thus be kept as
+ instance variables of the surrounding class. For simple single-step
+ actions such as a single find,
+ load, makePersistent, or
+ delete call, JdoTemplate
+ offers alternative convenience methods that can replace such one line
+ callback implementations. Furthermore, Spring provides a convenient
+ JdoDaoSupport base class that provides a
+ setPersistenceManagerFactory(..) method for
+ receiving a PersistenceManagerFactory, and
+ getPersistenceManagerFactory() and
+ getJdoTemplate() for use by subclasses. In
+ combination, this allows for very simple DAO implementations for
+ typical requirements:
+
+ public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
+
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return getJdoTemplate().find(
+ Product.class, "category = pCategory", "String category", new Object[] {category});
+ }
+}
+
+ As alternative to working with Spring's
+ JdoTemplate, you can also code Spring-based
+ DAOs at the JDO API level, explicitly opening and closing a
+ PersistenceManager. As elaborated in
+ the corresponding Hibernate section, the main advantage of this
+ approach is that your data access code is able to throw checked
+ exceptions. JdoDaoSupport offers a variety of
+ support methods for this scenario, for fetching and releasing a
+ transactional PersistenceManager as
+ well as for converting exceptions.
+
+
+
JPA
@@ -259,167 +345,6 @@
it.
-
-
- JDO
-
- For the currently recommended usage patterns for JDO see
-
-
- JdoTemplate and
- JdoDaoSupport
-
- Each JDO-based DAO will then receive the
- PersistenceManagerFactory through
- dependency injection. Such a DAO could be coded against plain JDO API,
- working with the given
- PersistenceManagerFactory, but will
- usually rather be used with the Spring Framework's
- JdoTemplate:
-
- <beans>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="persistenceManagerFactory" ref="myPmf"/>
- </bean>
-
-</beans>
-
- public class ProductDaoImpl implements ProductDao {
-
- private JdoTemplate jdoTemplate;
-
- public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
- this.jdoTemplate = new JdoTemplate(pmf);
- }
-
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return (Collection) this.jdoTemplate.execute(new JdoCallback() {
- public Object doInJdo(PersistenceManager pm) throws JDOException {
- Query query = pm.newQuery(Product.class, "category = pCategory");
- query.declareParameters("String pCategory");
- List result = query.execute(category);
- // do some further stuff with the result list
- return result;
- }
- });
- }
-}
-
- A callback implementation can effectively be used for any JDO
- data access. JdoTemplate will ensure that
- PersistenceManagers are properly opened and
- closed, and automatically participate in transactions. The template
- instances are thread-safe and reusable, they can thus be kept as
- instance variables of the surrounding class. For simple single-step
- actions such as a single find,
- load, makePersistent, or
- delete call, JdoTemplate
- offers alternative convenience methods that can replace such one line
- callback implementations. Furthermore, Spring provides a convenient
- JdoDaoSupport base class that provides a
- setPersistenceManagerFactory(..) method for
- receiving a PersistenceManagerFactory, and
- getPersistenceManagerFactory() and
- getJdoTemplate() for use by subclasses. In
- combination, this allows for very simple DAO implementations for
- typical requirements:
-
- public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
-
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return getJdoTemplate().find(
- Product.class, "category = pCategory", "String category", new Object[] {category});
- }
-}
-
- As alternative to working with Spring's
- JdoTemplate, you can also code Spring-based
- DAOs at the JDO API level, explicitly opening and closing a
- PersistenceManager. As elaborated in
- the corresponding Hibernate section, the main advantage of this
- approach is that your data access code is able to throw checked
- exceptions. JdoDaoSupport offers a variety of
- support methods for this scenario, for fetching and releasing a
- transactional PersistenceManager as
- well as for converting exceptions.
-
-
-
-
- iBATIS
-
- For the currently recommended usage patterns for iBATIS see
-
-
- Using SqlMapClientTemplate and
- SqlMapClientDaoSupport
-
- The SqlMapClientDaoSupport class offers a
- supporting class similar to the
- SqlMapDaoSupport. We extend it to implement our
- DAO:
-
- public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
-
- public Account getAccount(String email) throws DataAccessException {
- return (Account) getSqlMapClientTemplate().queryForObject("getAccountByEmail", email);
- }
-
- public void insertAccount(Account account) throws DataAccessException {
- getSqlMapClientTemplate().update("insertAccount", account);
- }
-}
-
- In the DAO, we use the pre-configured
- SqlMapClientTemplate to execute the queries,
- after setting up the SqlMapAccountDao in the
- application context and wiring it with our
- SqlMapClient instance:
-
- <beans>
-
- <bean id="accountDao" class="example.SqlMapAccountDao">
- <property name="sqlMapClient" ref="sqlMapClient"/>
- </bean>
-
-</beans>
-
- Note that a SqlMapTemplate instance could
- also be created manually, passing in the
- SqlMapClient as constructor argument. The
- SqlMapClientDaoSupport base class simply
- pre-initializes a SqlMapClientTemplate instance
- for us.
-
- The SqlMapClientTemplate also offers a
- generic execute method, taking a custom
- SqlMapClientCallback implementation as argument.
- This can, for example, be used for batching:
-
- public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
-
- public void insertAccount(Account account) throws DataAccessException {
- getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
- public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
- executor.startBatch();
- executor.update("insertAccount", account);
- executor.update("insertAddress", account.getAddress());
- executor.executeBatch();
- }
- });
- }
-}
-
- In general, any combination of operations offered by the native
- SqlMapExecutor API can be used in such a callback.
- Any SQLException thrown will automatically get
- converted to Spring's generic
- DataAccessException hierarchy.
-
-
diff --git a/spring-framework-reference/src/orm.xml b/spring-framework-reference/src/orm.xml
index 4a55059f74c..51441edcf60 100644
--- a/spring-framework-reference/src/orm.xml
+++ b/spring-framework-reference/src/orm.xml
@@ -8,17 +8,18 @@
Introduction
The Spring Framework provides integration with Hibernate,
- JDO, iBATIS SQL Maps and JPA: in terms of
+ JPA, JDO and iBATIS SQL Maps: in terms of
resource management, DAO implementation support, and transaction
strategies. For example for Hibernate, there is first-class support with
lots of IoC convenience features, addressing many typical Hibernate
integration issues. All of these support packages for O/R (Object
- Relational) mappers comply with Spring's generic transaction and DAO
- exception hierarchies. There are usually two integration styles: either
- using Spring's DAO 'templates' or coding DAOs against plain
- Hibernate/JDO/JPA/etc APIs. In both cases, DAOs can be configured through
- Dependency Injection and participate in Spring's resource and transaction
- management.
+ Relational) mappers can be configured through Dependency Injection, can
+ participate in Spring's resource and transaction management and they
+ comply with Spring's generic transaction and DAO exception hierarchies.
+ The curently recommended integration style is to code DAOs against plain
+ Hibernate/JPA/JDO/etc APIs. The older style of using Spring's DAO
+ 'templates' is no longer recommended and the coverage of this style can be
+ found in the Appendix.
Spring adds significant support when using the O/R mapping layer of
your choice to create data access applications. First of all, you should
@@ -106,15 +107,119 @@
It also leverages declarative transaction demarcation with different
transaction strategies.
- The JPetStore sample illustrates the use of iBATIS SQL Maps in a
- Spring environment. It also features two web tier versions: one based on
- Spring Web MVC, one based on Struts.
-
Beyond the samples shipped with Spring, there are a variety of
- Spring-based O/R mapping samples provided by specific vendors: for
- example, the JDO implementations JPOX () and Kodo ().
+ Spring-based O/R mapping samples provided by specific vendors.
+
+
+
+ General ORM integration considerations
+
+ This section highlights some common considerations regardles of
+ which ORM technology you use. The Hibernate section provides more details
+ and also show these features/configurations in a concrete context.
+
+ The major goal is to allow for clear application layering, with any
+ data access and transaction technology, and for loose coupling of
+ application objects. No more business service dependencies on the data
+ access or transaction strategy, no more hard-coded resource lookups, no
+ more hard-to-replace singletons, no more custom service registries. One
+ simple and consistent approach to wiring up application objects, keeping
+ them as reusable and free from container dependencies as possible. All the
+ individual data access features are usable on their own but integrate
+ nicely with Spring's application context concept, providing XML-based
+ configuration and cross-referencing of plain JavaBean instances that don't
+ need to be Spring-aware. In a typical Spring application, many important
+ objects are JavaBeans: data access templates, data access objects,
+ transaction managers, business services (that use the data access objects
+ and transaction managers), web view resolvers, web controllers (that use
+ the business services),and so on.
+
+
+ Resource and Transaction management
+
+ Typical business applications are often cluttered with repetitive
+ resource management code. Many projects try to invent their own
+ solutions for this issue, sometimes sacrificing proper handling of
+ failures for programming convenience. Spring advocates strikingly simple
+ solutions for proper resource handling, namely IoC via templating in the
+ case of JDBC and applying AOP interceptors for the ORM technologies.
+
+
+ The infrastructure cares for proper resource handling, and for
+ appropriate conversion of specific API exceptions to an unchecked
+ infrastructure exception hierarchy. Spring introduces a DAO exception
+ hierarchy, applicable to any data access strategy. For direct JDBC, the
+ JdbcTemplate class mentioned in a previous
+ section cares for connection handling, and for proper conversion of
+ SQLException to the
+ DataAccessException hierarchy, including
+ translation of database-specific SQL error codes to meaningful exception
+ classes. For ORM technologies, see the next section for how to get the
+ same exception translation benefits.
+
+ When it comes to transaction management the
+ JdbcTemplate class hooks in to the Spring
+ transaction support and supports both JTA and JDBC transactions, via
+ respective Spring transaction managers. For the supported ORM
+ technologies Spring offers Hibernate, JPA and JDO support via the
+ Hibernate / JPA / JDO transaction managers as well as JTA support. For
+ more details on the transaction support see the chapter.
+
+
+
+ Exception Translation
+
+ Using Hibernate, JDO or JPA in a DAO means that you will have to
+ decide how to handle the persistence technology's native exception
+ classes. The DAO could potentially throw a subclass of a
+ HibernateException,
+ JDOException or
+ PersistenceException depending on the technology
+ in use. These exceptions are all run-time exceptions and does not have
+ to be declared or caught. You would potentially also have to deal with
+ IllegalArgumentException and
+ IllegalStateException. This means that callers
+ can only treat exceptions as generally fatal - unless they want to
+ depend on the persistence technology's own exception structure. Catching
+ specific causes such as an optimistic locking failure is not possible
+ without tying the caller to the implementation strategy. This tradeoff
+ might be acceptable to applications that are strongly ORM-based and/or
+ do not need any special exception treatment. However, Spring offers a
+ solution allowing exception translation to be applied transparently
+ through the @Repository
+ annotation:
+
+ @Repository
+public class ProductDaoImpl implements ProductDao {
+
+ // class body here...
+
+}
+
+ <beans>
+
+ <!-- Exception translation bean post processor -->
+ <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl"/>
+
+</beans>
+
+ The postprocessor will automatically look for all exception
+ translators (implementations of the
+ PersistenceExceptionTranslator interface)
+ and advise all beans marked with the
+ @Repository annotation so that the
+ discovered translators can intercept and apply the appropriate
+ translation on the thrown exceptions.
+
+ In summary: DAOs can be implemented based on the plain persistence
+ technology's API and annotations, while still being able to benefit from
+ Spring-managed transactions, dependency injection, and transparent
+ exception conversion (if desired) to Spring's custom exception
+ hierarchies.
+
@@ -134,51 +239,6 @@
higher. Neither Hibernate 2.1 nor Hibernate 3.0 are supported
anymore.
-
- Resource management
-
- Typical business applications are often cluttered with repetitive
- resource management code. Many projects try to invent their own
- solutions for this issue, sometimes sacrificing proper handling of
- failures for programming convenience. Spring advocates strikingly simple
- solutions for proper resource handling, namely IoC via templating; for
- example infrastructure classes with callback interfaces, or applying AOP
- interceptors. The infrastructure cares for proper resource handling, and
- for appropriate conversion of specific API exceptions to an unchecked
- infrastructure exception hierarchy. Spring introduces a DAO exception
- hierarchy, applicable to any data access strategy. For direct JDBC, the
- JdbcTemplate class mentioned in a previous
- section cares for connection handling, and for proper conversion of
- SQLException to the
- DataAccessException hierarchy, including
- translation of database-specific SQL error codes to meaningful exception
- classes. It supports both JTA and JDBC transactions, via respective
- Spring transaction managers.
-
- Spring also offers Hibernate and JDO support, consisting of a
- HibernateTemplate /
- JdoTemplate analogous to
- JdbcTemplate, a
- HibernateInterceptor /
- JdoInterceptor, and a Hibernate / JDO transaction
- manager. The major goal is to allow for clear application layering, with
- any data access and transaction technology, and for loose coupling of
- application objects. No more business service dependencies on the data
- access or transaction strategy, no more hard-coded resource lookups, no
- more hard-to-replace singletons, no more custom service registries. One
- simple and consistent approach to wiring up application objects, keeping
- them as reusable and free from container dependencies as possible. All
- the individual data access features are usable on their own but
- integrate nicely with Spring's application context concept, providing
- XML-based configuration and cross-referencing of plain JavaBean
- instances that don't need to be Spring-aware. In a typical Spring
- application, many important objects are JavaBeans: data access
- templates, data access objects (that use the templates), transaction
- managers, business services (that use the data access objects and
- transaction managers), web view resolvers, web controllers (that use the
- business services),and so on.
-
-
SessionFactory setup in a Spring
container
@@ -801,8 +861,326 @@
cache.
+
+
-
+
+ JDO
+
+ Spring supports the standard JDO 2.0/2.1 API as data access
+ strategy, following the same style as the Hibernate support. The
+ corresponding integration classes reside in the
+ org.springframework.orm.jdo package.
+
+
+ PersistenceManagerFactory
+ setup
+
+ Spring provides a
+ LocalPersistenceManagerFactoryBean class that
+ allows for defining a local JDO
+ PersistenceManagerFactory within a Spring
+ application context:
+
+ <beans>
+
+ <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
+ <property name="configLocation" value="classpath:kodo.properties"/>
+ </bean>
+
+</beans>
+
+ Alternatively, a
+ PersistenceManagerFactory can also be set
+ up through direct instantiation of a
+ PersistenceManagerFactory implementation
+ class. A JDO PersistenceManagerFactory
+ implementation class is supposed to follow the JavaBeans pattern, just
+ like a JDBC DataSource implementation
+ class, which is a natural fit for a Spring bean definition. This setup
+ style usually supports a Spring-defined JDBC
+ DataSource, passed into the
+ "connectionFactory" property. For example, for the open source JDO
+ implementation DataNucleus (formerly JPOX) (http://www.datanucleus.org/):
+
+ <beans>
+
+ <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
+ <property name="driverClassName" value="${jdbc.driverClassName}"/>
+ <property name="url" value="${jdbc.url}"/>
+ <property name="username" value="${jdbc.username}"/>
+ <property name="password" value="${jdbc.password}"/>
+ </bean>
+
+ <bean id="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close">
+ <property name="connectionFactory" ref="dataSource"/>
+ <property name="nontransactionalRead" value="true"/>
+ </bean>
+
+</beans>
+
+ A JDO PersistenceManagerFactory can
+ also be set up in the JNDI environment of a J2EE application server,
+ usually through the JCA connector provided by the particular JDO
+ implementation. Spring's standard
+ JndiObjectFactoryBean can be used to retrieve and
+ expose such a PersistenceManagerFactory.
+ However, outside an EJB context, there is often no compelling benefit in
+ holding the PersistenceManagerFactory in
+ JNDI: only choose such setup for a good reason. See "container resources
+ versus local resources" in the Hibernate section for a discussion; the
+ arguments there apply to JDO as well.
+
+
+
+ Implementing DAOs based on the plain JDO API
+
+ DAOs can also be written against plain JDO API, without any Spring
+ dependencies, directly using an injected
+ PersistenceManagerFactory. A
+ corresponding DAO implementation looks like as follows:
+
+ public class ProductDaoImpl implements ProductDao {
+
+ private PersistenceManagerFactory persistenceManagerFactory;
+
+ public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
+ this.persistenceManagerFactory = pmf;
+ }
+
+ public Collection loadProductsByCategory(String category) {
+ PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
+ try {
+ Query query = pm.newQuery(Product.class, "category = pCategory");
+ query.declareParameters("String pCategory");
+ return query.execute(category);
+ }
+ finally {
+ pm.close();
+ }
+ }
+}
+
+ As the above DAO still follows the Dependency Injection pattern,
+ it still fits nicely into a Spring container, just like it would if
+ coded against Spring's JdoTemplate:
+
+ <beans>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="persistenceManagerFactory" ref="myPmf"/>
+ </bean>
+
+</beans>
+
+ The main issue with such DAOs is that they always get a new
+ PersistenceManager from the factory. To
+ still access a Spring-managed transactional
+ PersistenceManager, consider defining a
+ TransactionAwarePersistenceManagerFactoryProxy
+ (as included in Spring) in front of your target
+ PersistenceManagerFactory, passing the
+ proxy into your DAOs.
+
+ <beans>
+
+ <bean id="myPmfProxy"
+ class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
+ <property name="targetPersistenceManagerFactory" ref="myPmf"/>
+ </bean>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="persistenceManagerFactory" ref="myPmfProxy"/>
+ </bean>
+
+</beans>
+
+ Your data access code will then receive a transactional
+ PersistenceManager (if any) from the
+ PersistenceManagerFactory.getPersistenceManager()
+ method that it calls. The latter method call goes through the proxy,
+ which will first check for a current transactional
+ PersistenceManager before getting a new
+ one from the factory. close() calls on the
+ PersistenceManager will be ignored in
+ case of a transactional
+ PersistenceManager.
+
+ If your data access code will always run within an active
+ transaction (or at least within active transaction synchronization), it
+ is safe to omit the PersistenceManager.close()
+ call and thus the entire finally block, which you
+ might prefer to keep your DAO implementations concise:
+
+ public class ProductDaoImpl implements ProductDao {
+
+ private PersistenceManagerFactory persistenceManagerFactory;
+
+ public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
+ this.persistenceManagerFactory = pmf;
+ }
+
+ public Collection loadProductsByCategory(String category) {
+ PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
+ Query query = pm.newQuery(Product.class, "category = pCategory");
+ query.declareParameters("String pCategory");
+ return query.execute(category);
+ }
+}
+
+ With such DAOs that rely on active transactions, it is recommended
+ to enforce active transactions through turning
+ TransactionAwarePersistenceManagerFactoryProxy's
+ "allowCreate" flag off:
+
+ <beans>
+
+ <bean id="myPmfProxy"
+ class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
+ <property name="targetPersistenceManagerFactory" ref="myPmf"/>
+ <property name="allowCreate" value="false"/>
+ </bean>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="persistenceManagerFactory" ref="myPmfProxy"/>
+ </bean>
+
+</beans>
+
+ The main advantage of this DAO style is that it depends on JDO API
+ only; no import of any Spring class is required. This is of course
+ appealing from a non-invasiveness perspective, and might feel more
+ natural to JDO developers.
+
+ However, the DAO throws plain
+ JDOException (which is unchecked, so does
+ not have to be declared or caught), which means that callers can only
+ treat exceptions as generally fatal - unless they want to depend on
+ JDO's own exception structure. Catching specific causes such as an
+ optimistic locking failure is not possible without tying the caller to
+ the implementation strategy. This tradeoff might be acceptable to
+ applications that are strongly JDO-based and/or do not need any special
+ exception treatment.
+
+ In summary: DAOs can be implemented based on plain JDO API, while
+ still being able to participate in Spring-managed transactions. This
+ might in particular appeal to people already familiar with JDO, feeling
+ more natural to them. However, such DAOs will throw plain
+ JDOException; conversion to Spring's
+ DataAccessException would have to happen
+ explicitly (if desired).
+
+
+
+ Transaction management
+
+ To execute service operations within transactions, you can use
+ Spring's common declarative transaction facilities. For example:
+
+ <?xml version="1.0" encoding="UTF-8"?>
+<beans
+ xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/tx
+ http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
+ http://www.springframework.org/schema/aop
+ http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">
+ <property name="persistenceManagerFactory" ref="myPmf"/>
+ </bean>
+
+ <bean id="myProductService" class="product.ProductServiceImpl">
+ <property name="productDao" ref="myProductDao"/>
+ </bean>
+
+ <tx:advice id="txAdvice" transaction-manager="txManager">
+ <tx:attributes>
+ <tx:method name="increasePrice*" propagation="REQUIRED"/>
+ <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
+ <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
+ </tx:attributes>
+ </tx:advice>
+
+ <aop:config>
+ <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
+ <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
+ </aop:config>
+
+</beans>
+
+ Note that JDO requires an active transaction when modifying a
+ persistent object. There is no concept like a non-transactional flush in
+ JDO, in contrast to Hibernate. For this reason, the chosen JDO
+ implementation needs to be set up for a specific environment: in
+ particular, it needs to be explicitly set up for JTA synchronization, to
+ detect an active JTA transaction itself. This is not necessary for local
+ transactions as performed by Spring's
+ JdoTransactionManager, but it is necessary for
+ participating in JTA transactions (whether driven by Spring's
+ JtaTransactionManager or by EJB CMT / plain
+ JTA).
+
+ JdoTransactionManager is capable of
+ exposing a JDO transaction to JDBC access code that accesses the same
+ JDBC DataSource, provided that the
+ registered JdoDialect supports retrieval of the
+ underlying JDBC Connection. This is the
+ case for JDBC-based JDO 2.0 implementations by default.
+
+
+
+ JdoDialect
+
+ As an advanced feature, both JdoTemplate
+ and interfacename support a custom
+ JdoDialect, to be passed into the
+ "jdoDialect" bean property. In such a scenario, the DAOs won't receive a
+ PersistenceManagerFactory reference but
+ rather a full JdoTemplate instance instead (for
+ example, passed into JdoDaoSupport's
+ "jdoTemplate" property). A JdoDialect
+ implementation can enable some advanced features supported by Spring,
+ usually in a vendor-specific manner:
+
+
+
+ applying specific transaction semantics (such as custom
+ isolation level or transaction timeout)
+
+
+
+ retrieving the transactional JDBC
+ Connection (for exposure to
+ JDBC-based DAOs)
+
+
+
+ applying query timeouts (automatically calculated from
+ Spring-managed transaction timeout)
+
+
+
+ eagerly flushing a
+ PersistenceManager (to make
+ transactional changes visible to JDBC-based data access code)
+
+
+
+ advanced translation of JDOExceptions to
+ Spring DataAccessExceptions
+
+
+
+ See the JdoDialect Javadoc for more details
+ on its operations and how they are used within Spring's JDO
+ support.
@@ -1306,9 +1684,8 @@
}
The DAO above has no dependency on Spring and still fits nicely
- into a Spring application context, just like it would if coded against
- Spring's JpaTemplate. Moreover, the DAO takes
- advantage of annotations to require the injection of the default
+ into a Spring application context. Moreover, the DAO takes advantage of
+ annotations to require the injection of the default
EntityManagerFactory:
<beans>
@@ -1403,54 +1780,6 @@
a non-invasiveness perspective, and might feel more natural to JPA
developers.
-
-
- Exception Translation
-
- However, the DAO throws the plain
- PersistenceException exception class (which is
- unchecked, and so does not have to be declared or caught) but also
- IllegalArgumentException and
- IllegalStateException, which means that callers
- can only treat exceptions as generally fatal - unless they want to
- depend on JPA's own exception structure. Catching specific causes such
- as an optimistic locking failure is not possible without tying the
- caller to the implementation strategy. This tradeoff might be acceptable
- to applications that are strongly JPA-based and/or do not need any
- special exception treatment. However, Spring offers a solution allowing
- exception translation to be applied transparently through the
- @Repository annotation:
-
- @Repository
-public class ProductDaoImpl implements ProductDao {
-
- // class body here...
-
-}
-
- <beans>
-
- <!-- Exception translation bean post processor -->
- <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
-
- <bean id="myProductDao" class="product.ProductDaoImpl"/>
-
-</beans>
-
- The postprocessor will automatically look for all exception
- translators (implementations of the
- PersistenceExceptionTranslator interface)
- and advise all beans marked with the
- @Repository annotation so that the
- discovered translators can intercept and apply the appropriate
- translation on the thrown exceptions.
-
- In summary: DAOs can be implemented based on the plain Java
- Persistence API and annotations, while still being able to benefit from
- Spring-managed transactions, dependency injection, and transparent
- exception conversion (if desired) to Spring's custom exception
- hierarchies.
-
@@ -1550,333 +1879,14 @@ public class ProductDaoImpl implements ProductDao {
JpaDialect mechanism.
-
- JDO
-
- Spring supports the standard JDO 2.0/2.1 API as data access
- strategy, following the same style as the Hibernate support. The
- corresponding integration classes reside in the
- org.springframework.orm.jdo package.
-
-
- PersistenceManagerFactory
- setup
-
- Spring provides a
- LocalPersistenceManagerFactoryBean class that
- allows for defining a local JDO
- PersistenceManagerFactory within a Spring
- application context:
-
- <beans>
-
- <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
- <property name="configLocation" value="classpath:kodo.properties"/>
- </bean>
-
-</beans>
-
- Alternatively, a
- PersistenceManagerFactory can also be set
- up through direct instantiation of a
- PersistenceManagerFactory implementation
- class. A JDO PersistenceManagerFactory
- implementation class is supposed to follow the JavaBeans pattern, just
- like a JDBC DataSource implementation
- class, which is a natural fit for a Spring bean definition. This setup
- style usually supports a Spring-defined JDBC
- DataSource, passed into the
- "connectionFactory" property. For example, for the open source JDO
- implementation JPOX ():
-
- <beans>
-
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${jdbc.driverClassName}"/>
- <property name="url" value="${jdbc.url}"/>
- <property name="username" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
- </bean>
-
- <bean id="myPmf" class="org.jpox.PersistenceManagerFactoryImpl" destroy-method="close">
- <property name="connectionFactory" ref="dataSource"/>
- <property name="nontransactionalRead" value="true"/>
- </bean>
-
-</beans>
-
- A JDO PersistenceManagerFactory can
- also be set up in the JNDI environment of a J2EE application server,
- usually through the JCA connector provided by the particular JDO
- implementation. Spring's standard
- JndiObjectFactoryBean can be used to retrieve and
- expose such a PersistenceManagerFactory.
- However, outside an EJB context, there is often no compelling benefit in
- holding the PersistenceManagerFactory in
- JNDI: only choose such setup for a good reason. See "container resources
- versus local resources" in the Hibernate section for a discussion; the
- arguments there apply to JDO as well.
-
-
-
- Implementing DAOs based on the plain JDO API
-
- DAOs can also be written against plain JDO API, without any Spring
- dependencies, directly using an injected
- PersistenceManagerFactory. A
- corresponding DAO implementation looks like as follows:
-
- public class ProductDaoImpl implements ProductDao {
-
- private PersistenceManagerFactory persistenceManagerFactory;
-
- public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
- this.persistenceManagerFactory = pmf;
- }
-
- public Collection loadProductsByCategory(String category) {
- PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
- try {
- Query query = pm.newQuery(Product.class, "category = pCategory");
- query.declareParameters("String pCategory");
- return query.execute(category);
- }
- finally {
- pm.close();
- }
- }
-}
-
- As the above DAO still follows the Dependency Injection pattern,
- it still fits nicely into a Spring container, just like it would if
- coded against Spring's JdoTemplate:
-
- <beans>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="persistenceManagerFactory" ref="myPmf"/>
- </bean>
-
-</beans>
-
- The main issue with such DAOs is that they always get a new
- PersistenceManager from the factory. To
- still access a Spring-managed transactional
- PersistenceManager, consider defining a
- TransactionAwarePersistenceManagerFactoryProxy
- (as included in Spring) in front of your target
- PersistenceManagerFactory, passing the
- proxy into your DAOs.
-
- <beans>
-
- <bean id="myPmfProxy"
- class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
- <property name="targetPersistenceManagerFactory" ref="myPmf"/>
- </bean>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="persistenceManagerFactory" ref="myPmfProxy"/>
- </bean>
-
-</beans>
-
- Your data access code will then receive a transactional
- PersistenceManager (if any) from the
- PersistenceManagerFactory.getPersistenceManager()
- method that it calls. The latter method call goes through the proxy,
- which will first check for a current transactional
- PersistenceManager before getting a new
- one from the factory. close() calls on the
- PersistenceManager will be ignored in
- case of a transactional
- PersistenceManager.
-
- If your data access code will always run within an active
- transaction (or at least within active transaction synchronization), it
- is safe to omit the PersistenceManager.close()
- call and thus the entire finally block, which you
- might prefer to keep your DAO implementations concise:
-
- public class ProductDaoImpl implements ProductDao {
-
- private PersistenceManagerFactory persistenceManagerFactory;
-
- public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
- this.persistenceManagerFactory = pmf;
- }
-
- public Collection loadProductsByCategory(String category) {
- PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
- Query query = pm.newQuery(Product.class, "category = pCategory");
- query.declareParameters("String pCategory");
- return query.execute(category);
- }
-}
-
- With such DAOs that rely on active transactions, it is recommended
- to enforce active transactions through turning
- TransactionAwarePersistenceManagerFactoryProxy's
- "allowCreate" flag off:
-
- <beans>
-
- <bean id="myPmfProxy"
- class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
- <property name="targetPersistenceManagerFactory" ref="myPmf"/>
- <property name="allowCreate" value="false"/>
- </bean>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="persistenceManagerFactory" ref="myPmfProxy"/>
- </bean>
-
-</beans>
-
- The main advantage of this DAO style is that it depends on JDO API
- only; no import of any Spring class is required. This is of course
- appealing from a non-invasiveness perspective, and might feel more
- natural to JDO developers.
-
- However, the DAO throws plain
- JDOException (which is unchecked, so does
- not have to be declared or caught), which means that callers can only
- treat exceptions as generally fatal - unless they want to depend on
- JDO's own exception structure. Catching specific causes such as an
- optimistic locking failure is not possible without tying the caller to
- the implementation strategy. This tradeoff might be acceptable to
- applications that are strongly JDO-based and/or do not need any special
- exception treatment.
-
- In summary: DAOs can be implemented based on plain JDO API, while
- still being able to participate in Spring-managed transactions. This
- might in particular appeal to people already familiar with JDO, feeling
- more natural to them. However, such DAOs will throw plain
- JDOException; conversion to Spring's
- DataAccessException would have to happen
- explicitly (if desired).
-
-
-
- Transaction management
-
- To execute service operations within transactions, you can use
- Spring's common declarative transaction facilities. For example:
-
- <?xml version="1.0" encoding="UTF-8"?>
-<beans
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">
- <property name="persistenceManagerFactory" ref="myPmf"/>
- </bean>
-
- <bean id="myProductService" class="product.ProductServiceImpl">
- <property name="productDao" ref="myProductDao"/>
- </bean>
-
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <tx:attributes>
- <tx:method name="increasePrice*" propagation="REQUIRED"/>
- <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
- <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
- </tx:attributes>
- </tx:advice>
-
- <aop:config>
- <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
- <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
- </aop:config>
-
-</beans>
-
- Note that JDO requires an active transaction when modifying a
- persistent object. There is no concept like a non-transactional flush in
- JDO, in contrast to Hibernate. For this reason, the chosen JDO
- implementation needs to be set up for a specific environment: in
- particular, it needs to be explicitly set up for JTA synchronization, to
- detect an active JTA transaction itself. This is not necessary for local
- transactions as performed by Spring's
- JdoTransactionManager, but it is necessary for
- participating in JTA transactions (whether driven by Spring's
- JtaTransactionManager or by EJB CMT / plain
- JTA).
-
- JdoTransactionManager is capable of
- exposing a JDO transaction to JDBC access code that accesses the same
- JDBC DataSource, provided that the
- registered JdoDialect supports retrieval of the
- underlying JDBC Connection. This is the
- case for JDBC-based JDO 2.0 implementations by default.
-
-
-
- JdoDialect
-
- As an advanced feature, both JdoTemplate
- and interfacename support a custom
- JdoDialect, to be passed into the
- "jdoDialect" bean property. In such a scenario, the DAOs won't receive a
- PersistenceManagerFactory reference but
- rather a full JdoTemplate instance instead (for
- example, passed into JdoDaoSupport's
- "jdoTemplate" property). A JdoDialect
- implementation can enable some advanced features supported by Spring,
- usually in a vendor-specific manner:
-
-
-
- applying specific transaction semantics (such as custom
- isolation level or transaction timeout)
-
-
-
- retrieving the transactional JDBC
- Connection (for exposure to
- JDBC-based DAOs)
-
-
-
- applying query timeouts (automatically calculated from
- Spring-managed transaction timeout)
-
-
-
- eagerly flushing a
- PersistenceManager (to make
- transactional changes visible to JDBC-based data access code)
-
-
-
- advanced translation of JDOExceptions to
- Spring DataAccessExceptions
-
-
-
- See the JdoDialect Javadoc for more details
- on its operations and how they are used within Spring's JDO
- support.
-
-
-
iBATIS SQL Maps
- The iBATIS support in the Spring Framework much resembles the JDBC /
- Hibernate support in that it supports the same template style programming
- and just as with JDBC or Hibernate, the iBATIS support works with Spring's
- exception hierarchy and let's you enjoy the all IoC features Spring
- has.
+ The iBATIS support in the Spring Framework much resembles the JDBC
+ support in that it supports the same template style programming and just
+ as with JDBC or other ORM technologies, the iBATIS support works with
+ Spring's exception hierarchy and let's you enjoy the all IoC features
+ Spring has.
Transaction management can be handled through Spring's standard
facilities. There are no special transaction strategies for iBATIS, as
@@ -1887,11 +1897,9 @@ public class ProductDaoImpl implements ProductDao {
sufficient.
- Spring does actually support both iBatis 1.x and 2.x. However,
- only support for iBatis 2.x is actually shipped with the core Spring
- distribution. The iBatis 1.x support classes were moved to the Spring
- Modules project as of Spring 2.0, and you are directed there for
- documentation.
+ Spring supports iBatis 2.x. The iBatis 1.x support classes were
+ moved to the Spring Modules project as of Spring 2.0, and you are
+ directed there for documentation.
@@ -1955,6 +1963,71 @@ public class ProductDaoImpl implements ProductDao {
</beans>
+
+ Using SqlMapClientTemplate and
+ SqlMapClientDaoSupport
+
+ The SqlMapClientDaoSupport class offers a
+ supporting class similar to the SqlMapDaoSupport.
+ We extend it to implement our DAO:
+
+ public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
+
+ public Account getAccount(String email) throws DataAccessException {
+ return (Account) getSqlMapClientTemplate().queryForObject("getAccountByEmail", email);
+ }
+
+ public void insertAccount(Account account) throws DataAccessException {
+ getSqlMapClientTemplate().update("insertAccount", account);
+ }
+}
+
+ In the DAO, we use the pre-configured
+ SqlMapClientTemplate to execute the queries,
+ after setting up the SqlMapAccountDao in the
+ application context and wiring it with our
+ SqlMapClient instance:
+
+ <beans>
+
+ <bean id="accountDao" class="example.SqlMapAccountDao">
+ <property name="sqlMapClient" ref="sqlMapClient"/>
+ </bean>
+
+</beans>
+
+ Note that a SqlMapTemplate instance could
+ also be created manually, passing in the SqlMapClient
+ as constructor argument. The SqlMapClientDaoSupport
+ base class simply pre-initializes a
+ SqlMapClientTemplate instance for us.
+
+ The SqlMapClientTemplate also offers a
+ generic execute method, taking a custom
+ SqlMapClientCallback implementation as argument. This
+ can, for example, be used for batching:
+
+ public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
+
+ public void insertAccount(Account account) throws DataAccessException {
+ getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
+ public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
+ executor.startBatch();
+ executor.update("insertAccount", account);
+ executor.update("insertAddress", account.getAddress());
+ executor.executeBatch();
+ }
+ });
+ }
+}
+
+ In general, any combination of operations offered by the native
+ SqlMapExecutor API can be used in such a callback.
+ Any SQLException thrown will automatically get
+ converted to Spring's generic DataAccessException
+ hierarchy.
+
+
Implementing DAOs based on plain iBATIS API