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 + +
+ <classname>JdoTemplate</classname> and + <classname>JdoDaoSupport</classname> + + 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 - -
- <classname>JdoTemplate</classname> and - <classname>JdoDaoSupport</classname> - - 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 <classname>SqlMapClientTemplate</classname> and - <classname>SqlMapClientDaoSupport</classname> - - 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. -
-
<interfacename>SessionFactory</interfacename> 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. + +
+ <interfacename>PersistenceManagerFactory</interfacename> + 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. +
+ +
+ <interfacename>JdoDialect</interfacename> + + 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. - -
- <interfacename>PersistenceManagerFactory</interfacename> - 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. -
- -
- <interfacename>JdoDialect</interfacename> - - 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 <classname>SqlMapClientTemplate</classname> and + <classname>SqlMapClientDaoSupport</classname> + + 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