diff --git a/spring-framework-reference/src/classic-spring.xml b/spring-framework-reference/src/classic-spring.xml
new file mode 100644
index 00000000000..27f41258bdd
--- /dev/null
+++ b/spring-framework-reference/src/classic-spring.xml
@@ -0,0 +1,430 @@
+
+
+
+ Classic Spring Usage
+
+ This appendix discusses some classic Spring usage patterns as a
+ reference for developers maintaining legacy Spring applications. These usage
+ patterns no longer reflect the recommended way of using these features and
+ the current recommended usage is covered in the respective sections of the
+ reference manual.
+
+
+ Classic ORM usage
+
+ 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.
+
+
+
+ Hibernate
+
+ For the currently recommended usage patterns for Hibernate see
+
+
+
+ The HibernateTemplate
+
+ The basic programming model for templating looks as follows, for
+ methods that can be part of any custom data access object or business
+ service. There are no restrictions on the implementation of the
+ surrounding object at all, it just needs to provide a Hibernate
+ SessionFactory. It can get the latter
+ from anywhere, but preferably as bean reference from a Spring IoC
+ container - via a simple
+ setSessionFactory(..) bean property setter.
+ The following snippets show a DAO definition in a Spring container,
+ referencing the above defined
+ SessionFactory, and an example for a
+ DAO method implementation.
+
+ <beans>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="sessionFactory" ref="mySessionFactory"/>
+ </bean>
+
+</beans>
+
+ public class ProductDaoImpl implements ProductDao {
+
+ private HibernateTemplate hibernateTemplate;
+
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.hibernateTemplate = new HibernateTemplate(sessionFactory);
+ }
+
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
+ }
+}
+
+ The HibernateTemplate class provides many
+ methods that mirror the methods exposed on the Hibernate
+ Session interface, in addition to a
+ number of convenience methods such as the one shown above. If you need
+ access to the Session to invoke methods
+ that are not exposed on the HibernateTemplate,
+ you can always drop down to a callback-based approach like so.
+
+ public class ProductDaoImpl implements ProductDao {
+
+ private HibernateTemplate hibernateTemplate;
+
+ public void setSessionFactory(SessionFactory sessionFactory) {
+ this.hibernateTemplate = new HibernateTemplate(sessionFactory);
+ }
+
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return this.hibernateTemplate.execute(new HibernateCallback() {
+
+ public Object doInHibernate(Session session) {
+ Criteria criteria = session.createCriteria(Product.class);
+ criteria.add(Expression.eq("category", category));
+ criteria.setMaxResults(6);
+ return criteria.list();
+ }
+ };
+ }
+}
+
+ A callback implementation effectively can be used for any
+ Hibernate data access. HibernateTemplate will
+ ensure that Session instances 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 like a single find, load, saveOrUpdate,
+ or delete call, HibernateTemplate offers
+ alternative convenience methods that can replace such one line
+ callback implementations. Furthermore, Spring provides a convenient
+ HibernateDaoSupport base class that provides a
+ setSessionFactory(..) method for receiving a
+ SessionFactory, and
+ getSessionFactory() and
+ getHibernateTemplate()for use by subclasses.
+ In combination, this allows for very simple DAO implementations for
+ typical requirements:
+
+ public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
+
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ return this.getHibernateTemplate().find(
+ "from test.Product product where product.category=?", category);
+ }
+}
+
+
+
+ Implementing Spring-based DAOs without callbacks
+
+ As alternative to using Spring's
+ HibernateTemplate to implement DAOs, data
+ access code can also be written in a more traditional fashion, without
+ wrapping the Hibernate access code in a callback, while still
+ respecting and participating in Spring's generic
+ DataAccessException hierarchy. The
+ HibernateDaoSupport base class offers methods
+ to access the current transactional
+ Session and to convert exceptions in
+ such a scenario; similar methods are also available as static helpers
+ on the SessionFactoryUtils class. Note that
+ such code will usually pass 'false' as the value of
+ the getSession(..) methods
+ 'allowCreate' argument, to enforce running within a
+ transaction (which avoids the need to close the returned
+ Session, as its lifecycle is managed by
+ the transaction).
+
+ public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
+
+ public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
+ Session session = getSession(false);
+ try {
+ Query query = session.createQuery("from test.Product product where product.category=?");
+ query.setString(0, category);
+ List result = query.list();
+ if (result == null) {
+ throw new MyException("No search results.");
+ }
+ return result;
+ }
+ catch (HibernateException ex) {
+ throw convertHibernateAccessException(ex);
+ }
+ }
+}
+
+ The advantage of such direct Hibernate access code is that it
+ allows any checked application exception to be
+ thrown within the data access code; contrast this to the
+ HibernateTemplate class which is restricted to
+ throwing only unchecked exceptions within the callback. Note that you
+ can often defer the corresponding checks and the throwing of
+ application exceptions to after the callback, which still allows
+ working with HibernateTemplate. In general, the
+ HibernateTemplate class' convenience methods
+ are simpler and more convenient for many scenarios.
+
+
+
+
+ JPA
+
+ For the currently recommended usage patterns for JPA see
+
+
+ JpaTemplate and
+ JpaDaoSupport
+
+ Each JPA-based DAO will then receive a
+ EntityManagerFactory via dependency
+ injection. Such a DAO can be coded against plain JPA and work with the
+ given EntityManagerFactory or through
+ Spring's JpaTemplate:
+
+ <beans>
+
+ <bean id="myProductDao" class="product.ProductDaoImpl">
+ <property name="entityManagerFactory" ref="myEmf"/>
+ </bean>
+
+</beans>
+
+ public class JpaProductDao implements ProductDao {
+
+ private JpaTemplate jpaTemplate;
+
+ public void setEntityManagerFactory(EntityManagerFactory emf) {
+ this.jpaTemplate = new JpaTemplate(emf);
+ }
+
+ public Collection loadProductsByCategory(final String category) throws DataAccessException {
+ return (Collection) this.jpaTemplate.execute(new JpaCallback() {
+ public Object doInJpa(EntityManager em) throws PersistenceException {
+ Query query = em.createQuery("from Product as p where p.category = :category");
+ query.setParameter("category", category);
+ List result = query.getResultList();
+ // do some further processing with the result list
+ return result;
+ }
+ });
+ }
+}
+
+ The JpaCallback implementation
+ allows any type of JPA data access. The
+ JpaTemplate will ensure that
+ EntityManagers are properly opened and
+ closed and automatically participate in transactions. Moreover, the
+ JpaTemplate properly handles exceptions, making
+ sure resources are cleaned up and the appropriate transactions rolled
+ back. The template instances are thread-safe and reusable and they can
+ be kept as instance variable of the enclosing class. Note that
+ JpaTemplate offers single-step actions such as
+ find, load, merge, etc along with alternative convenience methods that
+ can replace one line callback implementations.
+
+ Furthermore, Spring provides a convenient
+ JpaDaoSupport base class that provides the
+ get/setEntityManagerFactory and
+ getJpaTemplate() to be used by
+ subclasses:
+
+ public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
+
+ public Collection loadProductsByCategory(String category) throws DataAccessException {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("category", category);
+ return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
+ }
+}
+
+ Besides working with Spring's
+ JpaTemplate, one can also code Spring-based
+ DAOs against the JPA, doing one's own explicit
+ EntityManager handling. As also
+ elaborated in the corresponding Hibernate section, the main advantage
+ of this approach is that your data access code is able to throw
+ checked exceptions. JpaDaoSupport offers a
+ variety of support methods for this scenario, for retrieving and
+ releasing a transaction EntityManager,
+ as well as for converting exceptions.
+
+ JpaTemplate mainly exists as a sibling of JdoTemplate
+ and HibernateTemplate, offering the same style for people used to
+ 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.
+
+
+
+
+
+ Classic Spring MVC
+
+ ...
+
+
diff --git a/spring-framework-reference/src/orm.xml b/spring-framework-reference/src/orm.xml
index a8525fa5723..4a55059f74c 100644
--- a/spring-framework-reference/src/orm.xml
+++ b/spring-framework-reference/src/orm.xml
@@ -238,150 +238,6 @@
However, that is typically not common outside of an EJB context.
-
- The HibernateTemplate
-
- The basic programming model for templating looks as follows, for
- methods that can be part of any custom data access object or business
- service. There are no restrictions on the implementation of the
- surrounding object at all, it just needs to provide a Hibernate
- SessionFactory. It can get the latter
- from anywhere, but preferably as bean reference from a Spring IoC
- container - via a simple setSessionFactory(..)
- bean property setter. The following snippets show a DAO definition in a
- Spring container, referencing the above defined
- SessionFactory, and an example for a DAO
- method implementation.
-
- <beans>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="sessionFactory" ref="mySessionFactory"/>
- </bean>
-
-</beans>
-
- public class ProductDaoImpl implements ProductDao {
-
- private HibernateTemplate hibernateTemplate;
-
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.hibernateTemplate = new HibernateTemplate(sessionFactory);
- }
-
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return this.hibernateTemplate.find("from test.Product product where product.category=?", category);
- }
-}
-
- The HibernateTemplate class provides many
- methods that mirror the methods exposed on the Hibernate
- Session interface, in addition to a
- number of convenience methods such as the one shown above. If you need
- access to the Session to invoke methods
- that are not exposed on the HibernateTemplate,
- you can always drop down to a callback-based approach like so.
-
- public class ProductDaoImpl implements ProductDao {
-
- private HibernateTemplate hibernateTemplate;
-
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.hibernateTemplate = new HibernateTemplate(sessionFactory);
- }
-
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return this.hibernateTemplate.execute(new HibernateCallback() {
-
- public Object doInHibernate(Session session) {
- Criteria criteria = session.createCriteria(Product.class);
- criteria.add(Expression.eq("category", category));
- criteria.setMaxResults(6);
- return criteria.list();
- }
- };
- }
-}
-
- A callback implementation effectively can be used for any
- Hibernate data access. HibernateTemplate will
- ensure that Session instances 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 like a single find, load, saveOrUpdate, or
- delete call, HibernateTemplate offers alternative
- convenience methods that can replace such one line callback
- implementations. Furthermore, Spring provides a convenient
- HibernateDaoSupport base class that provides a
- setSessionFactory(..) method for receiving a
- SessionFactory, and
- getSessionFactory() and
- getHibernateTemplate()for use by subclasses. In
- combination, this allows for very simple DAO implementations for typical
- requirements:
-
- public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
-
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- return this.getHibernateTemplate().find(
- "from test.Product product where product.category=?", category);
- }
-}
-
-
-
- Implementing Spring-based DAOs without callbacks
-
- As alternative to using Spring's
- HibernateTemplate to implement DAOs, data access
- code can also be written in a more traditional fashion, without wrapping
- the Hibernate access code in a callback, while still respecting and
- participating in Spring's generic
- DataAccessException hierarchy. The
- HibernateDaoSupport base class offers methods to
- access the current transactional Session
- and to convert exceptions in such a scenario; similar methods are also
- available as static helpers on the
- SessionFactoryUtils class. Note that such code
- will usually pass 'false' as the value of the
- getSession(..) methods
- 'allowCreate' argument, to enforce running within a
- transaction (which avoids the need to close the returned
- Session, as its lifecycle is managed by
- the transaction).
-
- public class HibernateProductDao extends HibernateDaoSupport implements ProductDao {
-
- public Collection loadProductsByCategory(String category) throws DataAccessException, MyException {
- Session session = getSession(false);
- try {
- Query query = session.createQuery("from test.Product product where product.category=?");
- query.setString(0, category);
- List result = query.list();
- if (result == null) {
- throw new MyException("No search results.");
- }
- return result;
- }
- catch (HibernateException ex) {
- throw convertHibernateAccessException(ex);
- }
- }
-}
-
- The advantage of such direct Hibernate access code is that it
- allows any checked application exception to be
- thrown within the data access code; contrast this to the
- HibernateTemplate class which is restricted to
- throwing only unchecked exceptions within the callback. Note that you
- can often defer the corresponding checks and the throwing of application
- exceptions to after the callback, which still allows working with
- HibernateTemplate. In general, the
- HibernateTemplate class' convenience methods are
- simpler and more convenient for many scenarios.
-
-
Implementing DAOs based on plain Hibernate 3 API
@@ -950,608 +806,6 @@
-
- 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.
-
-
-
- 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.
-
-
-
- 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.
-
- Transaction management can be handled through Spring's standard
- facilities. There are no special transaction strategies for iBATIS, as
- there is no special transactional resource involved other than a JDBC
- Connection. Hence, Spring's standard JDBC
- DataSourceTransactionManager or
- JtaTransactionManager are perfectly
- 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.
-
-
-
- Setting up the SqlMapClient
-
- If we want to map the previous Account class with iBATIS 2.x we
- need to create the following SQL map
- 'Account.xml':
-
- <sqlMap namespace="Account">
-
- <resultMap id="result" class="examples.Account">
- <result property="name" column="NAME" columnIndex="1"/>
- <result property="email" column="EMAIL" columnIndex="2"/>
- </resultMap>
-
- <select id="getAccountByEmail" resultMap="result">
- select ACCOUNT.NAME, ACCOUNT.EMAIL
- from ACCOUNT
- where ACCOUNT.EMAIL = #value#
- </select>
-
- <insert id="insertAccount">
- insert into ACCOUNT (NAME, EMAIL) values (#name#, #email#)
- </insert>
-
-</sqlMap>
-
- The configuration file for iBATIS 2 looks like this:
-
- <sqlMapConfig>
-
- <sqlMap resource="example/Account.xml"/>
-
-</sqlMapConfig>
-
- Remember that iBATIS loads resources from the class path, so be
- sure to add the 'Account.xml' file to the class
- path.
-
- We can use the SqlMapClientFactoryBean in
- the Spring container. Note that with iBATIS SQL Maps 2.x, the JDBC
- DataSource is usually specified on the
- SqlMapClientFactoryBean, which enables lazy
- loading.
-
- <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="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
- <property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
- <property name="dataSource" ref="dataSource"/>
- </bean>
-
-</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
-
- DAOs can also be written against plain iBATIS API, without any
- Spring dependencies, directly using an injected
- SqlMapClient. A corresponding DAO implementation
- looks like as follows:
-
- public class SqlMapAccountDao implements AccountDao {
-
- private SqlMapClient sqlMapClient;
-
- public void setSqlMapClient(SqlMapClient sqlMapClient) {
- this.sqlMapClient = sqlMapClient;
- }
-
- public Account getAccount(String email) {
- try {
- return (Account) this.sqlMapClient.queryForObject("getAccountByEmail", email);
- }
- catch (SQLException ex) {
- throw new MyDaoException(ex);
- }
- }
-
- public void insertAccount(Account account) throws DataAccessException {
- try {
- this.sqlMapClient.update("insertAccount", account);
- }
- catch (SQLException ex) {
- throw new MyDaoException(ex);
- }
- }
-}
-
- In such a scenario, the SQLException thrown by
- the iBATIS API needs to be handled in a custom fashion: usually,
- wrapping it in your own application-specific DAO exception. Wiring in
- the application context would still look like before, due to the fact
- that the plain iBATIS-based DAO still follows the Dependency Injection
- pattern:
-
- <beans>
-
- <bean id="accountDao" class="example.SqlMapAccountDao">
- <property name="sqlMapClient" ref="sqlMapClient"/>
- </bean>
-
-</beans>
-
-
-
JPA
@@ -2000,93 +1254,6 @@
-
- JpaTemplate and
- JpaDaoSupport
-
- Each JPA-based DAO will then receive a
- EntityManagerFactory via dependency
- injection. Such a DAO can be coded against plain JPA and work with the
- given EntityManagerFactory or through
- Spring's JpaTemplate:
-
- <beans>
-
- <bean id="myProductDao" class="product.ProductDaoImpl">
- <property name="entityManagerFactory" ref="myEmf"/>
- </bean>
-
-</beans>
-
- public class JpaProductDao implements ProductDao {
-
- private JpaTemplate jpaTemplate;
-
- public void setEntityManagerFactory(EntityManagerFactory emf) {
- this.jpaTemplate = new JpaTemplate(emf);
- }
-
- public Collection loadProductsByCategory(final String category) throws DataAccessException {
- return (Collection) this.jpaTemplate.execute(new JpaCallback() {
- public Object doInJpa(EntityManager em) throws PersistenceException {
- Query query = em.createQuery("from Product as p where p.category = :category");
- query.setParameter("category", category);
- List result = query.getResultList();
- // do some further processing with the result list
- return result;
- }
- });
- }
-}
-
- The JpaCallback implementation
- allows any type of JPA data access. The
- JpaTemplate will ensure that
- EntityManagers are properly opened and
- closed and automatically participate in transactions. Moreover, the
- JpaTemplate properly handles exceptions, making
- sure resources are cleaned up and the appropriate transactions rolled
- back. The template instances are thread-safe and reusable and they can
- be kept as instance variable of the enclosing class. Note that
- JpaTemplate offers single-step actions such as
- find, load, merge, etc along with alternative convenience methods that
- can replace one line callback implementations.
-
- Furthermore, Spring provides a convenient
- JpaDaoSupport base class that provides the
- get/setEntityManagerFactory and
- getJpaTemplate() to be used by
- subclasses:
-
- public class ProductDaoImpl extends JpaDaoSupport implements ProductDao {
-
- public Collection loadProductsByCategory(String category) throws DataAccessException {
- Map<String, String> params = new HashMap<String, String>();
- params.put("category", category);
- return getJpaTemplate().findByNamedParams("from Product as p where p.category = :category", params);
- }
-}
-
- Besides working with Spring's JpaTemplate,
- one can also code Spring-based DAOs against the JPA, doing one's own
- explicit EntityManager handling. As also
- elaborated in the corresponding Hibernate section, the main advantage of
- this approach is that your data access code is able to throw checked
- exceptions. JpaDaoSupport offers a variety of
- support methods for this scenario, for retrieving and releasing a
- transaction EntityManager, as well as for
- converting exceptions.
-
- JpaTemplate mainly exists as a sibling of JdoTemplate
- and HibernateTemplate, offering the same style for people used to it.
- For newly started projects, consider adopting the native JPA style of
- coding data access objects instead, based on a "shared EntityManager"
- reference obtained through the JPA
- @PersistenceContext annotation (using Spring's
- PersistenceAnnotationBeanPostProcessor; see below
- for details.)
-
-
Implementing DAOs based on plain JPA
@@ -2286,6 +1453,50 @@ public class ProductDaoImpl implements ProductDao {
+
+ JpaDialect
+
+ As an advanced feature JpaTemplate,
+ JpaTransactionManager and subclasses of
+ AbstractEntityManagerFactoryBean support a custom
+ JpaDialect, to be passed into the
+ "jpaDialect" bean property. In such a scenario, the DAOs won't receive an
+ EntityManagerFactory reference but rather a
+ full JpaTemplate instance instead (for example,
+ passed into JpaDaoSupport's "jpaTemplate"
+ property). A JpaDialect 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)
+
+
+
+ advanced translation of PersistenceExceptions
+ to Spring DataAccessExceptions
+
+
+
+ This is particularly valuable for special transaction semantics and
+ for advanced translation of exception. Note that the default
+ implementation used (DefaultJpaDialect) doesn't
+ provide any special capabilities and if the above features are required,
+ the appropriate dialect has to be specified.
+
+ See the JpaDialect Javadoc for more
+ details of its operations and how they are used within Spring's JPA
+ support.
+
+
Transaction Management
@@ -2339,47 +1550,460 @@ public class ProductDaoImpl implements ProductDao {
JpaDialect mechanism.
-
- JpaDialect
+
+ JDO
- As an advanced feature JpaTemplate,
- JpaTransactionManager and subclasses of
- AbstractEntityManagerFactoryBean support a custom
- JpaDialect, to be passed into the
- "jpaDialect" bean property. In such a scenario, the DAOs won't receive an
- EntityManagerFactory reference but rather a
- full JpaTemplate instance instead (for example,
- passed into JpaDaoSupport's "jpaTemplate"
- property). A JpaDialect implementation can
- enable some advanced features supported by Spring, usually in a
- vendor-specific manner:
+ 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.
-
-
- applying specific transaction semantics (such as custom
- isolation level or transaction timeout)
-
+
+ PersistenceManagerFactory
+ setup
-
- retrieving the transactional JDBC
- Connection (for exposure to JDBC-based
- DAOs)
-
+ Spring provides a
+ LocalPersistenceManagerFactoryBean class that
+ allows for defining a local JDO
+ PersistenceManagerFactory within a Spring
+ application context:
-
- advanced translation of PersistenceExceptions
- to Spring DataAccessExceptions
-
-
+ <beans>
- This is particularly valuable for special transaction semantics and
- for advanced translation of exception. Note that the default
- implementation used (DefaultJpaDialect) doesn't
- provide any special capabilities and if the above features are required,
- the appropriate dialect has to be specified.
+ <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
+ <property name="configLocation" value="classpath:kodo.properties"/>
+ </bean>
- See the JpaDialect Javadoc for more
- details of its operations and how they are used within Spring's JPA
- support.
+</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.
+
+ Transaction management can be handled through Spring's standard
+ facilities. There are no special transaction strategies for iBATIS, as
+ there is no special transactional resource involved other than a JDBC
+ Connection. Hence, Spring's standard JDBC
+ DataSourceTransactionManager or
+ JtaTransactionManager are perfectly
+ 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.
+
+
+
+ Setting up the SqlMapClient
+
+ If we want to map the previous Account class with iBATIS 2.x we
+ need to create the following SQL map
+ 'Account.xml':
+
+ <sqlMap namespace="Account">
+
+ <resultMap id="result" class="examples.Account">
+ <result property="name" column="NAME" columnIndex="1"/>
+ <result property="email" column="EMAIL" columnIndex="2"/>
+ </resultMap>
+
+ <select id="getAccountByEmail" resultMap="result">
+ select ACCOUNT.NAME, ACCOUNT.EMAIL
+ from ACCOUNT
+ where ACCOUNT.EMAIL = #value#
+ </select>
+
+ <insert id="insertAccount">
+ insert into ACCOUNT (NAME, EMAIL) values (#name#, #email#)
+ </insert>
+
+</sqlMap>
+
+ The configuration file for iBATIS 2 looks like this:
+
+ <sqlMapConfig>
+
+ <sqlMap resource="example/Account.xml"/>
+
+</sqlMapConfig>
+
+ Remember that iBATIS loads resources from the class path, so be
+ sure to add the 'Account.xml' file to the class
+ path.
+
+ We can use the SqlMapClientFactoryBean in
+ the Spring container. Note that with iBATIS SQL Maps 2.x, the JDBC
+ DataSource is usually specified on the
+ SqlMapClientFactoryBean, which enables lazy
+ loading.
+
+ <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="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
+ <property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
+ <property name="dataSource" ref="dataSource"/>
+ </bean>
+
+</beans>
+
+
+
+ Implementing DAOs based on plain iBATIS API
+
+ DAOs can also be written against plain iBATIS API, without any
+ Spring dependencies, directly using an injected
+ SqlMapClient. A corresponding DAO implementation
+ looks like as follows:
+
+ public class SqlMapAccountDao implements AccountDao {
+
+ private SqlMapClient sqlMapClient;
+
+ public void setSqlMapClient(SqlMapClient sqlMapClient) {
+ this.sqlMapClient = sqlMapClient;
+ }
+
+ public Account getAccount(String email) {
+ try {
+ return (Account) this.sqlMapClient.queryForObject("getAccountByEmail", email);
+ }
+ catch (SQLException ex) {
+ throw new MyDaoException(ex);
+ }
+ }
+
+ public void insertAccount(Account account) throws DataAccessException {
+ try {
+ this.sqlMapClient.update("insertAccount", account);
+ }
+ catch (SQLException ex) {
+ throw new MyDaoException(ex);
+ }
+ }
+}
+
+ In such a scenario, the SQLException thrown by
+ the iBATIS API needs to be handled in a custom fashion: usually,
+ wrapping it in your own application-specific DAO exception. Wiring in
+ the application context would still look like before, due to the fact
+ that the plain iBATIS-based DAO still follows the Dependency Injection
+ pattern:
+
+ <beans>
+
+ <bean id="accountDao" class="example.SqlMapAccountDao">
+ <property name="sqlMapClient" ref="sqlMapClient"/>
+ </bean>
+
+</beans>
+
diff --git a/spring-framework-reference/src/spring-framework-reference.xml b/spring-framework-reference/src/spring-framework-reference.xml
index f9c3e49ea7e..9b18161341a 100644
--- a/spring-framework-reference/src/spring-framework-reference.xml
+++ b/spring-framework-reference/src/spring-framework-reference.xml
@@ -330,6 +330,7 @@
+