orm.xml 101.6 KB
Newer Older
1
<?xml version="1.0" encoding="UTF-8"?>
2 3
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
4
<chapter id="orm">
5
  <title>Object Relational Mapping (ORM) Data Access</title>
6 7

  <section id="orm-introduction">
8 9
    <title>Introduction to ORM with Spring</title>

10
    <para>The Spring Framework supports integration
11 12
    with Hibernate, Java Persistence API (JPA), Java Data Objects (JDO) and
    iBATIS SQL Maps for resource management, data access object (DAO)
13 14 15 16 17
    implementations, and transaction strategies. For example, for Hibernate
    there is first-class support with several convenient IoC features that
    address many typical Hibernate integration issues. You can configure
    all of the supported features for O/R (object relational) mapping tools through
    Dependency Injection. They can participate in Spring's resource
T
Thomas Risberg 已提交
18
    and transaction management, and they comply with Spring's generic
19 20 21 22
    transaction and DAO exception hierarchies. The recommended integration
    style is to code DAOs against plain Hibernate, JPA, and JDO APIs. The
    older style of using Spring's DAO templates is no longer recommended;
    however, coverage of this style can be found in the <xref
T
Thomas Risberg 已提交
23
    linkend="classic-spring-orm" /> in the appendices.</para>
24 25 26

    <para>Spring adds significant enhancements to the ORM layer of your choice
    when you create data access applications. You can leverage as much of the
27
    integration support as you wish, and you should compare this integration
28 29 30
    effort with the cost and risk of building a similar infrastructure
    in-house. You can use much of the ORM support as you would a library,
    regardless of technology, because everything is designed as a set of
31 32
    reusable JavaBeans. ORM in a Spring IoC container facilitates
    configuration and deployment. Thus most examples in this section show
33 34 35 36
    configuration inside a Spring container.</para>

    <para>Benefits of using the Spring Framework to create your ORM DAOs
    include:</para>
37 38 39

    <itemizedlist>
      <listitem>
40 41
        <para><emphasis>Easier testing.</emphasis> Spring's IoC approach makes
        it easy to swap the implementations and configuration locations of
42 43
        Hibernate <interfacename>SessionFactory</interfacename> instances,
        JDBC <interfacename>DataSource</interfacename> instances, transaction
44 45 46 47
        managers, and mapped object implementations (if needed). <!--I changed *mappes* to *mapped*; is that what you mean? Also, clarify whether *if needed* refers only to that or to the rest as well 
TR: OK. Refers only to mapped object implementations-->This in turn makes it
        much easier to test each piece of persistence-related code in
        isolation.<!--deleted redundancy; sentence already refers to isolating each piece of code. TR: OK. moved isolation to the end--></para>
48 49 50 51
      </listitem>

      <listitem>
        <para><emphasis>Common data access exceptions.</emphasis> Spring can
52 53 54
        wrap exceptions from your ORM tool, converting them from proprietary
        (potentially checked) exceptions to a common runtime
        DataAccessException hierarchy. This feature allows you to handle most
55
        persistence exceptions, which are non-recoverable, only in the
56 57 58 59 60 61
        appropriate layers, without annoying boilerplate catches, throws, and
        exception declarations. You can still trap and handle exceptions as
        necessary. Remember that JDBC exceptions (including DB-specific
        dialects) are also converted to the same hierarchy, meaning that you
        can perform some operations with JDBC within a consistent programming
        model.</para>
62 63 64 65 66
      </listitem>

      <listitem>
        <para><emphasis>General resource management.</emphasis> Spring
        application contexts can handle the location and configuration of
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
        Hibernate <interfacename>SessionFactory</interfacename> instances, JPA
        <interfacename>EntityManagerFactory</interfacename> instances, JDBC
        <interfacename>DataSource</interfacename> instances, iBATIS SQL Maps
        configuration objects, and other related resources. This makes these
        values easy to manage and change. Spring offers efficient, easy, and
        safe handling of persistence resources. For example, related code that
        uses Hibernate generally needs to use the same Hibernate
        <interfacename>Session</interfacename> to ensure efficiency and proper
        transaction handling. Spring makes it easy to create and bind a
        <interfacename>Session</interfacename> to the current thread
        transparently, <!--This bullet and next refer to template wrapper class. Is this referring to using Spring DAO templates, whichis no longer recommend--><!--ed? If so, it's confusing to discuss it as an option. Sends a mixed message. If not, explain what you mean by *template* wrapper class. 
TR: REVISED, PLS REVIEW. Good point, removed coverage of template wrapper.-->by
        exposing a current <interfacename>Session</interfacename> through the
        Hibernate <interfacename>SessionFactory</interfacename>. Thus Spring
        solves many chronic problems of typical Hibernate usage, for any local
        or JTA transaction environment.</para>
83 84 85
      </listitem>

      <listitem>
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
        <para><emphasis>Integrated transaction management.</emphasis> You can
        wrap your ORM code with a declarative, aspect-oriented programming
        (AOP) style method interceptor either through the
        <interfacename>@Transactional</interfacename> annotation or by
        explicitly configuring the transaction AOP advice in an XML
        configuration file. In both cases, transaction semantics and exception
        handling (rollback, and so on) are handled for you. As discussed
        below, in <!--Instead of *below*, provide link to section. TR: OK--><link
        linkend="orm-resource-mngmnt">Resource and transaction
        management</link>, you can also swap various transaction managers,
        without affecting your ORM-related code. For example, you can swap
        between local transactions and JTA, with the same full services (such
        as declarative transactions) available in both scenarios.
        Additionally, JDBC-related code can fully integrate transactionally
        with the code you use to do ORM. This is useful for data access that
        is not suitable for ORM, such as batch processing and BLOB streaming,
        which still need <!--if both batch processing and BLOB streaming need to share common transactions w/ ORM, then change *needs* to *to need*. If --><!--it refers only to BLOB streaming, say *the latter of which still needs to share...* TR: OK. Chnaged to *to need*-->to
103 104 105 106
        share common transactions with ORM operations.</para>
      </listitem>
    </itemizedlist>

107 108 109
    <para><!--The PetClinic sample in the Spring distribution offers alternative DAO implementations and application context configurations for JDBC, 
Hibernate, and JPA. PetClinic is a working sample application that illustrates the use of Hibernate and JPA in a Spring web application. 
It also leverages declarative transaction demarcation with different transaction strategies.
110

111 112
Beyond the samples shipped with Spring, vendors provide a variety of Spring-based ORM samples.  --><!--Name vendors, link to them? TR: WILL ADDRESS LATER. We need to point to the current samples which aren't completed yet. --><emphasis>TODO:
    provide links to current samples</emphasis></para>
113 114 115 116 117
  </section>

  <section id="orm-general">
    <title>General ORM integration considerations</title>

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    <para>This section highlights considerations that apply to all ORM
    technologies. The <xref linkend="orm-hibernate" /> section provides more
    details and also show these features and configurations in a concrete
    context.</para>

    <para>The major goal of Spring's ORM integration is 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 need not 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.</para>
138 139

    <section id="orm-resource-mngmnt">
140
      <title>Resource and transaction management</title>
141

142
      <para>Typical business applications are cluttered with repetitive
143
      resource management code. Many projects try to invent their own
144 145 146 147 148
      solutions, sometimes sacrificing proper handling of failures for
      programming convenience. Spring advocates simple solutions for proper
      resource handling, namely IoC through templating<!--same question as before re templates. Does preceding refer to Spring templates that in beginning you say you no longer recommend? 
TR: OK AS IS. The template for JDBC is still recommended--> in the case of
      JDBC and applying AOP interceptors for the ORM technologies.</para>
149

150
      <para>The infrastructure provides proper resource handling and
151
      appropriate conversion of specific API exceptions to an unchecked
152 153 154 155 156
      infrastructure exception hierarchy. <!--What do you mean by *cares for*? I substituted *provides*. Should it be *implements*? TR: OK-->Spring
      introduces a DAO exception hierarchy, applicable to any data access
      strategy. For direct JDBC, the <classname>JdbcTemplate</classname> class
      mentioned in a previous section provides connection handling and proper
      conversion of <classname>SQLException</classname> to the
157 158 159
      <classname>DataAccessException</classname> 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
160
      same exception translation benefits.</para>
161

162
      <para>When it comes to transaction management, the
163
      <classname>JdbcTemplate</classname> class hooks in to the Spring
164
      transaction support and supports both JTA and JDBC transactions, through
165
      respective Spring transaction managers. For the supported ORM
166 167 168 169
      technologies Spring offers Hibernate, JPA and JDO support through the
      Hibernate, JPA, and JDO transaction managers as well as JTA support. For
      details on transaction support, see the <xref linkend="transaction" />
      chapter.</para>
170 171 172
    </section>

    <section id="orm-exception-translation">
173 174 175 176 177 178 179 180 181
      <title>Exception translation</title>

      <para>When you use Hibernate, JPA, or JDO in a DAO, you must decide how
      to handle the persistence technology's native exception classes. The DAO
      throws a subclass of a <classname>HibernateException</classname>,
      <classname>PersistenceException</classname> or
      <interfacename>JDOException</interfacename> depending on the technology.
      These exceptions are all run-time exceptions and do not have to be
      declared or caught. You may also have to deal with
182 183
      <classname>IllegalArgumentException</classname> and
      <classname>IllegalStateException</classname>. This means that callers
184 185
      can only treat exceptions as generally fatal, unless they want to depend
      on the persistence technology's own exception structure. Catching
186
      specific causes such as an optimistic locking failure is not possible
187
      without tying the caller to the implementation strategy. This trade off
188
      might be acceptable to applications that are strongly ORM-based and/or
189 190 191
      do not need any special exception treatment. However, Spring enables
      exception translation to be applied transparently through the
      <interfacename>@Repository</interfacename> annotation:</para>
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

      <programlisting language="java">@Repository
public class ProductDaoImpl implements ProductDao {

    <lineannotation>// class body here...</lineannotation>

}</programlisting>

      <programlisting language="xml">&lt;beans&gt;

  <lineannotation>&lt;!-- <classname>Exception</classname> translation bean post processor --&gt;</lineannotation>
  &lt;bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/&gt;

  &lt;bean id="myProductDao" class="product.ProductDaoImpl"/&gt;

&lt;/beans&gt;</programlisting>

209
      <para>The postprocessor automatically looks for all exception
210 211
      translators (implementations of the
      <interfacename>PersistenceExceptionTranslator</interfacename> interface)
212
      and advises all beans marked with the
213 214 215 216
      <interfacename>@Repository</interfacename> annotation so that the
      discovered translators can intercept and apply the appropriate
      translation on the thrown exceptions.</para>

217 218
      <para>In summary: you can implement DAOs based on the plain persistence
      technology's API and annotations, while still benefiting from
219 220 221 222
      Spring-managed transactions, dependency injection, and transparent
      exception conversion (if desired) to Spring's custom exception
      hierarchies.</para>
    </section>
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
  </section>

  <section id="orm-hibernate">
    <title>Hibernate</title>

    <para>We will start with a coverage of <ulink
    url="http://www.hibernate.org/">Hibernate 3</ulink> in a Spring
    environment, using it to demonstrate the approach that Spring takes
    towards integrating O/R mappers. This section will cover many issues in
    detail and show different variations of DAO implementations and
    transaction demarcation. Most of these patterns can be directly translated
    to all other supported ORM tools. The following sections in this chapter
    will then cover the other ORM technologies, showing briefer examples
    there.</para>

C
Costin Leau 已提交
238
    <para><note><para>As of Spring 3.0, Spring requires Hibernate 3.2 or later.</para></note></para>
239 240 241 242 243 244

    <section id="orm-session-factory-setup">
      <title><interfacename>SessionFactory</interfacename> setup in a Spring
      container</title>

      <para>To avoid tying application objects to hard-coded resource lookups,
245
      you can define resources such as a JDBC
246 247
      <interfacename>DataSource</interfacename> or a Hibernate
      <interfacename>SessionFactory</interfacename> as beans in the Spring
248 249 250 251 252 253 254 255
      container. Application objects that need to access resources receive
      references to such predefined instances through bean references, as
      illustrated in the DAO definition in the next section.</para>

      <para>The following excerpt from an XML application context definition
      shows how to set up a JDBC <classname>DataSource</classname> and a
      Hibernate <interfacename>SessionFactory</interfacename> on top of
      it:</para>
256

257
      <programlisting language="xml">&lt;beans&gt;
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

  &lt;bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
    &lt;property name="driverClassName" value="org.hsqldb.jdbcDriver"/&gt;
    &lt;property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/&gt;
    &lt;property name="username" value="sa"/&gt;
    &lt;property name="password" value=""/&gt;
  &lt;/bean&gt;

  &lt;bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
    &lt;property name="dataSource" ref="myDataSource"/&gt;
    &lt;property name="mappingResources"&gt;
      &lt;list&gt;
        &lt;value&gt;product.hbm.xml&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name="hibernateProperties"&gt;
      &lt;value&gt;
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
      &lt;/value&gt;
    &lt;/property&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>

282
      <para>Switching from a local Jakarta Commons DBCP
283 284 285 286
      <classname>BasicDataSource</classname> to a JNDI-located
      <interfacename>DataSource</interfacename> (usually managed by an
      application server) is just a matter of configuration:</para>

287
      <programlisting language="xml">&lt;beans&gt;
288

289
  &lt;jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/&gt;
290 291 292 293 294

&lt;/beans&gt;</programlisting>

      <para>You can also access a JNDI-located
      <interfacename>SessionFactory</interfacename>, using Spring's
295 296
      <classname>JndiObjectFactoryBean</classname> /
      <literal>&lt;jee:jndi-lookup&gt;</literal> to retrieve and expose it.
297 298 299 300 301 302
      However, that is typically not common outside of an EJB context.</para>
    </section>

    <section id="orm-hibernate-straight">
      <title>Implementing DAOs based on plain Hibernate 3 API</title>

303
      <para>Hibernate 3 has a feature called contextual sessions, wherein
304 305 306 307
      Hibernate itself manages one current
      <interfacename>Session</interfacename> per transaction. This is roughly
      equivalent to Spring's synchronization of one Hibernate
      <interfacename>Session</interfacename> per transaction. A corresponding
308 309
      DAO implementation resembles the following example, based on the plain
      Hibernate API:</para>
310

311
      <programlisting language="java">public class ProductDaoImpl implements ProductDao {
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Collection loadProductsByCategory(String category) {
        return this.sessionFactory.getCurrentSession()
                .createQuery("from test.Product product where product.category=?")
                .setParameter(0, category)
                .list();
    }
}</programlisting>

327 328
      <para>This style is similar to that of the Hibernate reference
      documentation and examples, except for holding the
329 330 331 332 333 334 335
      <interfacename>SessionFactory</interfacename> in an instance variable.
      We strongly recommend such an instance-based setup over the old-school
      <literal>static</literal> <classname>HibernateUtil</classname> class
      from Hibernate's CaveatEmptor sample application. (In general, do not
      keep any resources in <literal>static</literal> variables unless
      <emphasis>absolutely</emphasis> necessary.)</para>

336 337
      <para>The above DAO follows the dependency injection pattern: it fits
      nicely into a Spring IoC container, just as it would if coded against
338
      Spring's <classname>HibernateTemplate</classname>. Of course, such a DAO
339
      can also be set up in plain Java (for example, in unit tests). Simply
340
      instantiate it and call <methodname>setSessionFactory(..)</methodname>
341 342
      with the desired factory reference. As a Spring bean definition, the DAO
      would resemble the following:</para>
343

344
      <programlisting language="xml">&lt;beans&gt;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361

  &lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
    &lt;property name="sessionFactory" ref="mySessionFactory"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>

      <para>The main advantage of this DAO style is that it depends on
      Hibernate API only; no import of any Spring class is required. This is
      of course appealing from a non-invasiveness perspective, and will no
      doubt feel more natural to Hibernate developers.</para>

      <para>However, the DAO throws plain
      <classname>HibernateException</classname> (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
      Hibernate's own exception hierarchy. Catching specific causes such as an
362 363
      optimistic locking failure is not possible without tying the caller to
      the implementation strategy. This trade off might be acceptable to
364 365 366 367 368 369 370 371 372
      applications that are strongly Hibernate-based and/or do not need any
      special exception treatment.</para>

      <para>Fortunately, Spring's
      <classname>LocalSessionFactoryBean</classname> supports Hibernate's
      <methodname>SessionFactory.getCurrentSession()</methodname> method for
      any Spring transaction strategy, returning the current Spring-managed
      transactional <interfacename>Session</interfacename> even with
      <classname>HibernateTransactionManager</classname>. Of course, the
373
      standard behavior of that method remains the return of the current
374
      <interfacename>Session</interfacename> associated with the ongoing JTA
375 376 377
      transaction, if any. This behavior applies regardless of whether you are
      using Spring's <classname>JtaTransactionManager</classname>, EJB
      container managed transactions (CMTs), or JTA.</para>
378

379
      <para>In summary: you can implement DAOs based on the plain Hibernate 3
380 381 382 383
      API, while still being able to participate in Spring-managed
      transactions.</para>
    </section>

384 385 386
    <section id="orm-hibernate-tx-declarative">
      <title>Declarative transaction demarcation</title>

387
      <para>We recommend that you use Spring's declarative transaction
M
Mark Pollack 已提交
388
      support, which enables you to replace explicit transaction demarcation
389 390 391 392 393 394 395
      API calls in your Java code with an AOP transaction interceptor. This
      transaction interceptor can be configured in a Spring container using
      either Java annotations or XML.<!--Reword last part of preceding sentence to clarify *what* is *using Java annotations or XML*. Are you using Java annotations or XML to replace--><!--explicit transaction demarcation API calls, etc. OR are you saying the Spring container is using these? 
TR: REVISED, PLS REVIEW.-->This declarative transaction capability allows you
      to keep business services free of repetitive transaction demarcation
      code and to focus on adding business logic, which is the real value of
      your application.</para>
396 397

      <note>
398 399 400
        <para>Prior to continuing, you are <emphasis>strongly</emphasis>
        encouraged to read <xref linkend="transaction-declarative" /> if you
        have not done so.</para>
401 402 403 404
      </note>

      <para>Furthermore, transaction semantics like propagation behavior and
      isolation level can be changed in a configuration file and do not affect
T
Thomas Risberg 已提交
405
      the business service implementations.<!--give context to example; what is it showing, what is its purpose? TR: REVISED, PLS REVIEW. Added some context.--></para>
406 407 408

      <para>The following example shows how you can configure an AOP
      transaction interceptor, using XML, for a simple service class:</para>
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424

      <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;

  <lineannotation>&lt;!-- <interfacename>SessionFactory</interfacename>, <interfacename>DataSource</interfacename>, etc. omitted --&gt;</lineannotation>

C
Costin Leau 已提交
425 426
  &lt;bean id="transactionManager" 
            class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
427 428 429 430
    &lt;property name="sessionFactory" ref="sessionFactory"/&gt;
  &lt;/bean&gt;
  
  &lt;aop:config&gt;
C
Costin Leau 已提交
431 432
    &lt;aop:pointcut id="productServiceMethods" 
            expression="execution(* product.ProductService.*(..))"/&gt;
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
    &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/&gt;
  &lt;/aop:config&gt;

  &lt;tx:advice id="txAdvice" transaction-manager="myTxManager"&gt;
    &lt;tx:attributes&gt;
      &lt;tx:method name="increasePrice*" propagation="REQUIRED"/&gt;
      &lt;tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/&gt;
      &lt;tx:method name="*" propagation="SUPPORTS" read-only="true"/&gt;
    &lt;/tx:attributes&gt;
  &lt;/tx:advice&gt;

  &lt;bean id="myProductService" class="product.SimpleProductService"&gt;
    &lt;property name="productDao" ref="myProductDao"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>

450 451
      <para>This is the service class that is advised:</para>

452 453 454 455 456 457 458 459 460
      <programlisting language="java">public class ProductServiceImpl implements ProductService {

    private ProductDao productDao;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    <lineannotation>// notice the absence of transaction demarcation code in this method</lineannotation>
C
Costin Leau 已提交
461 462
    <lineannotation>// Spring's declarative transaction infrastructure will be demarcating</lineannotation>
    <lineannotation>// transactions on your behalf </lineannotation>
463 464 465 466 467 468
    public void increasePriceOfAllProductsInCategory(final String category) {
        List productsToChange = this.productDao.loadProductsByCategory(category);
        <lineannotation>// ...</lineannotation>
    }
}</programlisting>

469 470 471 472 473
      <para>We also show an attribute-support based configuration, in the
      following example. <!--I added *in the following example*; is this correct? Relate example below to the one that follows it. TR: OK-->You
      annotate the service layer with @Transactional annotations and instruct
      the Spring container to find these annotations and provide transactional
      semantics for these annotated methods.</para>
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496

      <programlisting language="java">public class ProductServiceImpl implements ProductService {

    private ProductDao productDao;

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    @Transactional
    public void increasePriceOfAllProductsInCategory(final String category) {
        List productsToChange = this.productDao.loadProductsByCategory(category);
        <lineannotation>// ...</lineannotation>
    }

    @Transactional(readOnly = true)
    public List&lt;Product&gt; findAllProducts() {
        return this.productDao.findAllProducts();
    }

}</programlisting>

      <para>As you can see from the following configuration example, the
497 498 499 500 501
      configuration is much simplified, compared to the XML example above,
      while still providing the same functionality driven by the annotations
      in the service layer code. All you need to provide is the
      TransactionManager implementation and a "&lt;tx:annotation-driven/&gt;"
      entry.<!--What does preceding example show, what's its relation to this example? TR: REVISED, PLS REVIEW.--></para>
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517

      <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;

  <lineannotation>&lt;!-- <interfacename>SessionFactory</interfacename>, <interfacename>DataSource</interfacename>, etc. omitted --&gt;</lineannotation>

C
Costin Leau 已提交
518 519
  &lt;bean id="transactionManager"
            class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
520 521 522 523 524 525 526 527 528 529 530 531
    &lt;property name="sessionFactory" ref="sessionFactory"/&gt;
  &lt;/bean&gt;
  
  &lt;tx:annotation-driven/&gt;

  &lt;bean id="myProductService" class="product.SimpleProductService"&gt;
    &lt;property name="productDao" ref="myProductDao"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>
    </section>

532 533 534
    <section id="orm-hibernate-tx-programmatic">
      <title>Programmatic transaction demarcation</title>

535
      <para>You can demarcate transactions in a higher level of the
536
      application, on top of such lower-level data access services spanning
537 538 539 540 541 542
      any number of operations. Nor do restrictions exist on the
      implementation of the surrounding business service; it just needs a
      Spring <classname>PlatformTransactionManager</classname>. Again, the
      latter can come from anywhere, but preferably as a bean reference
      through a <methodname>setTransactionManager(..)</methodname> method,
      just as the <classname>productDAO</classname> should be set by a
543 544 545
      <methodname>setProductDao(..)</methodname> method. The following
      snippets show a transaction manager and a business service definition in
      a Spring application context, and an example for a business method
546
      implementation:</para>
547

548
      <programlisting language="xml">&lt;beans&gt;
549 550 551 552 553 554 555 556 557 558 559 560

  &lt;bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
    &lt;property name="sessionFactory" ref="mySessionFactory"/&gt;
  &lt;/bean&gt;

  &lt;bean id="myProductService" class="product.ProductServiceImpl"&gt;
    &lt;property name="transactionManager" ref="myTxManager"/&gt;
    &lt;property name="productDao" ref="myProductDao"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>

561
      <programlisting language="java">public class ProductServiceImpl implements ProductService {
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589

    private TransactionTemplate transactionTemplate;
    private ProductDao productDao;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public void setProductDao(ProductDao productDao) {
        this.productDao = productDao;
    }

    public void increasePriceOfAllProductsInCategory(final String category) {
        this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {

                public void doInTransactionWithoutResult(TransactionStatus status) {
                    List productsToChange = this.productDao.loadProductsByCategory(category);
                    <lineannotation>// do the price increase...</lineannotation>
                }
            }
        );
    }
}</programlisting>

      <para>Spring's <classname>TransactionInterceptor</classname> allows any
      checked application exception to be thrown with the callback code, while
      <classname>TransactionTemplate</classname> is restricted to unchecked
      exceptions within the callback.
590 591 592
      <classname>TransactionTemplate</classname> triggers a rollback in case
      of an unchecked application exception, or if the transaction is marked
      rollback-only by the application (via
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
      <classname>TransactionStatus</classname>).
      <classname>TransactionInterceptor</classname> behaves the same way by
      default but allows configurable rollback policies per method.</para>
    </section>

    <section id="orm-hibernate-tx-strategies">
      <title>Transaction management strategies</title>

      <para>Both <classname>TransactionTemplate</classname> and
      <classname>TransactionInterceptor</classname> delegate the actual
      transaction handling to a
      <classname>PlatformTransactionManager</classname> instance, which can be
      a <classname>HibernateTransactionManager</classname> (for a single
      Hibernate <interfacename>SessionFactory</interfacename>, using a
      <classname>ThreadLocal</classname>
      <interfacename>Session</interfacename> under the hood) or a
      <classname>JtaTransactionManager</classname> (delegating to the JTA
610 611 612 613 614 615 616 617 618
      subsystem of the container) for Hibernate applications. You can even use
      a custom <classname>PlatformTransactionManager</classname>
      implementation. Switching from native Hibernate transaction management
      to JTA, such as when facing distributed transaction requirements for
      certain deployments of your application, is just a matter of
      configuration. Simply replace the Hibernate transaction manager with
      Spring's JTA transaction implementation. Both transaction demarcation
      and data access code will work without changes, because they just use
      the generic transaction management APIs.</para>
619 620 621 622

      <para>For distributed transactions across multiple Hibernate session
      factories, simply combine <classname>JtaTransactionManager</classname>
      as a transaction strategy with multiple
623 624 625 626 627 628
      <classname>LocalSessionFactoryBean</classname> definitions. Each DAO
      then gets one specific <interfacename>SessionFactory</interfacename>
      reference passed into its corresponding bean property. If all underlying
      JDBC data sources are transactional container ones, a business service
      can demarcate transactions across any number of DAOs and any number of
      session factories without special regard, as long as it is using
629 630
      <classname>JtaTransactionManager</classname> as the strategy.</para>

631
      <programlisting language="xml">&lt;beans&gt;
632

633
  &lt;jee:jndi-lookup id="dataSource1" jndi-name="java:comp/env/jdbc/myds1"/&gt;
634

635
  &lt;jee:jndi-lookup id="dataSource2" jndi-name="java:comp/env/jdbc/myds2"/&gt;
636

C
Costin Leau 已提交
637 638
  &lt;bean id="mySessionFactory1"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
639 640 641 642 643 644 645 646 647 648 649 650 651 652
    &lt;property name="dataSource" ref="myDataSource1"/&gt;
    &lt;property name="mappingResources"&gt;
      &lt;list&gt;
        &lt;value&gt;product.hbm.xml&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name="hibernateProperties"&gt;
      &lt;value&gt;
        hibernate.dialect=org.hibernate.dialect.MySQLDialect
        hibernate.show_sql=true
      &lt;/value&gt;
    &lt;/property&gt;
  &lt;/bean&gt;

C
Costin Leau 已提交
653 654
  &lt;bean id="mySessionFactory2"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
    &lt;property name="dataSource" ref="myDataSource2"/&gt;
    &lt;property name="mappingResources"&gt;
      &lt;list&gt;
        &lt;value&gt;inventory.hbm.xml&lt;/value&gt;
      &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name="hibernateProperties"&gt;
      &lt;value&gt;
        hibernate.dialect=org.hibernate.dialect.OracleDialect
      &lt;/value&gt;
    &lt;/property&gt;
  &lt;/bean&gt;

  &lt;bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;

  &lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
    &lt;property name="sessionFactory" ref="mySessionFactory1"/&gt;
  &lt;/bean&gt;

  &lt;bean id="myInventoryDao" class="product.InventoryDaoImpl"&gt;
    &lt;property name="sessionFactory" ref="mySessionFactory2"/&gt;
  &lt;/bean&gt;

678
  &lt;bean id="myProductService" class="product.ProductServiceImpl"&gt;
679 680
    &lt;property name="productDao" ref="myProductDao"/&gt;
    &lt;property name="inventoryDao" ref="myInventoryDao"/&gt;
681 682
  &lt;/bean&gt;

683
  &lt;aop:config&gt;
C
Costin Leau 已提交
684 685
    &lt;aop:pointcut id="productServiceMethods"
                expression="execution(* product.ProductService.*(..))"/&gt;
686 687 688 689 690 691 692 693 694 695 696
    &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/&gt;
  &lt;/aop:config&gt;

  &lt;tx:advice id="txAdvice" transaction-manager="myTxManager"&gt;
    &lt;tx:attributes&gt;
      &lt;tx:method name="increasePrice*" propagation="REQUIRED"/&gt;
      &lt;tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/&gt;
      &lt;tx:method name="*" propagation="SUPPORTS" read-only="true"/&gt;
    &lt;/tx:attributes&gt;
  &lt;/tx:advice&gt;

697 698 699 700
&lt;/beans&gt;</programlisting>

      <para>Both <classname>HibernateTransactionManager</classname> and
      <classname>JtaTransactionManager</classname> allow for proper JVM-level
701 702 703 704
      cache handling with Hibernate, without container-specific transaction
      manager lookup or a JCA connector (if you are not using EJB to initiate
      transactions).<!--Is it clear that the parenthetical phrase applies to only *JCA connector* or does it apply to *without transaction manager lookup* also?
TR: OK. Reads OK to me, it applies to both. --></para>
705 706

      <para><classname>HibernateTransactionManager</classname> can export the
707 708 709 710 711 712 713 714 715 716 717 718 719 720
      Hibernate JDBC <interfacename>Connection</interfacename> to plain JDBC
      access code, for a specific <interfacename>DataSource</interfacename>.
      This capability allows for high-level transaction demarcation with mixed
      Hibernate and JDBC data access completely without JTA, if you are
      accessing only one database.
      <classname>HibernateTransactionManager</classname> automatically exposes
      the Hibernate transaction as a JDBC transaction if you have set up the
      passed-in <interfacename>SessionFactory</interfacename> with a
      <interfacename>DataSource</interfacename> through the
      <classname>dataSource</classname> property of the
      <classname>LocalSessionFactoryBean</classname> class. Alternatively, you
      can specify explicitly the <interfacename>DataSource</interfacename> for
      which the transactions are supposed to be exposed through the
      <classname>dataSource</classname> property of the
721 722 723 724
      <classname>HibernateTransactionManager</classname> class.</para>
    </section>

    <section id="orm-hibernate-resources">
725 726 727 728 729 730 731 732 733 734
      <title>Comparing container-managed and locally defined resources<!--I've revised to better communicate the point of the section, which I think has to do with --><!--comparing spring's local support for transactions as opposed to container support. Revise as necessary. 
TR: REVISED, PLS REVIEW. Changed to heading *resources* since it technically could be more than transactions i.e. caching--></title>

      <para>You can switch between a container-managed JNDI
      <interfacename>SessionFactory</interfacename><!--Clarify whether JNDI SessionFactory refers to container resources; I'm not sure what's being compared. 
TR: REVISED, PLS REVIEW. Clarified by addin container-managed.--> and a
      locally defined one, without having to change a single line of
      application code. Whether to keep resource definitions in the container
      or locally within the application is mainly a matter of the transaction
      strategy that you use. Compared to a Spring-defined local
735 736 737 738
      <interfacename>SessionFactory</interfacename>, a manually registered
      JNDI <interfacename>SessionFactory</interfacename> does not provide any
      benefits. Deploying a <interfacename>SessionFactory</interfacename>
      through Hibernate's JCA connector provides the added value of
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
      participating in the Java EE server's management infrastructure, but
      does not add actual value beyond that.</para>

      <para>Spring's transaction support is not bound to a container.
      Configured with any strategy other than JTA, transaction support also
      works in a stand-alone or test environment. Especially in the typical
      case of single-database transactions, Spring's single-resource local
      transaction support <!--I wrote *stand-alone transaction support*; if not correct, specify what you mean by *this*. 
TR: REVISED, PLS REVIEW. Changed to single-resource local transaction support.-->is
      a lightweight and powerful alternative to JTA. When you use local EJB
      stateless session beans to drive transactions, you depend both on an EJB
      container and JTA, even if you access only a single database, and only
      use stateless session beans to provide declarative transactions through
      container-managed transactions. <!--Does the next sentence refer to Spring or non-Spring? Clarify. I'm not sure whether the point of this paragraph and preceding is clear. 
TR: REVISED, PLS REVIEW. It's not very clear. I've revised it. It refers to non-Spring programmatic use of JTA.-->Also,
      direct use of JTA programmatically requires a Java EE environment as
      well. JTA does not involve only container dependencies in terms of JTA
      itself and of JNDI <interfacename>DataSource</interfacename> instances.
      For non-Spring, JTA-driven Hibernate transactions, you have to use the
758
      Hibernate JCA connector, or extra Hibernate transaction code with the
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
      <interfacename>TransactionManagerLookup</interfacename> configured for
      proper JVM-level caching.</para>

      <para>Spring-driven transactions can work as well with a locally defined
      Hibernate <interfacename>SessionFactory</interfacename> as they do with
      a local JDBC <interfacename>DataSource </interfacename>if they are
      accessing a single database. Thus you only have to use Spring's JTA
      transaction strategy when you have distributed transaction requirements.
      A JCA connector requires container-specific deployment steps, and
      obviously JCA support in the first place. This configuration requires
      more work than deploying a simple web application with local resource
      definitions and Spring-driven transactions. Also, you often need the
      Enterprise Edition of your container if you are using, for example,
      WebLogic Express, which does not provide JCA. A Spring application with
      local resources and transactions spanning one single database works in
      any Java EE web container (without JTA, JCA, or EJB) such as Tomcat,
      Resin, or even plain Jetty. Additionally, you can easily reuse such a
      middle tier in desktop applications or test suites.</para>

      <para>All things considered, if you do not use EJBs, stick with local
779 780
      <interfacename>SessionFactory</interfacename> setup and Spring's
      <classname>HibernateTransactionManager</classname> or
781 782 783 784 785 786
      <classname>JtaTransactionManager</classname>. You get all of the
      benefits, including proper transactional JVM-level caching and
      distributed transactions, without the inconvenience of container
      deployment. JNDI registration of a Hibernate
      <interfacename>SessionFactory</interfacename> through the JCA connector
      only adds value when used in conjunction with EJBs.</para>
787 788 789
    </section>

    <section id="orm-hibernate-invalid-jdbc-access-error">
790
      <title>Spurious application server warnings with Hibernate</title>
791 792 793

      <para>In some JTA environments with very strict
      <interfacename>XADataSource</interfacename> implementations -- currently
794 795
      only some WebLogic Server and WebSphere versions -- when Hibernate is
      configured without regard to the JTA
796 797
      <interfacename>PlatformTransactionManager</interfacename> object for
      that environment, it is possible for spurious warning or exceptions to
798 799 800 801
      show up in the application server log. These warnings or exceptions
      indicate that the connection being accessed is no longer valid, or JDBC
      access is no longer valid, possibly because the transaction is no longer
      active. As an example, here is an actual exception from WebLogic:</para>
802 803 804 805

      <programlisting>java.sql.SQLException: The transaction is no longer active - status: 'Committed'.
   No further JDBC access is allowed within this transaction.</programlisting>

806 807 808 809
      <para>You resolve this warning by simply making Hibernate aware of the
      JTA <interfacename>PlatformTransactionManager</interfacename> instance,
      to which it will synchronize (along with Spring). You have two options
      for doing this:</para>
810 811 812 813 814 815

      <itemizedlist>
        <listitem>
          <para>If in your application context you are already directly
          obtaining the JTA
          <interfacename>PlatformTransactionManager</interfacename> object
816
          (presumably from JNDI through
817
          <literal>JndiObjectFactoryBean/<literal>&lt;jee:jndi-lookup&gt;</literal></literal>)
818
          and feeding it, for example, to Spring's
819
          <classname>JtaTransactionManager</classname>, then the easiest way
820 821 822 823
          is to specify a reference to the bean defining this JTA
          <interfacename>PlatformTransactionManager</interfacename>
          instance<!--Replace *this* with exactly what *this* refes to--> as
          the value of the <property>jtaTransactionManager</property> property
C
Chris Beams 已提交
824
          for <classname>LocalSessionFactoryBean.</classname> Spring then makes
825
          the object available to Hibernate.</para>
826 827 828 829
        </listitem>

        <listitem>
          <para>More likely you do not already have the JTA
830 831 832 833 834 835 836 837 838
          <interfacename>PlatformTransactionManager</interfacename> instance,
          because Spring's <classname>JtaTransactionManager</classname> can
          find it itself. <!--Re preceding sentence, if this is the case, then why would you need to do what first bullet describes? 
TR: OK AS IS. This is very container dependent, and either case is possible.-->Thus
          you need to configure Hibernate to look up JTA
          <interfacename>PlatformTransactionManager</interfacename> directly.
          You do this by configuring an application server- specific
          <literal>TransactionManagerLookup</literal> class in the Hibernate
          configuration, as described in the Hibernate manual.</para>
839 840 841
        </listitem>
      </itemizedlist>

842 843 844
      <para>The remainder of this section describes the sequence of events
      that occur with and without Hibernate's awareness of the JTA
      <interfacename>PlatformTransactionManager</interfacename>.</para>
845 846

      <para>When Hibernate is not configured with any awareness of the JTA
847 848
      <interfacename>PlatformTransactionManager</interfacename>, the following
      events occur when a JTA transaction commits:</para>
849

850
      <orderedlist>
851
        <listitem>
852
          <para>The JTA transaction commits.</para>
853 854 855 856
        </listitem>

        <listitem>
          <para>Spring's <classname>JtaTransactionManager</classname> is
857
          synchronized to the JTA transaction, so it is called back through an
858 859 860 861 862
          <emphasis>afterCompletion</emphasis> callback by the JTA transaction
          manager.</para>
        </listitem>

        <listitem>
C
Chris Beams 已提交
863
          <para>Among other activities, this synchronization<!--Identify *this*. TR: REVISED, PLS REVIEW. Added "synchronization"--> can
864 865 866 867
          trigger a callback by Spring to Hibernate, through Hibernate's
          <literal>afterTransactionCompletion</literal> callback <!--Preceding line, is *afterTransactionCompletion* callback the same as *afterCompletion* callback in step 2? If so, revise so --><!--there is no redundancy, or at least refer to the two callbacks in the same way. 
TR: OK AS IS. Two different callback methhods - one is Spring's (*afterCompletion*) and the other is Hibernate's (*afterTransactionCompletion*)-->(used
          to clear the Hibernate cache), followed by an explicit
868
          <literal>close()</literal> call on the Hibernate Session, which
869
          causes Hibernate to attempt to <literal>close()</literal> the JDBC
870 871 872 873 874 875 876
          Connection.</para>
        </listitem>

        <listitem>
          <para>In some environments, this
          <methodname>Connection.close()</methodname> call then triggers the
          warning or error, as the application server no longer considers the
877
          <interfacename>Connection</interfacename> usable at all, because the
878 879
          transaction has already been committed.</para>
        </listitem>
880
      </orderedlist>
881 882

      <para>When Hibernate is configured with awareness of the JTA
883 884
      <interfacename>PlatformTransactionManager</interfacename>, the following
      events occur when a JTA transaction commits:</para>
885

886
      <orderedlist>
887
        <listitem>
888
          <para>the JTA transaction is ready to commit.</para>
889 890 891 892
        </listitem>

        <listitem>
          <para>Spring's <classname>JtaTransactionManager</classname> is
893 894 895
          synchronized to the JTA transaction, so the transaction is called
          back through a <emphasis>beforeCompletion</emphasis> callback by the
          JTA transaction manager.</para>
896 897 898 899 900 901 902 903 904 905 906
        </listitem>

        <listitem>
          <para>Spring is aware that Hibernate itself is synchronized to the
          JTA transaction, and behaves differently than in the previous
          scenario. Assuming the Hibernate
          <interfacename>Session</interfacename> needs to be closed at all,
          Spring will close it now.</para>
        </listitem>

        <listitem>
907
          <para>The JTA transaction commits.</para>
908 909 910
        </listitem>

        <listitem>
911 912 913 914
          <para>Hibernate is synchronized to the JTA transaction, so the
          transaction is called back through an
          <emphasis>afterCompletion</emphasis> callback by the JTA transaction
          manager, and can properly clear its cache.</para>
915
        </listitem>
916
      </orderedlist>
917 918 919
    </section>
  </section>

920 921
  <section id="orm-jdo">
    <title>JDO</title>
922

923
    <para>Spring supports the standard JDO 2.0 and 2.1 APIs as data access
924 925 926
    strategy, following the same style as the Hibernate support. The
    corresponding integration classes reside in the
    <literal>org.springframework.orm.jdo</literal> package.</para>
927

928 929 930
    <section id="orm-jdo-setup">
      <title><interfacename>PersistenceManagerFactory</interfacename>
      setup</title>
931

932 933
      <para>Spring provides a
      <classname>LocalPersistenceManagerFactoryBean</classname> class that
934
      allows you to define a local JDO
935 936
      <interfacename>PersistenceManagerFactory</interfacename> within a Spring
      application context:</para>
937

938
      <programlisting language="xml">&lt;beans&gt;
939

940 941 942
  &lt;bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean"&gt;
    &lt;property name="configLocation" value="classpath:kodo.properties"/&gt;
  &lt;/bean&gt;
943 944 945

&lt;/beans&gt;</programlisting>

946 947 948
      <para>Alternatively, you can set up a
      <interfacename>PersistenceManagerFactory</interfacename> through direct
      instantiation of a
949 950
      <interfacename>PersistenceManagerFactory</interfacename> implementation
      class. A JDO <interfacename>PersistenceManagerFactory</interfacename>
M
Mark Pollack 已提交
951 952
      implementation class follows the JavaBeans pattern, just like a JDBC
      <interfacename>DataSource</interfacename> implementation class, which is
953 954
      a natural fit for a configuration that uses Spring. This setup style
      usually supports a Spring-defined JDBC
955
      <interfacename>DataSource</interfacename>, passed into the
956 957 958 959 960 961
      <classname>connectionFactory</classname> property. For example, for the
      open source JDO implementation DataNucleus (formerly JPOX) (<ulink
      url="http://www.datanucleus.org/">http://www.datanucleus.org/</ulink>),
      this is the XML configuration of the
      <interfacename>PersistenceManagerFactory</interfacename>
      implementation:<!--complete the intro sentence; what does this example show? What is its purpose? TR: REVISED, PLS REVIEW.--></para>
962

963
      <programlisting language="xml">&lt;beans&gt;
964

965 966 967 968 969 970
 &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
   &lt;property name="driverClassName" value="${jdbc.driverClassName}"/&gt;
   &lt;property name="url" value="${jdbc.url}"/&gt;
   &lt;property name="username" value="${jdbc.username}"/&gt;
   &lt;property name="password" value="${jdbc.password}"/&gt;
 &lt;/bean&gt;
971

972 973 974 975
 &lt;bean id="myPmf" class="org.datanucleus.jdo.JDOPersistenceManagerFactory" destroy-method="close"&gt;
   &lt;property name="connectionFactory" ref="dataSource"/&gt;
   &lt;property name="nontransactionalRead" value="true"/&gt;
 &lt;/bean&gt;
976

977
&lt;/beans&gt;</programlisting>
978

979 980 981 982 983
      <para>You can also set up JDO
      <interfacename>PersistenceManagerFactory</interfacename> in the JNDI
      environment of a Java EE application server, usually through the JCA
      connector provided by the particular JDO implementation. Spring's
      standard <literal>JndiObjectFactoryBean /
984 985 986
      <literal>&lt;jee:jndi-lookup&gt;</literal></literal> can be used to
      retrieve and expose such a
      <interfacename>PersistenceManagerFactory</interfacename>. However,
987 988 989 990 991
      outside an EJB context, no real benefit exists in holding the
      <interfacename>PersistenceManagerFactory</interfacename> in JNDI: only
      choose such a setup for a good reason. See <xref
      linkend="orm-hibernate-resources" /> for a discussion; the arguments
      there apply to JDO as well.</para>
992
    </section>
993

994 995
    <section id="orm-jdo-daos-straight">
      <title>Implementing DAOs based on the plain JDO API</title>
996

997 998 999 1000
      <para>DAOs can also be written directly against plain JDO API, without
      any Spring dependencies, by using an injected
      <interfacename>PersistenceManagerFactory</interfacename>. The following
      is an example of a corresponding DAO implementation:</para>
1001

1002
      <programlisting language="java">public class ProductDaoImpl implements ProductDao {
1003

1004
    private PersistenceManagerFactory persistenceManagerFactory;
1005

1006 1007 1008
    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
        this.persistenceManagerFactory = pmf;
    }
1009

1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    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();
        }
    }
}</programlisting>
1022

1023 1024 1025
      <para>Because the above DAO follows the dependency injection pattern, it
      fits nicely into a Spring container, just as it would if coded against
      Spring's <classname>JdoTemplate</classname>:</para>
1026

1027
      <programlisting language="xml">&lt;beans&gt;
1028

1029 1030 1031
  &lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
    &lt;property name="persistenceManagerFactory" ref="myPmf"/&gt;
  &lt;/bean&gt;
1032

1033
&lt;/beans&gt;</programlisting>
1034

1035
      <para>The main problem with such DAOs is that they always get a new
1036
      <interfacename>PersistenceManager</interfacename> from the factory. To
1037 1038
      access a Spring-managed transactional
      <interfacename>PersistenceManager</interfacename>, define a
1039 1040
      <classname>TransactionAwarePersistenceManagerFactoryProxy</classname>
      (as included in Spring) in front of your target
1041 1042
      <interfacename>PersistenceManagerFactory</interfacename>, then passing a
      reference to that proxy into your DAOs as in the following example:<!--Revise to clarify *what* is passing the proxy into DAOs? How does that relate to rest of the sentence? TR: REVISED, PLS REVIEW.--></para>
1043

1044
      <programlisting language="xml">&lt;beans&gt;
1045

1046 1047 1048 1049
  &lt;bean id="myPmfProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"&gt;
    &lt;property name="targetPersistenceManagerFactory" ref="myPmf"/&gt;
  &lt;/bean&gt;
1050

1051 1052 1053
  &lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
    &lt;property name="persistenceManagerFactory" ref="myPmfProxy"/&gt;
  &lt;/bean&gt;
1054

1055
&lt;/beans&gt;</programlisting>
1056

1057
      <para>Your data access code will receive a transactional
1058 1059 1060
      <interfacename>PersistenceManager</interfacename> (if any) from the
      <methodname>PersistenceManagerFactory.getPersistenceManager()</methodname>
      method that it calls. The latter method call goes through the proxy,
1061
      which first checks for a current transactional
1062
      <interfacename>PersistenceManager</interfacename> before getting a new
1063 1064 1065
      one from the factory. Any <methodname>close()</methodname> calls on the
      <interfacename>PersistenceManager</interfacename> are ignored in case of
      a transactional
1066
      <interfacename>PersistenceManager</interfacename>.</para>
1067

1068 1069 1070 1071 1072
      <para>If your data access code always runs within an active transaction
      (or at least within active transaction synchronization), it is safe to
      omit the <methodname>PersistenceManager.close()</methodname> call and
      thus the entire <literal>finally</literal> block, which you might do to
      keep your DAO implementations concise:</para>
1073

1074
      <programlisting language="java">public class ProductDaoImpl implements ProductDao {
1075

1076
    private PersistenceManagerFactory persistenceManagerFactory;
1077

1078 1079 1080
    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
        this.persistenceManagerFactory = pmf;
    }
1081

1082 1083 1084 1085 1086 1087 1088
    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);
    }
}</programlisting>
1089

1090
      <para>With such DAOs that rely on active transactions, it is recommended
1091
      that you enforce active transactions through turning off
1092
      <classname>TransactionAwarePersistenceManagerFactoryProxy</classname>'s
1093
      <classname>allowCreate</classname> flag:</para>
1094

1095
      <programlisting language="xml">&lt;beans&gt;
1096

1097 1098 1099 1100 1101
  &lt;bean id="myPmfProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy"&gt;
    &lt;property name="targetPersistenceManagerFactory" ref="myPmf"/&gt;
    &lt;property name="allowCreate" value="false"/&gt;
  &lt;/bean&gt;
1102

1103 1104 1105
  &lt;bean id="myProductDao" class="product.ProductDaoImpl"&gt;
    &lt;property name="persistenceManagerFactory" ref="myPmfProxy"/&gt;
  &lt;/bean&gt;
1106

1107
&lt;/beans&gt;</programlisting>
1108

1109 1110 1111 1112
      <para>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.</para>
1113

1114 1115 1116
      <para>However, the DAO throws plain
      <exceptionname>JDOException</exceptionname> (which is unchecked, so does
      not have to be declared or caught), which means that callers can only
1117 1118 1119 1120
      treat exceptions as fatal, unless you 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 trade off might be acceptable to
1121 1122
      applications that are strongly JDO-based and/or do not need any special
      exception treatment.</para>
1123

1124 1125 1126 1127 1128 1129
      <para>In summary, you can DAOs based on the plain JDO API, and they can
      still participate in Spring-managed transactions. This strategy might
      appeal to you if you are already familiar with JDO. However, such DAOs
      throw plain <exceptionname>JDOException</exceptionname>, and you would
      have to convert explicitly to Spring's
      <exceptionname>DataAccessException</exceptionname> (if desired).</para>
1130
    </section>
1131

1132 1133
    <section id="orm-jdo-tx">
      <title>Transaction management</title>
1134

1135
      <note>
1136 1137 1138 1139
        <para>You are <emphasis>strongly</emphasis> encouraged to read <xref
        linkend="transaction-declarative" /> if you have not done so, to get a
        more detailed coverage of Spring's declarative transaction
        support.</para>
1140 1141
      </note>

1142 1143 1144
      <para>To execute service operations within transactions, you can use
      Spring's common declarative transaction facilities. For example:</para>

1145 1146 1147 1148 1149 1150 1151 1152
      <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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 
1153
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
1154
   http://www.springframework.org/schema/tx 
1155
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
1156
   http://www.springframework.org/schema/aop 
1157
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
1158

1159 1160 1161
  &lt;bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager"&gt;
    &lt;property name="persistenceManagerFactory" ref="myPmf"/&gt;
  &lt;/bean&gt;
1162

1163 1164 1165
  &lt;bean id="myProductService" class="product.ProductServiceImpl"&gt;
    &lt;property name="productDao" ref="myProductDao"/&gt;
  &lt;/bean&gt;
1166

1167 1168 1169 1170 1171 1172 1173
  &lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt;
    &lt;tx:attributes&gt;
      &lt;tx:method name="increasePrice*" propagation="REQUIRED"/&gt;
      &lt;tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/&gt;
      &lt;tx:method name="*" propagation="SUPPORTS" read-only="true"/&gt;
    &lt;/tx:attributes&gt;
  &lt;/tx:advice&gt;
1174

1175
  &lt;aop:config&gt;
C
Costin Leau 已提交
1176 1177
    &lt;aop:pointcut id="productServiceMethods"
            expression="execution(* product.ProductService.*(..))"/&gt;
1178 1179
    &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/&gt;
  &lt;/aop:config&gt;
1180

1181
&lt;/beans&gt;</programlisting>
1182

1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
      <para>JDO requires an active transaction to modify a persistent object.
      The non-transactional flush concept does not exist in JDO, in contrast
      to Hibernate. For this reason, you need to set up the chosen JDO
      implementation for a specific environment. Specifically, you need to set
      it up explicitly for JTA synchronization, to detect an active JTA
      transaction itself. This is not necessary for local transactions as
      performed by Spring's <classname>JdoTransactionManager</classname>, but
      it is necessary to participate in JTA transactions, whether driven by
      Spring's <classname>JtaTransactionManager</classname> or by EJB CMT and
      plain JTA.</para>
1193

1194 1195 1196 1197 1198 1199 1200
      <para><classname>JdoTransactionManager</classname> is capable of
      exposing a JDO transaction to JDBC access code that accesses the same
      JDBC <interfacename>DataSource</interfacename>, provided that the
      registered <classname>JdoDialect</classname> supports retrieval of the
      underlying JDBC <interfacename>Connection</interfacename>. This is the
      case for JDBC-based JDO 2.0 implementations by default.</para>
    </section>
1201

1202 1203
    <section id="orm-jdo-dialect">
      <title><interfacename>JdoDialect</interfacename></title>
1204

1205
      <para>As an advanced feature, both <classname>JdoTemplate</classname>
1206 1207
      and <classname>JdoTransactionManager</classname> support a custom
      <interfacename>JdoDialect</interfacename> that can be passed into the
1208 1209 1210
      <code>jdoDialect</code> bean property. In this scenario, the DAOs will
      not receive a <interfacename>PersistenceManagerFactory</interfacename>
      reference but rather a full <classname>JdoTemplate</classname> instance
1211 1212
      (for example, passed into the <literal>jdoTemplate</literal>
      property of <classname>JdoDaoSupport</classname>). Using a
1213 1214 1215
      <interfacename>JdoDialect</interfacename> implementation, you can enable
      advanced features supported by Spring, usually in a vendor-specific
      manner:</para>
1216

1217 1218
      <itemizedlist>
        <listitem>
1219 1220
          <para>Applying specific transaction semantics such as custom
          isolation level or transaction timeout</para>
1221
        </listitem>
1222

1223
        <listitem>
1224 1225 1226
          <para>Retrieving the transactional JDBC
          <interfacename>Connection</interfacename> for exposure to JDBC-based
          DAOs</para>
1227
        </listitem>
1228

1229
        <listitem>
1230 1231
          <para>Applying query timeouts, which are automatically calculated
          from Spring-managed transaction timeouts</para>
1232
        </listitem>
1233

1234
        <listitem>
1235 1236 1237
          <para>Eagerly flushing a
          <interfacename>PersistenceManager,</interfacename> to make
          transactional changes visible to JDBC-based data access code</para>
1238
        </listitem>
1239

1240
        <listitem>
1241
          <para>Advanced translation of <literal>JDOExceptions</literal> to
1242 1243 1244
          Spring <literal>DataAccessExceptions</literal></para>
        </listitem>
      </itemizedlist>
1245

1246
      <para>See the <classname>JdoDialect</classname> Javadoc for more details
1247
      on its operations and how to use them within Spring's JDO
1248
      support.</para>
1249
    </section>
1250
  </section>
1251

1252 1253
  <section id="orm-jpa">
    <title>JPA</title>
1254

1255 1256
    <para>The Spring JPA, available under the
    <literal>org.springframework.orm.jpa</literal> package, offers
1257 1258 1259 1260 1261
    comprehensive support for the <ulink
    url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/index.html">Java
    Persistence API</ulink> in a similar manner to the integration with
    Hibernate or JDO, while being aware of the underlying implementation in
    order to provide additional features.</para>
1262

1263
    <section id="orm-jpa-setup">
1264
      <title>Three options for JPA setup in a Spring environment</title>
1265

1266 1267 1268
      <para>The Spring JPA support offers three ways of setting up the JPA
      <interfacename>EntityManagerFactory</interfacename> that will be used by
      the application to obtain an entity manager.<!--Define and give purpose of JPA EntityManagerFactory. TR: REVISED, PLS REVIEW.--></para>
1269

1270 1271
      <section id="orm-jpa-setup-lemfb">
        <title><classname>LocalEntityManagerFactoryBean</classname></title>
1272

1273 1274 1275 1276 1277
        <note>
          <para>Only use this option in simple deployment environments such as
          stand-alone applications and integration tests.</para>
        </note>

1278 1279
        <para>The <classname>LocalEntityManagerFactoryBean</classname> creates
        an <interfacename>EntityManagerFactory</interfacename> suitable for
1280 1281 1282 1283 1284 1285
        simple deployment environments where the application uses only JPA for
        data access. <!--Note says use option only for stand-alone apps and testing; does that conflict with preceding line re data access? 
TR: REVISED, PLS REVIEW.-->The factory bean uses the JPA
        <interfacename>PersistenceProvider</interfacename> autodetection
        mechanism (according to JPA's Java SE bootstrapping) and, in most
        cases, requires you to specify only the persistence unit name:</para>
1286

1287 1288 1289 1290 1291
        <programlisting language="xml">&lt;beans&gt;

   &lt;bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"&gt;
      &lt;property name="persistenceUnitName" value="myPersistenceUnit"/&gt;
   &lt;/bean&gt;
1292

1293
&lt;/beans&gt;</programlisting>
1294

1295 1296 1297 1298 1299 1300 1301 1302 1303
        <para>This form of JPA deployment is the simplest and the most
        limited. You cannot refer <!--cannot link *what* to an existing datasource? TR: REVISED, PLS REVIEW.-->to
        an existing JDBC <interfacename>DataSource</interfacename> bean
        definition and no support for global transactions exists. Furthermore,
        weaving (byte-code transformation) of persistent classes is
        provider-specific, often requiring a specific JVM agent to specified
        on startup. This option is sufficient only for stand-alone
        applications and test environments, for which the JPA specification is
        designed.</para>
1304
      </section>
1305

1306
      <section id="orm-jpa-setup-jndi">
1307 1308 1309 1310 1311 1312 1313 1314 1315
        <title>Obtaining an <classname>EntityManagerFactory</classname> from
        JNDI</title>

        <note>
          <para>Use this option when deploying to a Java EE 5 server. Check
          your server's documentation on how to deploy a custom JPA provider
          into your server, allowing for a different provider than the
          server's default.</para>
        </note>
1316

1317
        <para>Obtaining an <interfacename>EntityManagerFactory</interfacename>
1318
        from JNDI (for example in a Java EE 5 environment), is simply a matter
1319 1320 1321 1322 1323
        of changing the XML configuration:</para>

        <programlisting language="xml">&lt;beans&gt;

    &lt;jee:jndi-lookup id="myEmf" jndi-name="persistence/myPersistenceUnit"/&gt;
1324

1325
&lt;/beans&gt;</programlisting>
1326

1327 1328
        <para>This action assumes standard Java EE 5 bootstrapping: the Java
        EE server autodetects persistence units (in effect,
1329 1330
        <literal>META-INF/persistence.xml</literal> files in application jars)
        and <literal>persistence-unit-ref</literal> entries in the Java EE
1331 1332
        deployment descriptor (for example, <literal>web.xml</literal>) and
        defines environment naming context locations for those persistence
1333
        units.</para>
1334

1335 1336 1337 1338 1339 1340 1341 1342
        <para>In such a scenario, the entire persistence unit deployment,
        including the weaving (byte-code transformation) of persistent
        classes, is up to the Java EE server. The JDBC
        <interfacename>DataSource</interfacename> is defined through a JNDI
        location in the <literal>META-INF/persistence.xml</literal> file;
        EntityManager transactions are integrated with the server's JTA
        subsystem. Spring merely uses the obtained
        <interfacename>EntityManagerFactory</interfacename>, passing it on to
1343 1344 1345 1346 1347 1348 1349 1350 1351
        application objects through dependency injection, and managing
        transactions for the persistence unit,<!--identify *it* TR: REVISED, PLS REVIEW. Added *persistence unit*-->
        typically through <classname>JtaTransactionManager</classname>.</para>

        <para>If multiple persistence units are used in the same application,
        the bean names of such JNDI-retrieved persistence units should match
        the persistence unit names that the application uses to refer to them,
        for example, in <literal>@PersistenceUnit</literal> and
        <literal>@PersistenceContext</literal> annotations.</para>
1352
      </section>
1353

1354 1355
      <section id="orm-jpa-setup-lcemfb">
        <title><classname>LocalContainerEntityManagerFactoryBean</classname></title>
1356

1357 1358 1359 1360 1361 1362 1363
        <note>
          <para>Use this option for full JPA capabilities in a Spring-based
          application environment. This includes web containers such as Tomcat
          as well as stand-alone applications and integration tests with
          sophisticated persistence requirements.</para>
        </note>

1364 1365 1366 1367 1368
        <para>The
        <classname>LocalContainerEntityManagerFactoryBean</classname> gives
        full control over <interfacename>EntityManagerFactory</interfacename>
        configuration and is appropriate for environments where fine-grained
        customization is required. The
1369
        <classname>LocalContainerEntityManagerFactoryBean</classname> creates
C
Chris Beams 已提交
1370
        a <interfacename>PersistenceUnitInfo</interfacename> instance based
1371 1372
        on the <literal>persistence.xml</literal> file, the supplied
        <literal>dataSourceLookup</literal> strategy, and the specified
1373
        <literal>loadTimeWeaver</literal>. It is thus possible to work with
1374 1375 1376
        custom data sources outside of JNDI and to control the weaving
        process. The following example shows a typical bean definition for a
        <interfacename>LocalContainerEntityManagerFactoryBean</interfacename>:<!--The following examples shows what? What's its purpose? TR: REVISED, PLS REVIEW.--></para>
1377

1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
        <programlisting language="xml">&lt;beans&gt;
        
 &lt;bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
  &lt;property name="dataSource" ref="someDataSource"/&gt;
  &lt;property name="loadTimeWeaver"&gt;
    &lt;bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/&gt;
  &lt;/property&gt;
 &lt;/bean&gt;
 
&lt;/beans&gt;</programlisting>
1388

1389 1390
        <para>The following example shows a typical
        <literal>persistence.xml</literal> file:</para>
1391

1392
        <programlisting language="xml">&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"&gt;
1393

1394 1395 1396 1397
  &lt;persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL"&gt;
    &lt;mapping-file&gt;META-INF/orm.xml&lt;/mapping-file&gt;
    &lt;exclude-unlisted-classes/&gt;
  &lt;/persistence-unit&gt;
1398

1399
&lt;/persistence&gt;</programlisting>
1400

1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
        <note>
          <para>The <code>exclude-unlisted-classes</code> element always
          indicates that <emphasis>no</emphasis> scanning for annotated entity
          classes is supposed to occur, in order to support the
          <code>&lt;exclude-unlisted-classes/&gt;</code> shortcut. This is in
          line with the JPA specification, which suggests that shortcut, but
          unfortunately is in conflict with the JPA XSD, which implies
          <code>false</code> for that shortcut. Consequently,
          <code>&lt;exclude-unlisted-classes&gt; false
          &lt;/exclude-unlisted-classes/&gt;</code> is not supported. Simply
          omit the <code>exclude-unlisted-classes</code> element if you want
          entity class scanning to occur.</para>
        </note>

        <para>Using the
        <classname>LocalContainerEntityManagerFactoryBean</classname> is the
        most powerful JPA setup option, allowing for flexible local
        configuration within the application. It supports links to an existing
        JDBC <interfacename>DataSource</interfacename>, supports both local
        and global transactions, and so on. However, it also imposes
        requirements on the runtime environment, such as the availability <!--Clarify: first says it imposes *requirements* but says such as *the availability* of a weaving-capable Classloader. Revise to say--><!--whether you are *required* to use this when persistence provider demands byte-code transformation. i.e. what is the *requirement* here? 
TR: OK AS IS. The requirement is to provide the classloader for the runtime environment, if necessary - this is configured outside of Spring.-->of
        a weaving-capable class loader if the persistence provider demands
        byte-code transformation.</para>

        <para>This option may conflict with the built-in JPA capabilities of a
        Java EE 5 server. In a full Java EE 5 environment, consider obtaining
        your <interfacename>EntityManagerFactory</interfacename> from JNDI.
        Alternatively, specify a custom
        <classname>persistenceXmlLocation</classname> on your
1431
        <classname>LocalContainerEntityManagerFactoryBean</classname>
1432 1433 1434 1435
        definition, for example, META-INF/my-persistence.xml, and only include
        a descriptor with that name in your application jar files. Because the
        Java EE 5 server only looks for default
        <literal>META-INF/persistence.xml</literal> files, it ignores such
1436 1437 1438 1439 1440 1441 1442
        custom persistence units and hence avoid conflicts with a
        Spring-driven JPA setup upfront. (This applies to Resin 3.1, for
        example.)</para>

        <sidebar>
          <title>When is load-time weaving required?</title>

1443 1444 1445 1446 1447
          <para>Not all JPA providers require a JVM agent ; Hibernate is an
          example of one that does not. If your provider does not require an
          agent or you have other alternatives, such as applying enhancements
          at build time through a custom compiler or an ant task, the
          load-time weaver <emphasis role="bold">should not</emphasis> be
1448 1449 1450 1451 1452 1453
          used.</para>
        </sidebar>

        <para>The <interfacename>LoadTimeWeaver</interfacename> interface is a
        Spring-provided class that allows JPA
        <interfacename>ClassTransformer</interfacename> instances to be
1454 1455 1456
        plugged in a specific manner, depending whether the environment is a
        web container or application server. <!--Preceding: is this what you mean? Avoid slashes (web container/application server); slashes mean different things depending on context.--><!--Revise if necessary. TR: OK.-->
        Hooking <literal>ClassTransformers</literal> through a Java 5 <ulink
1457
        url="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html">agent</ulink>
1458
        typically is not efficient. The agents work against the
1459
        <emphasis>entire virtual machine</emphasis> and inspect
1460 1461
        <emphasis>every</emphasis> class that is loaded, which is usually
        undesirable in a production server environment.</para>
1462

1463 1464 1465 1466
        <para>Spring provides a number of
        <interfacename>LoadTimeWeaver</interfacename> implementations for
        various environments, allowing
        <interfacename>ClassTransformer</interfacename> instances to be
1467
        applied only <emphasis>per class loader</emphasis> and not per
1468
        VM.</para>
1469

C
Chris Beams 已提交
1470
        <para>Refer to <xref linkend="aop-aj-ltw-spring" /> in the AOP chapter for more insight regarding the 
C
Costin Leau 已提交
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
        <interfacename>LoadTimeWeaver</interfacename> implementations and their setup, either generic or customized to 
        various platforms (such as Tomcat, WebLogic, OC4J, GlassFish, Resin and JBoss).</para>
		
		
		<para>As described in the aforementioned section, you can configure a context-wide <interfacename>LoadTimeWeaver</interfacename>
		using the  <literal>context:load-time-weaver</literal> configuration element. (This has been available since Spring 2.5.)
		Such a global weaver is picked up by all JPA <classname>LocalContainerEntityManagerFactoryBeans</classname>
        automatically. This is the preferred way of setting up a load-time weaver, delivering autodetection of the platform 
        (WebLogic, OC4J, GlassFish, Tomcat, Resin, JBoss or VM agent) and automatic propagation of the weaver to all weaver-aware beans:</para>
		
		<programlisting language="xml">&lt;context:load-time-weaver/&gt;
&lt;bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
    ...
&lt;/bean&gt;</programlisting>
		
		<para> However, if needed, one can manually specify a dedicated weaver through the <literal>loadTimeWeaver</literal> property:</para> 

        <programlisting language="xml">&lt;bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
1489 1490 1491 1492
  &lt;property name="loadTimeWeaver"&gt;
    &lt;bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/&gt;
  &lt;/property&gt;
&lt;/bean&gt;</programlisting>
1493

C
Costin Leau 已提交
1494 1495 1496 1497
          <para>No matter how the LTW is configured, using this technique, JPA applications relying on
          instrumentation can run in the target platform (ex: Tomcat) without needing an agent. 
          This is important especially when the hosting applications rely on different JPA implementations 
          because the JPA transformers are applied only at class loader level and thus are
1498
          isolated from each other.</para>
1499

C
Costin Leau 已提交
1500 1501
		<!-- 
		  <note>
1502 1503
            <para>If you use TopLink Essentials as a JPA provider under
            Tomcat, place the toplink-essentials JAR under
1504
            <emphasis>$CATALINA_HOME</emphasis>/shared/lib folder instead of
C
Costin Leau 已提交
1505 1506
            inside your war.--><!--Revise: *instead of placing the JAR under your WAR*, OR *instead of placing WAR under $CATALINA_HOME/etc*? 
TR: REVISED, PLS REVIEW. Should be *inside your war*. --><!-- </para>
1507
          </note>
C
Costin Leau 已提交
1508
		 -->
1509
      </section>
1510

1511 1512
      <section id="orm-jpa-multiple-pu">
        <title>Dealing with multiple persistence units</title>
1513

1514
        <para>For applications that rely on multiple persistence units
1515
        locations, stored in various JARS in the classpath, for example,
1516 1517
        Spring offers the
        <interfacename>PersistenceUnitManager</interfacename> to act as a
1518 1519 1520 1521 1522 1523
        central repository and to avoid the persistence units discovery
        process, which can be expensive. The default implementation allows
        multiple locations to be specified that are parsed and later retrieved
        through the persistence unit name. (By default, the classpath is
        searched for <filename>META-INF/persistence.xml</filename>
        files.)</para>
1524

1525
        <programlisting language="xml">&lt;bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"&gt;
1526
  &lt;property name="persistenceXmlLocations"&gt;
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
    &lt;list&gt;
     &lt;value&gt;org/springframework/orm/jpa/domain/persistence-multi.xml&lt;/value&gt;
     &lt;value&gt;classpath:/my/package/**/custom-persistence.xml&lt;/value&gt;
     &lt;value&gt;classpath*:META-INF/persistence.xml&lt;/value&gt;
    &lt;/list&gt;
  &lt;/property&gt;
  &lt;property name="dataSources"&gt;
   &lt;map&gt;
    &lt;entry key="localDataSource" value-ref="local-db"/&gt;
    &lt;entry key="remoteDataSource" value-ref="remote-db"/&gt;
   &lt;/map&gt;
  &lt;/property&gt;
  <lineannotation>&lt;!-- if no datasource is specified, use this one --&gt;</lineannotation>
  &lt;property name="defaultDataSource" ref="remoteDataSource"/&gt;
&lt;/bean&gt;
1542

1543 1544
&lt;bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
  &lt;property name="persistenceUnitManager" ref="pum"/&gt;
1545
  &lt;property name="persistenceUnitName" value="myCustomUnit"/&gt;
1546 1547
&lt;/bean&gt;</programlisting>

1548 1549 1550 1551 1552 1553 1554 1555
        <para>The default implementation allows customization of the
        <interfacename>PersistenceUnitInfo</interfacename> instances,<!--What is *infos*? information? Clarify. TR: REVISED, PLS REVIEW.-->
        before they are fed to the JPA provider, declaratively through its
        <!--through what's properties? JPA provider's? TR: OK AS IS. It's the PersistenceUnitManager default implementation's properties-->properties,
        which affect <emphasis>all</emphasis> hosted units, or
        programmatically, through the
        <interfacename>PersistenceUnitPostProcessor</interfacename>, which
        allows persistence unit selection. If no
1556
        <interfacename>PersistenceUnitManager</interfacename> is specified,
1557
        one is created and used internally by
1558 1559
        <classname>LocalContainerEntityManagerFactoryBean</classname>.</para>
      </section>
1560
    </section>
1561

1562 1563
    <section id="orm-jpa-straight">
      <title>Implementing DAOs based on plain JPA</title>
1564

1565
      <note>
1566
        <para>Although <interfacename>EntityManagerFactory</interfacename>
1567 1568
        instances are thread-safe,
        <interfacename>EntityManager</interfacename> instances are not. The
1569 1570
        injected JPA <interfacename>EntityManager</interfacename> behaves like
        an <interfacename>EntityManager</interfacename> fetched from an
1571
        application server's JNDI environment, as defined by the JPA
1572 1573 1574 1575 1576
        specification. It delegates all calls to the current transactional
        <interfacename>EntityManager</interfacename>, if any; otherwise, it
        falls back to a newly created
        <interfacename>EntityManager</interfacename> per operation, in effect
        making its usage thread-safe.<!--Seems contradictory. First sentence says EntityManager instances are not thread-safe; last sentence refers to use--><!--of EntityManager as thread-safe. TR: REVISED, PLS REVIEW.--></para>
1577 1578
      </note>

1579 1580
      <para>It is possible to write code against the plain JPA without any
      Spring dependencies, by using an injected
1581
      <interfacename>EntityManagerFactory</interfacename> or
1582 1583
      <interfacename>EntityManager</interfacename>. Spring can understand
      <interfacename>@PersistenceUnit</interfacename> and
1584 1585 1586
      <interfacename>@PersistenceContext</interfacename> annotations both at
      field and method level if a
      <classname>PersistenceAnnotationBeanPostProcessor</classname> is
1587 1588 1589
      enabled. A plain JPA DAO implementation using the
      <interfacename>@PersistenceUnit</interfacename> annotation <!--corresponding to what? TR: REVISED, PLS REVIEW.-->might
      look like this:</para>
1590

1591
      <programlisting language="java">public class ProductDaoImpl implements ProductDao {
1592

1593
    private EntityManagerFactory emf;
1594

1595 1596 1597
    @PersistenceUnit
    public void setEntityManagerFactory(EntityManagerFactory emf) {
        this.emf = emf;
1598 1599 1600
    }

    public Collection loadProductsByCategory(String category) {
1601
        EntityManager em = this.emf.createEntityManager();
1602
        try {
1603 1604 1605
             Query query = em.createQuery("from Product as p where p.category = ?1");
             query.setParameter(1, category);
             return query.getResultList();
1606 1607
        }
        finally {
1608 1609 1610
            if (em != null) {
                em.close();
            }
1611 1612 1613 1614
        }
    }
}</programlisting>

1615 1616 1617 1618
      <para>The DAO above has no dependency on Spring and still fits nicely
      into a Spring application context. Moreover, the DAO takes advantage of
      annotations to require the injection of the default
      <interfacename>EntityManagerFactory</interfacename>:</para>
1619

1620
      <programlisting language="xml">&lt;beans&gt;
1621

1622 1623 1624 1625
  <lineannotation>&lt;!-- bean post-processor for JPA annotations --&gt;</lineannotation>
  &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;

  &lt;bean id="myProductDao" class="product.ProductDaoImpl"/&gt;
1626 1627 1628

&lt;/beans&gt;</programlisting>

1629
      <para>As an alternative to defining a
1630
      <classname>PersistenceAnnotationBeanPostProcessor</classname>
1631
      explicitly, consider using the Spring
1632
      <literal>context:annotation-config</literal> XML element in your
1633 1634 1635 1636
      application context configuration. Doing so automatically registers all
      Spring standard post-processors for annotation-based configuration,
      including <classname>CommonAnnotationBeanPostProcessor</classname> and
      so on.</para>
1637

1638
      <programlisting language="xml">&lt;beans&gt;
1639

1640 1641
  <lineannotation>&lt;!-- post-processors for all standard config annotations --&gt;</lineannotation>
  &lt;context:annotation-config/&gt;
1642

1643
  &lt;bean id="myProductDao" class="product.ProductDaoImpl"/&gt;
1644 1645 1646

&lt;/beans&gt;</programlisting>

1647 1648 1649
      <para>The main problem with such a DAO is that it always creates a new
      <interfacename>EntityManager</interfacename> through the factory. You
      can avoid this by requesting a transactional
1650
      <interfacename>EntityManager</interfacename> (also called "shared
1651
      EntityManager" because it is a shared, thread-safe proxy for the actual
1652 1653
      transactional EntityManager) to be injected instead of the
      factory:</para>
1654

1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
      <programlisting language="java">public class ProductDaoImpl implements ProductDao {

    @PersistenceContext
    private EntityManager em;

    public Collection loadProductsByCategory(String category) {
       Query query = em.createQuery("from Product as p where p.category = :category");
       query.setParameter("category", category);
       return query.getResultList(); 
    }
}</programlisting>

1667 1668
      <para>The <literal>@PersistenceContext</literal> annotation has an
      optional attribute <literal>type</literal>, which defaults to
1669
      <literal>PersistenceContextType.TRANSACTION</literal>. This default is
1670 1671 1672 1673 1674 1675 1676 1677 1678
      what you need to receive a shared EntityManager proxy. The alternative,
      <literal>PersistenceContextType.EXTENDED</literal>, is a completely
      different affair: This results in a so-called extended EntityManager,
      which is <emphasis>not thread-safe</emphasis> and hence must not be used
      in a concurrently accessed component such as a Spring-managed singleton
      bean. Extended EntityManagers are only supposed to be used in stateful
      components that, for example, reside in a session, with the lifecycle of
      the EntityManager not tied to a current transaction but rather being
      completely up to the application.</para>
1679 1680

      <sidebar>
1681
        <title>Method- and field-level Injection</title>
1682

1683 1684 1685
        <para>Annotations that indicate dependency injections (such as
        <literal>@PersistenceUnit</literal> and
        <literal>@PersistenceContext</literal>) can be applied on field or
1686 1687 1688 1689 1690 1691
        methods inside a class, hence the expressions <emphasis>method-level
        injection</emphasis> and <emphasis>field-level injection</emphasis>.
        Field-level annotations are concise and easier to use while
        method-level allows for further processing of the injected dependency.
        In both cases the member visibility (public, protected, private) does
        not matter.</para>
1692

1693
        <para>What about class-level annotations?</para>
1694

1695 1696 1697
        <para>On the Java EE 5 platform, they are used for dependency
        declaration and not for resource injection.</para>
      </sidebar>
1698

1699 1700
      <para>The injected <interfacename>EntityManager</interfacename> is
      Spring-managed (aware of the ongoing transaction). It is important to
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
      note that even though the new DAO implementation uses method level
      injection of an <interfacename>EntityManager</interfacename> instead of
      an <interfacename>EntityManagerFactory</interfacename>, no change is
      required in the application context XML due to annotation usage.<!--I changed *prefers* to *works better with*. Revise if needed, but an impl. doesn't *prefer*. Also *what* is due to annotation usage; what does--><!--this refer to? TR: REVISED, PLS REVIEW.--></para>

      <para>The main advantage of this DAO style is that it only depends on
      Java Persistence API; no import of any Spring class is required.
      Moreover, as the JPA annotations are understood, the injections are
      applied automatically by the Spring container. This is appealing from a
      non-invasiveness perspective, and might feel more natural to JPA
1711 1712
      developers.</para>
    </section>
1713

1714 1715
    <section id="orm-jpa-tx">
      <title>Transaction Management</title>
1716

1717
      <note>
1718 1719 1720 1721
        <para>You are <emphasis>strongly</emphasis> encouraged to read <xref
        linkend="transaction-declarative" /> if you have not done so, to get a
        more detailed coverage of Spring's declarative transaction
        support.</para>
1722
      </note>
1723

1724 1725 1726
      <para>To execute service operations within transactions, you can use
      Spring's common declarative transaction facilities. For example:</para>

1727
      <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
1728 1729 1730 1731 1732 1733
&lt;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 
1734
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
1735
       http://www.springframework.org/schema/tx 
1736
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
1737
       http://www.springframework.org/schema/aop 
1738
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
1739

1740 1741
  &lt;bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
    &lt;property name="entityManagerFactory" ref="myEmf"/&gt;
1742 1743 1744 1745 1746
  &lt;/bean&gt;

  &lt;bean id="myProductService" class="product.ProductServiceImpl"&gt;
    &lt;property name="productDao" ref="myProductDao"/&gt;
  &lt;/bean&gt;
1747 1748 1749 1750 1751
  
  &lt;aop:config&gt;
    &lt;aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/&gt;
    &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/&gt;
  &lt;/aop:config&gt;
1752

1753
  &lt;tx:advice id="txAdvice" transaction-manager="myTxManager"&gt;
1754 1755 1756 1757 1758 1759 1760 1761 1762
    &lt;tx:attributes&gt;
      &lt;tx:method name="increasePrice*" propagation="REQUIRED"/&gt;
      &lt;tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/&gt;
      &lt;tx:method name="*" propagation="SUPPORTS" read-only="true"/&gt;
    &lt;/tx:attributes&gt;
  &lt;/tx:advice&gt;

&lt;/beans&gt;</programlisting>

1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
      <para>Spring JPA allows a configured
      <classname>JpaTransactionManager</classname> to expose a JPA transaction
      to JDBC access code that accesses the same JDBC
      <interfacename>DataSource</interfacename>, provided that the registered
      <interfacename>JpaDialect</interfacename> supports retrieval of the
      underlying JDBC <interfacename>Connection</interfacename>. Out of the
      box, Spring provides dialects for the Toplink, Hibernate and OpenJPA JPA
      implementations. See the next section for details on the
      <interfacename>JpaDialect</interfacename> mechanism.</para>
    </section>

    <section id="orm-jpa-dialect">
      <title><interfacename>JpaDialect</interfacename></title>

      <para>As an advanced feature <classname>JpaTemplate</classname>,
      <classname>JpaTransactionManager</classname> and subclasses of
      <classname>AbstractEntityManagerFactoryBean</classname> support a custom
      <interfacename>JpaDialect</interfacename>, to be passed into the
1781 1782 1783 1784 1785 1786 1787
      <property>jpaDialect</property> bean property. In such a scenario, the
      DAOs do not receive an
      <interfacename>EntityManagerFactory</interfacename> reference but rather
      a full <classname>JpaTemplate</classname> instance (for example,
      passed<!--Clarify *what* is passed? Reword this for example phrase. TR: OK AS-->
      into the <property>jpaTemplate</property> property<classname> of
      JpaDaoSupport</classname>). A <interfacename>JpaDialect</interfacename>
1788 1789 1790 1791 1792
      implementation can enable some advanced features supported by Spring,
      usually in a vendor-specific manner:</para>

      <itemizedlist>
        <listitem>
1793
          <para>Applying specific transaction semantics such as custom
1794 1795 1796 1797
          isolation level or transaction timeout)</para>
        </listitem>

        <listitem>
1798 1799 1800
          <para>Retrieving the transactional JDBC
          <interfacename>Connection</interfacename> for exposure to JDBC-based
          DAOs)</para>
1801 1802 1803
        </listitem>

        <listitem>
1804
          <para>Advanced translation of
1805 1806 1807 1808 1809 1810
          <literal>PersistenceExceptions</literal> to Spring
          <literal>DataAccessExceptions</literal></para>
        </listitem>
      </itemizedlist>

      <para>This is particularly valuable for special transaction semantics
1811 1812 1813 1814
      and for advanced translation of exception. The default implementation
      used (<classname>DefaultJpaDialect</classname>) does not provide any
      special capabilities and if the above features are required, you have to
      specify the appropriate dialect.</para>
1815 1816 1817 1818 1819

      <para>See the <interfacename>JpaDialect</interfacename> Javadoc for more
      details of its operations and how they are used within Spring's JPA
      support.</para>
    </section>
1820
  </section>
1821

1822 1823
  <section id="orm-ibatis">
    <title>iBATIS SQL Maps</title>
1824

1825
    <para>The iBATIS support in the Spring Framework much resembles the JDBC
1826 1827 1828 1829
    support in that it supports the same template style programming, and as
    with JDBC and other ORM technologies, the iBATIS support works with
    Spring's exception hierarchy and lets you enjoy Spring's IoC
    features.</para>
1830

1831
    <para>Transaction management can be handled through Spring's standard
1832 1833
    facilities. No special transaction strategies are necessary for iBATIS,
    because no special transactional resource involved other than a JDBC
1834 1835 1836 1837
    <interfacename>Connection</interfacename>. Hence, Spring's standard JDBC
    <classname>DataSourceTransactionManager</classname> or
    <classname>JtaTransactionManager</classname> are perfectly
    sufficient.</para>
1838

1839
    <note>
1840 1841
      <para>Spring supports iBATIS 2.x. The iBATIS 1.x support classes are no
      longer provided.<!--directed where? TR: REVISED, PLS REVIEW.--></para>
1842
    </note>
1843

1844 1845
    <section id="orm-ibatis-setup">
      <title>Setting up the <classname>SqlMapClient</classname></title>
1846

1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877
      <para>Using iBATIS SQL Maps involves creating SqlMap configuration files
      containing statements and result maps. Spring takes care of loading
      those using the <classname>SqlMapClientFactoryBean</classname>. For the
      examples we will be using the following <classname>Account</classname>
      class:</para>

      <programlisting language="xml">public class Account {

    private String name;
    private String email; 

    public String getName() {
        return this.name;
    }
 
    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}</programlisting>

      <para>To map this <classname>Account</classname> class<!--*previous account class*:Identify the account class and the section you're talking about 
TR: REVISED, PLS REVIEW. The Account class was part of the iBATIS 1.0 examples that were dropped a long time ago. No one has complained.
Makes you wonder if anyone actually reads thes docs :)--> with iBATIS 2.x we
1878
      need to create the following SQL map
1879
      <filename>Account.xml</filename>:</para>
1880

1881
      <programlisting language="xml">&lt;sqlMap namespace="Account"&gt;
1882

1883 1884 1885 1886
  &lt;resultMap id="result" class="examples.Account"&gt;
    &lt;result property="name" column="NAME" columnIndex="1"/&gt;
    &lt;result property="email" column="EMAIL" columnIndex="2"/&gt;
  &lt;/resultMap&gt;
1887

1888 1889 1890 1891 1892
  &lt;select id="getAccountByEmail" resultMap="result"&gt;
    select ACCOUNT.NAME, ACCOUNT.EMAIL
    from ACCOUNT
    where ACCOUNT.EMAIL = #value#
  &lt;/select&gt;
1893

1894 1895 1896
  &lt;insert id="insertAccount"&gt;
    insert into ACCOUNT (NAME, EMAIL) values (#name#, #email#)
  &lt;/insert&gt;
1897

1898
&lt;/sqlMap&gt;</programlisting>
1899

1900
      <para>The configuration file for iBATIS 2 looks like this:</para>
1901

1902
      <programlisting language="xml">&lt;sqlMapConfig&gt;
1903

1904
  &lt;sqlMap resource="example/Account.xml"/&gt;
1905

1906
&lt;/sqlMapConfig&gt;</programlisting>
1907

1908
      <para>Remember that iBATIS loads resources from the class path, so be
1909
      sure to add the<filename>Account.xml</filename> file to the class
1910
      path.</para>
1911

1912 1913 1914 1915
      <para>We can use the <classname>SqlMapClientFactoryBean</classname> in
      the Spring container. Note that with iBATIS SQL Maps 2.x, the JDBC
      <interfacename>DataSource</interfacename> is usually specified on the
      <classname>SqlMapClientFactoryBean</classname>, which enables lazy
1916 1917
      loading. This is the configuration needed for these bean
      definitions:<!--Need intro to this example; what's its purpose? TR: REVISED, PLS REVIEW.--></para>
1918

1919
      <programlisting language="xml">&lt;beans&gt;
1920

1921 1922 1923 1924 1925
  &lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
    &lt;property name="driverClassName" value="${jdbc.driverClassName}"/&gt;
    &lt;property name="url" value="${jdbc.url}"/&gt;
    &lt;property name="username" value="${jdbc.username}"/&gt;
    &lt;property name="password" value="${jdbc.password}"/&gt;
1926 1927
  &lt;/bean&gt;

1928 1929 1930
  &lt;bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"&gt;
    &lt;property name="configLocation" value="WEB-INF/sqlmap-config.xml"/&gt;
    &lt;property name="dataSource" ref="dataSource"/&gt;
1931 1932 1933
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>
1934
    </section>
1935

1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968
    <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">&lt;beans&gt;

  &lt;bean id="accountDao" class="example.SqlMapAccountDao"&gt;
    &lt;property name="sqlMapClient" ref="sqlMapClient"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>

1969 1970 1971 1972
      <para>An <classname>SqlMapTemplate</classname> instance can also be
      created manually, passing in the <literal>SqlMapClient</literal> as
      constructor argument. The <literal>SqlMapClientDaoSupport</literal> base
      class simply preinitializes a
1973 1974
      <classname>SqlMapClientTemplate</classname> instance for us.</para>

1975 1976
      <para>The <classname>SqlMapClientTemplate</classname> offers a generic
      <literal>execute</literal> method, taking a custom
1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
      <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.
1996 1997
      Any thrown <literal>SQLException</literal> is converted automatically to
      Spring's generic <classname>DataAccessException</classname>
1998 1999 2000
      hierarchy.</para>
    </section>

2001 2002
    <section id="orm-ibatis-straight">
      <title>Implementing DAOs based on plain iBATIS API</title>
2003

2004 2005
      <para>DAOs can also be written against plain iBATIS API, without any
      Spring dependencies, directly using an injected
2006 2007
      <literal>SqlMapClient</literal>. The following example shows a
      corresponding DAO implementation:</para>
2008

2009 2010 2011 2012 2013 2014 2015
      <programlisting language="java">public class SqlMapAccountDao implements AccountDao {
        
    private SqlMapClient sqlMapClient;
    
    public void setSqlMapClient(SqlMapClient sqlMapClient) {
        this.sqlMapClient = sqlMapClient;
    }
2016

2017 2018 2019 2020 2021 2022 2023 2024
    public Account getAccount(String email) {
        try {
            return (Account) this.sqlMapClient.queryForObject("getAccountByEmail", email);
        }
        catch (SQLException ex) {
            throw new MyDaoException(ex);
        }
    }
2025

2026 2027 2028 2029 2030 2031 2032 2033 2034
    public void insertAccount(Account account) throws DataAccessException {
        try {
            this.sqlMapClient.update("insertAccount", account);
        }
        catch (SQLException ex) {
            throw new MyDaoException(ex);
        }
    }
}</programlisting>
2035

2036 2037 2038 2039 2040 2041 2042 2043
      <para>In this scenario, you need to handle the
      <literal>SQLException</literal> thrown by the iBATIS API in a custom
      fashion, usually by wrapping it in your own application-specific DAO
      exception. Wiring in the application context would still look like it
      does in the example for the
      <classname>SqlMapClientDaoSupport</classname><!--Clarify what wiring the app context looks like. What do you mean *before*? Looks like *what* specifically? TR: REVISED, PLS REVIEW.-->,
      due to the fact that the plain iBATIS-based DAO still follows the
      dependency injection pattern:</para>
2044

2045
      <programlisting language="xml">&lt;beans&gt;
2046

2047 2048 2049 2050 2051 2052
  &lt;bean id="accountDao" class="example.SqlMapAccountDao"&gt;
    &lt;property name="sqlMapClient" ref="sqlMapClient"/&gt;
  &lt;/bean&gt;

&lt;/beans&gt;</programlisting>
    </section>
2053
  </section>
2054
</chapter>