updated ORM coverage to provide <tx:advice> and @Transactional samples; removed ProxyFactoryBean example

This commit is contained in:
Thomas Risberg 2009-06-09 23:30:36 +00:00
parent 48e7c44c35
commit c9bcc771dc
2 changed files with 193 additions and 141 deletions

View File

@ -89,7 +89,7 @@ public class SomeMovieFinder implements MovieFinder {
<interfacename>@PersistenceContext</interfacename> annotations. Here is an <interfacename>@PersistenceContext</interfacename> annotations. Here is an
example for a JPA repository:</para> example for a JPA repository:</para>
<programlisting language="java"><![CDATA[@Repository <programlisting language="java">@Repository
public class JpaMovieFinder implements MovieFinder { public class JpaMovieFinder implements MovieFinder {
@PersistenceContext @PersistenceContext
@ -97,12 +97,12 @@ public class JpaMovieFinder implements MovieFinder {
// ... // ...
}]]></programlisting> }</programlisting>
<para>If you are using the classic Hibernate APIs than you can inject the <para>If you are using the classic Hibernate APIs than you can inject the
SessionFactory:</para> SessionFactory:</para>
<programlisting language="java"><![CDATA[@Repository <programlisting language="java">@Repository
public class HibernateMovieFinder implements MovieFinder { public class HibernateMovieFinder implements MovieFinder {
private SessionFactory sessionFactory; private SessionFactory sessionFactory;
@ -114,7 +114,7 @@ public class HibernateMovieFinder implements MovieFinder {
// ... // ...
}]]></programlisting> }</programlisting>
<para>Last example we will show here is for typical JDBC support. You <para>Last example we will show here is for typical JDBC support. You
would have the <classname>DataSource</classname> injected into an would have the <classname>DataSource</classname> injected into an
@ -123,7 +123,7 @@ public class HibernateMovieFinder implements MovieFinder {
like <classname>SimpleJdbcCall</classname> etc using this like <classname>SimpleJdbcCall</classname> etc using this
<classname>DataSource</classname>.</para> <classname>DataSource</classname>.</para>
<programlisting language="java"><![CDATA[@Repository <programlisting language="java">@Repository
public class JdbcMovieFinder implements MovieFinder { public class JdbcMovieFinder implements MovieFinder {
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
@ -135,6 +135,14 @@ public class JdbcMovieFinder implements MovieFinder {
// ... // ...
}]]></programlisting> }</programlisting>
<note>
<para>Please see the specific coverage of each persistence technology
for details on how to configure the application context to take
advantage of these annotations.</para>
</note>
<para></para>
</section> </section>
</chapter> </chapter>

View File

@ -142,8 +142,8 @@
solutions for this issue, sometimes sacrificing proper handling of solutions for this issue, sometimes sacrificing proper handling of
failures for programming convenience. Spring advocates strikingly simple failures for programming convenience. Spring advocates strikingly simple
solutions for proper resource handling, namely IoC via templating in the solutions for proper resource handling, namely IoC via templating in the
case of JDBC and applying AOP interceptors for the ORM technologies. case of JDBC and applying AOP interceptors for the ORM
</para> technologies.</para>
<para>The infrastructure cares for proper resource handling, and for <para>The infrastructure cares for proper resource handling, and for
appropriate conversion of specific API exceptions to an unchecked appropriate conversion of specific API exceptions to an unchecked
@ -155,7 +155,7 @@
<classname>DataAccessException</classname> hierarchy, including <classname>DataAccessException</classname> hierarchy, including
translation of database-specific SQL error codes to meaningful exception translation of database-specific SQL error codes to meaningful exception
classes. For ORM technologies, see the next section for how to get the classes. For ORM technologies, see the next section for how to get the
same exception translation benefits. </para> same exception translation benefits.</para>
<para>When it comes to transaction management the <para>When it comes to transaction management the
<classname>JdbcTemplate</classname> class hooks in to the Spring <classname>JdbcTemplate</classname> class hooks in to the Spring
@ -164,7 +164,7 @@
technologies Spring offers Hibernate, JPA and JDO support via the technologies Spring offers Hibernate, JPA and JDO support via the
Hibernate / JPA / JDO transaction managers as well as JTA support. For Hibernate / JPA / JDO transaction managers as well as JTA support. For
more details on the transaction support see the <xref more details on the transaction support see the <xref
linkend="transaction" /> chapter. </para> linkend="transaction" /> chapter.</para>
</section> </section>
<section id="orm-exception-translation"> <section id="orm-exception-translation">
@ -382,6 +382,140 @@ public class ProductDaoImpl implements ProductDao {
transactions.</para> transactions.</para>
</section> </section>
<section id="orm-hibernate-tx-declarative">
<title>Declarative transaction demarcation</title>
<para>We recommended that you use Spring's declarative transaction
support, which essentially enables you to replace explicit transaction
demarcation API calls in your Java code with an AOP transaction
interceptor configured in a Spring container. This allows you to keep
business services free of repetitive transaction demarcation code, and
allows you to focus on adding business logic which is where the real
value of your application lies.</para>
<note>
<para>You are <emphasis>strongly</emphasis> encouraged to read the
section entitled <xref linkend="transaction-declarative" /> if you
have not done so already prior to continuing.</para>
</note>
<para>Furthermore, transaction semantics like propagation behavior and
isolation level can be changed in a configuration file and do not affect
the business service implementations.</para>
<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>
&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
&lt;property name="sessionFactory" ref="sessionFactory"/&gt;
&lt;/bean&gt;
&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;
&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>
<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>
<lineannotation>// Spring's declarative transaction infrastructure will be demarcating transactions on your behalf </lineannotation>
public void increasePriceOfAllProductsInCategory(final String category) {
List productsToChange = this.productDao.loadProductsByCategory(category);
<lineannotation>// ...</lineannotation>
}
}</programlisting>
<para>For completenes we will also show an attribute-support based
configuration. We 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>
<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
configuration is much simplified while still providing the same
functionality driven by the annotations in the service layer
code.</para>
<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>
&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
&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>
<section id="orm-hibernate-tx-programmatic"> <section id="orm-hibernate-tx-programmatic">
<title>Programmatic transaction demarcation</title> <title>Programmatic transaction demarcation</title>
@ -435,59 +569,6 @@ public class ProductDaoImpl implements ProductDao {
); );
} }
}</programlisting> }</programlisting>
</section>
<section id="orm-hibernate-tx-declarative">
<title>Declarative transaction demarcation</title>
<para>Alternatively, one can use Spring's declarative transaction
support, which essentially enables you to replace explicit transaction
demarcation API calls in your Java code with an AOP transaction
interceptor configured in a Spring container. This allows you to keep
business services free of repetitive transaction demarcation code, and
allows you to focus on adding business logic which is where the real
value of your application lies. Furthermore, transaction semantics like
propagation behavior and isolation level can be changed in a
configuration file and do not affect the business service
implementations.</para>
<programlisting language="xml">&lt;beans&gt;
&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="org.springframework.aop.framework.ProxyFactoryBean"&gt;
&lt;property name="proxyInterfaces" value="product.ProductService"/&gt;
&lt;property name="target"&gt;
&lt;bean class="product.DefaultProductService"&gt;
&lt;property name="productDao" ref="myProductDao"/&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="interceptorNames"&gt;
&lt;list&gt;
&lt;value&gt;myTxInterceptor&lt;/value&gt; <lineannotation>&lt;!-- the transaction interceptor (configured elsewhere) --&gt;</lineannotation>
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;</programlisting>
<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>
<lineannotation>// Spring's declarative transaction infrastructure will be demarcating transactions on your behalf </lineannotation>
public void increasePriceOfAllProductsInCategory(final String category) {
List productsToChange = this.productDao.loadProductsByCategory(category);
<lineannotation>// ...</lineannotation>
}
}</programlisting>
<para>Spring's <classname>TransactionInterceptor</classname> allows any <para>Spring's <classname>TransactionInterceptor</classname> allows any
checked application exception to be thrown with the callback code, while checked application exception to be thrown with the callback code, while
@ -499,55 +580,6 @@ public class ProductDaoImpl implements ProductDao {
<classname>TransactionStatus</classname>). <classname>TransactionStatus</classname>).
<classname>TransactionInterceptor</classname> behaves the same way by <classname>TransactionInterceptor</classname> behaves the same way by
default but allows configurable rollback policies per method.</para> default but allows configurable rollback policies per method.</para>
<para>The following higher level approach to declarative transactions
doesn't use the <classname>ProxyFactoryBean</classname>, and as such may
be easier to use if you have a large number of service objects that you
wish to make transactional.</para>
<note>
<para>You are <emphasis>strongly</emphasis> encouraged to read the
section entitled <xref linkend="transaction-declarative" /> if you
have not done so already prior to continuing.</para>
</note>
<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-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"&gt;
<lineannotation>&lt;!-- <interfacename>SessionFactory</interfacename>, <interfacename>DataSource</interfacename>, etc. omitted --&gt;</lineannotation>
&lt;bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;
&lt;property name="sessionFactory" ref="mySessionFactory"/&gt;
&lt;/bean&gt;
&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;
&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>
</section> </section>
<section id="orm-hibernate-tx-strategies"> <section id="orm-hibernate-tx-strategies">
@ -633,26 +665,24 @@ public class ProductDaoImpl implements ProductDao {
&lt;property name="sessionFactory" ref="mySessionFactory2"/&gt; &lt;property name="sessionFactory" ref="mySessionFactory2"/&gt;
&lt;/bean&gt; &lt;/bean&gt;
<lineannotation>&lt;!-- this shows the Spring 1.x style of declarative transaction configuration --&gt;</lineannotation> &lt;bean id"myProductService" class="product.ProductServiceImpl"&gt;
<lineannotation>&lt;!-- it is totally supported, 100% legal in Spring 2.x, but see also above for the sleeker, Spring 2.0 style --&gt;</lineannotation> &lt;property name="productDao" ref="myProductDao"/&gt;
&lt;bean id="myProductService" &lt;property name="inventoryDao" ref="myInventoryDao"/&gt;
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
&lt;property name="transactionManager" ref="myTxManager"/&gt;
&lt;property name="target"&gt;
&lt;bean class="product.ProductServiceImpl"&gt;
&lt;property name="productDao" ref="myProductDao"/&gt;
&lt;property name="inventoryDao" ref="myInventoryDao"/&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="transactionAttributes"&gt;
&lt;props&gt;
&lt;prop key="increasePrice*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;
&lt;prop key="someOtherBusinessMethod"&gt;PROPAGATION_REQUIRES_NEW&lt;/prop&gt;
&lt;prop key="*"&gt;PROPAGATION_SUPPORTS,readOnly&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
&lt;/bean&gt; &lt;/bean&gt;
&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;
&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;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>Both <classname>HibernateTransactionManager</classname> and <para>Both <classname>HibernateTransactionManager</classname> and
@ -1078,6 +1108,13 @@ public class ProductDaoImpl implements ProductDao {
<para>To execute service operations within transactions, you can use <para>To execute service operations within transactions, you can use
Spring's common declarative transaction facilities. For example:</para> Spring's common declarative transaction facilities. For example:</para>
<note>
<para>You are <emphasis>strongly</emphasis> encouraged to read the
section entitled <xref linkend="transaction-declarative" /> if you
have not done so to get a more detailed coverage of Spring's
declarative transaction support.</para>
</note>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans &lt;beans
xmlns="http://www.springframework.org/schema/beans" xmlns="http://www.springframework.org/schema/beans"
@ -1086,11 +1123,11 @@ public class ProductDaoImpl implements ProductDao {
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"&gt; http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
&lt;bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager"&gt; &lt;bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager"&gt;
&lt;property name="persistenceManagerFactory" ref="myPmf"/&gt; &lt;property name="persistenceManagerFactory" ref="myPmf"/&gt;
@ -1755,10 +1792,10 @@ public class ProductDaoImpl implements ProductDao {
<literal>@PersistenceUnit</literal> and <literal>@PersistenceUnit</literal> and
<literal>@PersistenceContext</literal>) can be applied on field or <literal>@PersistenceContext</literal>) can be applied on field or
methods inside a class, therefore the expression "method/field level methods inside a class, therefore the expression "method/field level
injection". Field-level annotations concise and easier to use while injection". Field-level annotations are concise and easier to use
method-level allow for processing the injected dependency. In both while method-level allow for further processing of the injected
cases the member visibility (public, protected, private) does not dependency. In both cases the member visibility (public, protected,
matter.</para> private) does not matter.</para>
<para>What about class level annotations?</para> <para>What about class level annotations?</para>
@ -1832,6 +1869,13 @@ public class ProductDaoImpl implements ProductDao {
<para>To execute service operations within transactions, you can use <para>To execute service operations within transactions, you can use
Spring's common declarative transaction facilities. For example:</para> Spring's common declarative transaction facilities. For example:</para>
<note>
<para>You are <emphasis>strongly</emphasis> encouraged to read the
section entitled <xref linkend="transaction-declarative" /> if you have
not done so to get a more detailed coverage of Spring's declarative
transaction support.</para>
</note>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@ -1839,11 +1883,11 @@ public class ProductDaoImpl implements ProductDao {
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"&gt; http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"&gt;
&lt;bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt; &lt;bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
&lt;property name="entityManagerFactory" ref="myEmf"/&gt; &lt;property name="entityManagerFactory" ref="myEmf"/&gt;