2

SpringベースのWebアプリケーション内で宣言型トランザクション管理を構成しようとしましたが、協力できません。

私には2つの主な問題があります:

  1. dataSource(アプリケーションに必要)でdefaultAutoCommitをfalseに設定すると、トランザクションが含まれるかどうかに関係なく、すべてのクエリがロールバックされます。
  2. トランザクションが構成され、プロキシクラスとトランザクションメソッドが作成されますが、トランザクションは使用されていないようです。

最初の問題は、個々のクエリがすべてデータベースでロールバックされるため、かなり複雑です。これには、SELECTステートメントも含まれます。すべてのクエリがデータベースでロールバックされる原因は何ですか?

2番目の問題については、トランザクション管理の構成の概要を以下に示します。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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/context http://www.springframework.org/schema/spring-context-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"
       default-autowire="byName">

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
  <!-- the transactional semantics... -->
  <tx:attributes>
    <!-- other methods use the default transaction settings (see below) -->
    <tx:method name="*" rollback-for="Exception" />
  </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution
 of an operation defined by a service in the service package -->
<aop:config>
  <aop:pointcut id="serviceOperations" expression="execution(* foo.bar.service.*.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperations"/>
</aop:config>

<!-- similarly, don't forget the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="defaultAutoCommit" value="false" />
</bean>

<bean id="fooService" class="foo.bar.service.FooService" />

<bean id="barService" class="foo.bar.service.BarService" />

<bean id="zapService" class="foo.bar.service.ZapService" />

</beans>

この問題を解決するために私が訪れたすべてのチュートリアルとフォーラムから、私の構成は正しいはずだと思います。しかし、私はaopとspringのトランザクションを完全には理解していないので、重要な何かを見逃している可能性があります。

上記でほのめかしたように、ログをトレースして、サービスクラス用に作成されているプロキシとトランザクションメソッドを確認できます。ただし、実際にアプリケーションを実行してログをトレースすると、DataSourceTransactionManagerを処理するステートメントや、作成、コミット、ロールバックなどのトランザクションが表示されません。

実際には何も実行されていないように見えます。さまざまなチュートリアルを実行し、さまざまな方法を試したため、非常に混乱していますが、常にこの状況に陥ります。

また、DataSourceTransactionManagerからメッセージを受信するようにlog4jプロパティが正しく設定されていることもかなり確信していますが、ログエラーだけではないことを確認するために以下に提供しています。

私のlog4jは、トランザクションをトレースするために次のロガーでセットアップされています。

log4j.logger.org.springframework=INFO, file
log4j.logger.org.springframework.jdbc.datasource=DEBUG, file
log4j.logger.org.springframework.transaction=DEBUG, file

注:ある時点でDEBUGでトップロガーを実行しました。そこで、サービスプロキシが作成されていることを確認しました。

誰かが何が起こっているのかについて何か洞察を持っていますか?トランザクションが作成されている部分がいくつかあるので、現時点ではかなり行き詰まっていますが、トランザクションが使用されている兆候はまったく見られません。

編集

JBNizetから要求された追加情報。

私のアプリケーション全体はアノテーション駆動型であるため、サービスBeanは@Serviceでアノテーションが付けられ、名前ベースの自動配線を介してコントローラーに注入されます。

以下は私のサービスクラスの1つの例です(名前は変更されていますが、私のapplicationContext.xmlを反映します)。

@Service("zapService")
public class ZapService
{

    /**
     * Data access object which performs the database look up
     */
    private ZapDAO zapDAO;

    /**
     * Add the given zap to the database
     *
     * @param zap a populated zap
     */
    public void processNewZap(Zap zap)
    {
        zapDAO.processNewZap(zap);
    }
}

ご覧のとおり、私のサービスクラスは、コントローラークラスとdaoクラスの間のプロキシにすぎません。DAOは、私が実際にデータベース接続を処理する場所です。

トランザクションを処理するときは、daoクラスではなく、サービスをトランザクションにすることが好ましい方法であるとどこかで読んだと思います。私が間違っている場合は訂正してください。

ZapDAOクラスの概要を以下に示します。

@Repository("zapDAO")
public class ZapDAO
{

    /**
     * Log4j logger for this class
     */
    Logger logger = Logger.getLogger(ZapDAO.class);

    /**
     * Spring jdbc object to handle interacting with the database
     */
    private JdbcTemplate jdbcTemplate;

    public void processNewZap(Zap zap) {

        ... query constructing logic ...

        this.jdbcTemplate.update(INSERT_ZAP_QUERY_SQL);

    }

    public void setDataSource(DataSource dataSource)
    {
        Assert.notNull(dataSource, "You must supply a valid data source");

        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
}

jdbcTemplateを使用して、接続とクエリを処理します。

4

1 に答える 1

3

それで、何時間にもわたって検索、デバッグ、そして髪の毛をはぎ取った後、私はついにすべての答えを提供するこの小さな宝石に出くわしました。

私はそのようなことが問題であるとは思っていませんでしたが、上記のリンクで概説されている手順に従うことは完全に機能しました。

dispatch-servlet.xml内で、最初にコンポーネントスキャンを次のように宣言しました。

<context:component-scan base-package="foo.bar"/>

これは、すべてのアプリケーションBeanの親パッケージです。そのため、上記のリンクで説明されているように、SpringはapplicationContext.xmlのトランザクションサービスBeanを、トランザクションを認識していないdispatcher-servlet.xmlのサービスBeanで上書きしていました。

私が行ったのは、上記のコンポーネントを分割することだけでした。スキャンして、非トランザクションBeanを含むフォルダーのみをスキャンします。

<context:component-scan base-package="foo.bar.controller"/>
<context:component-scan base-package="foo.bar.model"/>
<context:component-scan base-package="foo.bar.service.display"/>
<context:component-scan base-package="foo.bar.service.security"/>

<!-- foo.bar.service gets scanned in applicationContext.xml and includes 
transactions so we must make sure to not include it here. The transactional beans
will be overridden in that case -->

この後、トランザクションは期待どおりに機能し、最終的にログファイルにトランザクションとDataSourceTransactionManagerのフットプリントが表示されました。これにより、データベースの自動ロールバックに関する最初の最初の問題も修正されました。取引の欠如と密接に関係していたに違いないと思います。

于 2011-04-01T19:55:39.520 に答える