Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1236 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
3 changed files with 1419 additions and 1364 deletions
@ -0,0 +1,430 @@
@@ -0,0 +1,430 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
||||
<appendix id="classic-spring"> |
||||
<title>Classic Spring Usage</title> |
||||
|
||||
<para>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.</para> |
||||
|
||||
<section id="classic-spring-orm"> |
||||
<title>Classic ORM usage</title> |
||||
|
||||
<para>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 <xref linkend="orm" /> chapter. |
||||
</para> |
||||
|
||||
<section id="classic-spring-hibernate"> |
||||
<title>Hibernate</title> |
||||
|
||||
<para>For the currently recommended usage patterns for Hibernate see |
||||
<xref linkend="orm-hibernate" /></para> |
||||
|
||||
<section id="orm-hibernate-template"> |
||||
<title>The <classname>HibernateTemplate</classname></title> |
||||
|
||||
<para>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 |
||||
<interfacename>SessionFactory</interfacename>. It can get the latter |
||||
from anywhere, but preferably as bean reference from a Spring IoC |
||||
container - via a simple |
||||
<methodname>setSessionFactory(..)</methodname> bean property setter. |
||||
The following snippets show a DAO definition in a Spring container, |
||||
referencing the above defined |
||||
<interfacename>SessionFactory</interfacename>, and an example for a |
||||
DAO method implementation.</para> |
||||
|
||||
<programlisting language="xml"><beans> |
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl"> |
||||
<property name="sessionFactory" ref="mySessionFactory"/> |
||||
</bean> |
||||
|
||||
</beans></programlisting> |
||||
|
||||
<programlisting language="java">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); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>The <classname>HibernateTemplate</classname> class provides many |
||||
methods that mirror the methods exposed on the Hibernate |
||||
<interfacename>Session</interfacename> interface, in addition to a |
||||
number of convenience methods such as the one shown above. If you need |
||||
access to the <interfacename>Session</interfacename> to invoke methods |
||||
that are not exposed on the <classname>HibernateTemplate</classname>, |
||||
you can always drop down to a callback-based approach like so.</para> |
||||
|
||||
<programlisting language="java">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(); |
||||
} |
||||
}; |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>A callback implementation effectively can be used for any |
||||
Hibernate data access. <classname>HibernateTemplate</classname> will |
||||
ensure that <interfacename>Session</interfacename> 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, <classname>HibernateTemplate</classname> offers |
||||
alternative convenience methods that can replace such one line |
||||
callback implementations. Furthermore, Spring provides a convenient |
||||
<classname>HibernateDaoSupport</classname> base class that provides a |
||||
<methodname>setSessionFactory(..)</methodname> method for receiving a |
||||
<interfacename>SessionFactory</interfacename>, and |
||||
<methodname>getSessionFactory()</methodname> and |
||||
<methodname>getHibernateTemplate()</methodname>for use by subclasses. |
||||
In combination, this allows for very simple DAO implementations for |
||||
typical requirements:</para> |
||||
|
||||
<programlisting language="java">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); |
||||
} |
||||
}</programlisting> |
||||
</section> |
||||
|
||||
<section id="orm-hibernate-daos"> |
||||
<title>Implementing Spring-based DAOs without callbacks</title> |
||||
|
||||
<para>As alternative to using Spring's |
||||
<classname>HibernateTemplate</classname> 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 |
||||
<classname>DataAccessException</classname> hierarchy. The |
||||
<classname>HibernateDaoSupport</classname> base class offers methods |
||||
to access the current transactional |
||||
<interfacename>Session</interfacename> and to convert exceptions in |
||||
such a scenario; similar methods are also available as static helpers |
||||
on the <classname>SessionFactoryUtils</classname> class. Note that |
||||
such code will usually pass '<literal>false</literal>' as the value of |
||||
the <methodname>getSession(..)</methodname> methods |
||||
'<literal>allowCreate</literal>' argument, to enforce running within a |
||||
transaction (which avoids the need to close the returned |
||||
<interfacename>Session</interfacename>, as its lifecycle is managed by |
||||
the transaction).</para> |
||||
|
||||
<programlisting language="java">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); |
||||
} |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>The advantage of such direct Hibernate access code is that it |
||||
allows <emphasis>any</emphasis> checked application exception to be |
||||
thrown within the data access code; contrast this to the |
||||
<classname>HibernateTemplate</classname> 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 <classname>HibernateTemplate</classname>. In general, the |
||||
<classname>HibernateTemplate</classname> class' convenience methods |
||||
are simpler and more convenient for many scenarios.</para> |
||||
</section> |
||||
</section> |
||||
|
||||
<section id="classic-spring-jpa"> |
||||
<title>JPA</title> |
||||
|
||||
<para>For the currently recommended usage patterns for JPA see <xref |
||||
linkend="orm-jpa" /></para> |
||||
|
||||
<section id="orm-jpa-template"> |
||||
<title><classname>JpaTemplate</classname> and |
||||
<classname>JpaDaoSupport</classname></title> |
||||
|
||||
<para>Each JPA-based DAO will then receive a |
||||
<interfacename>EntityManagerFactory</interfacename> via dependency |
||||
injection. Such a DAO can be coded against plain JPA and work with the |
||||
given <interfacename>EntityManagerFactory</interfacename> or through |
||||
Spring's <classname>JpaTemplate</classname>:</para> |
||||
|
||||
<programlisting language="xml"><beans> |
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl"> |
||||
<property name="entityManagerFactory" ref="myEmf"/> |
||||
</bean> |
||||
|
||||
</beans></programlisting> |
||||
|
||||
<programlisting language="java">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(); |
||||
<lineannotation>// do some further processing with the result list</lineannotation> |
||||
return result; |
||||
} |
||||
}); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>The <interfacename>JpaCallback</interfacename> implementation |
||||
allows any type of JPA data access. The |
||||
<classname>JpaTemplate</classname> will ensure that |
||||
<interfacename>EntityManager</interfacename>s are properly opened and |
||||
closed and automatically participate in transactions. Moreover, the |
||||
<classname>JpaTemplate</classname> 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 |
||||
<classname>JpaTemplate</classname> offers single-step actions such as |
||||
find, load, merge, etc along with alternative convenience methods that |
||||
can replace one line callback implementations.</para> |
||||
|
||||
<para>Furthermore, Spring provides a convenient |
||||
<classname>JpaDaoSupport</classname> base class that provides the |
||||
<literal>get/setEntityManagerFactory</literal> and |
||||
<methodname>getJpaTemplate()</methodname> to be used by |
||||
subclasses:</para> |
||||
|
||||
<programlisting language="java">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); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>Besides working with Spring's |
||||
<classname>JpaTemplate</classname>, one can also code Spring-based |
||||
DAOs against the JPA, doing one's own explicit |
||||
<interfacename>EntityManager</interfacename> 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. <classname>JpaDaoSupport</classname> offers a |
||||
variety of support methods for this scenario, for retrieving and |
||||
releasing a transaction <interfacename>EntityManager</interfacename>, |
||||
as well as for converting exceptions.</para> |
||||
|
||||
<para><emphasis>JpaTemplate mainly exists as a sibling of JdoTemplate |
||||
and HibernateTemplate, offering the same style for people used to |
||||
it.</emphasis></para> |
||||
</section> |
||||
</section> |
||||
|
||||
<section id="classic-spring-jdo"> |
||||
<title>JDO</title> |
||||
|
||||
<para>For the currently recommended usage patterns for JDO see <xref |
||||
linkend="orm-jdo" /></para> |
||||
|
||||
<section id="orm-jdo-template"> |
||||
<title><classname>JdoTemplate</classname> and |
||||
<classname>JdoDaoSupport</classname></title> |
||||
|
||||
<para>Each JDO-based DAO will then receive the |
||||
<interfacename>PersistenceManagerFactory</interfacename> through |
||||
dependency injection. Such a DAO could be coded against plain JDO API, |
||||
working with the given |
||||
<interfacename>PersistenceManagerFactory</interfacename>, but will |
||||
usually rather be used with the Spring Framework's |
||||
<classname>JdoTemplate</classname>:</para> |
||||
|
||||
<programlisting language="xml"><beans> |
||||
|
||||
<bean id="myProductDao" class="product.ProductDaoImpl"> |
||||
<property name="persistenceManagerFactory" ref="myPmf"/> |
||||
</bean> |
||||
|
||||
</beans></programlisting> |
||||
|
||||
<programlisting language="java">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); |
||||
<lineannotation>// do some further stuff with the result list</lineannotation> |
||||
return result; |
||||
} |
||||
}); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>A callback implementation can effectively be used for any JDO |
||||
data access. <classname>JdoTemplate</classname> will ensure that |
||||
<classname>PersistenceManager</classname>s 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 <literal>find</literal>, |
||||
<literal>load</literal>, <literal>makePersistent</literal>, or |
||||
<literal>delete</literal> call, <classname>JdoTemplate</classname> |
||||
offers alternative convenience methods that can replace such one line |
||||
callback implementations. Furthermore, Spring provides a convenient |
||||
<classname>JdoDaoSupport</classname> base class that provides a |
||||
<literal>setPersistenceManagerFactory(..)</literal> method for |
||||
receiving a <classname>PersistenceManagerFactory</classname>, and |
||||
<methodname>getPersistenceManagerFactory()</methodname> and |
||||
<methodname>getJdoTemplate()</methodname> for use by subclasses. In |
||||
combination, this allows for very simple DAO implementations for |
||||
typical requirements:</para> |
||||
|
||||
<programlisting language="java">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}); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>As alternative to working with Spring's |
||||
<classname>JdoTemplate</classname>, you can also code Spring-based |
||||
DAOs at the JDO API level, explicitly opening and closing a |
||||
<interfacename>PersistenceManager</interfacename>. 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. <classname>JdoDaoSupport</classname> offers a variety of |
||||
support methods for this scenario, for fetching and releasing a |
||||
transactional <interfacename>PersistenceManager</interfacename> as |
||||
well as for converting exceptions.</para> |
||||
</section> |
||||
</section> |
||||
|
||||
<section id="classic-spring-ibatis"> |
||||
<title>iBATIS</title> |
||||
|
||||
<para>For the currently recommended usage patterns for iBATIS see <xref |
||||
linkend="orm-ibatis" /></para> |
||||
|
||||
<section id="orm-ibatis-template"> |
||||
<title>Using <classname>SqlMapClientTemplate</classname> and |
||||
<classname>SqlMapClientDaoSupport</classname></title> |
||||
|
||||
<para>The <classname>SqlMapClientDaoSupport</classname> class offers a |
||||
supporting class similar to the |
||||
<classname>SqlMapDaoSupport</classname>. We extend it to implement our |
||||
DAO:</para> |
||||
|
||||
<programlisting language="java">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); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>In the DAO, we use the pre-configured |
||||
<classname>SqlMapClientTemplate</classname> to execute the queries, |
||||
after setting up the <literal>SqlMapAccountDao</literal> in the |
||||
application context and wiring it with our |
||||
<literal>SqlMapClient</literal> instance:</para> |
||||
|
||||
<programlisting language="xml"><beans> |
||||
|
||||
<bean id="accountDao" class="example.SqlMapAccountDao"> |
||||
<property name="sqlMapClient" ref="sqlMapClient"/> |
||||
</bean> |
||||
|
||||
</beans></programlisting> |
||||
|
||||
<para>Note that a <classname>SqlMapTemplate</classname> instance could |
||||
also be created manually, passing in the |
||||
<literal>SqlMapClient</literal> as constructor argument. The |
||||
<literal>SqlMapClientDaoSupport</literal> base class simply |
||||
pre-initializes a <classname>SqlMapClientTemplate</classname> instance |
||||
for us.</para> |
||||
|
||||
<para>The <classname>SqlMapClientTemplate</classname> also offers a |
||||
generic <literal>execute</literal> method, taking a custom |
||||
<literal>SqlMapClientCallback</literal> implementation as argument. |
||||
This can, for example, be used for batching:</para> |
||||
|
||||
<programlisting language="java">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(); |
||||
} |
||||
}); |
||||
} |
||||
}</programlisting> |
||||
|
||||
<para>In general, any combination of operations offered by the native |
||||
<literal>SqlMapExecutor</literal> API can be used in such a callback. |
||||
Any <literal>SQLException</literal> thrown will automatically get |
||||
converted to Spring's generic |
||||
<classname>DataAccessException</classname> hierarchy.</para> |
||||
</section> |
||||
</section> |
||||
</section> |
||||
|
||||
<section id="clasic-spring-mvc"> |
||||
<title>Classic Spring MVC</title> |
||||
|
||||
<para>...</para> |
||||
</section> |
||||
</appendix> |
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue