4

SpringがDAOオブジェクトへのプロキシをサービスに注入しているという問題がありますが、このサービスはコントローラーに注入され、具象クラスです。これにより、サービス全体のトランザクションを使用できず、DAO 呼び出しごとにトランザクションを個別に起動できます。それは私が期待する振る舞いです。

構成:

コントローラーは、@Controller アノテーションとコンストラクター DI を持つクラスです。

サービス:

@成分
@トランザクション
public class UserServiceImpl は UserService を実装します { ...}

ダオ:

@成分
@トランザクション
public class UserDaoImpl は UserDao を実装します {

JPA構成:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="xxxPersistenceUnit"/>
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<tx:annotation-driven />

なぜそれが起こっているのか誰にも分かりますか?

4

4 に答える 4

5

サーブレットコンテキストで誤ってUserServiceImpl作成された可能性があります。 式をチェックして、 クラスのみが含まれていることを確認してください。context:component-scanController

コンポーネントスキャンフィルターの例については、@Serviceが2回作成されるを参照してください。

たとえば、トランザクションマネージャーBeanがルートWebアプリコンテキスト<tx:annotation-driven>で宣言されている場合、トランザクションプロキシはルートアプリコンテキストのBeanに対してのみ作成されます(Spring Documentationから)。

BeanPostProcessorインターフェースは、コンテナーごとにスコープが設定されます。これは、コンテナ階層を使用している場合にのみ関係します。1つのコンテナーでBeanPostProcessorを定義すると、そのコンテナー内のBeanに対してのみ機能します。あるコンテナーで定義されたBeanは、両方のコンテナーが同じ階層の一部であっても、別のコンテナーのBeanPostProcessorによって後処理されません。

ユーザーサービスのトランザクション構成が別のトランザクションマネージャー(または別のデフォルトの伝播)を使用するように構成されている可能性は低いですが、その場合TransactionInterceptor 、DAOメソッドのスタックトレースに呼び出しが存在します。

自分が何をしているのかを理解していれば、SpringのDAOクラスに参加することは絶対に問題あり@Transactionalません-リポジトリまたはDAOがトランザクションを開くことができないという考えは、トランザクションを開くための定型コードを作成する必要があり、それが困難だった暗い時代から来ていますトランザクションインスタンスを管理します(そして、トランザクションがどのように管理されているかを確信できませんでした)。しかし、宣言型構成を使用している場合、状況はそれほど悪くありません。Propagation.REQUIREDSpringは、ほとんどのメソッドがトランザクションモードを使用する設定より規約スタイルを促進します。SpringPropagation.REQUIREDでは、メソッドをデコレーションするときのデフォルトモードです@Transactional(この伝播は@Transactionalアノテーション宣言にハードコーディングされています)。つまり、新しい論理トランザクションは同じ物理トランザクションにマップされるため、DAOクラスをデコレーションします。@Transactional無害です。

Springでのトランザクション伝播に関するリファレンスについては、http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html#tx-propagationを参照してください。

たとえば、Spring Data JPA(彼らは彼らが何をしているのかを知っていると確信しています)では、リポジトリインスタンスのCRUDメソッドはデフォルトでトランザクションです。これは場合によっては便利かもしれませんが、メカニズムは、HibernateがSession 明示的なトランザクションを宣言せずに表示するためにから任意のオブジェクトをget()できる場合と同じです(もちろん、フレームワークがなんらかの方法でトランザクションなしで実行できることを意味するわけではありません-この場合は暗黙的です)。

于 2013-01-29T20:05:18.467 に答える
2

あなたの言っていることが少し理解できませんが、サービス コールだけでなく、DAO 呼び出しごとに新しいトランザクションを取得していることに驚いているようです。残念ながら、DAO クラスに "@Transactional" を付けることで指定したのは、まさにそれです。少なくとも通常のパターンに従っている場合、DAO はトランザクション対応であってはなりません。私の理解が正しければ、DAO クラスの @Transactional アノテーションを削除する必要があります。

于 2013-01-29T16:22:53.473 に答える
1

他のレスポンダーは、DAO に として注釈を付けるべきではないという点で正しいです@Transactionalが、実際に何が起こっているのかを理解するには、Spring Reference Manual の Transaction Propagation セクションを参照する必要があります。使用時のデフォルトの伝搬@TransactionalREQUIRES_PROPAGATIONですので、具体的に見直してください。

あなたの質問はそれほど具体的ではないので、あなたが何を探しているのか正確にはわかりません。

編集:質問を読み直すと、コンポーネントのスキャンに問題がある可能性があります。<tx:annotation-driven />コンポーネントがサービス クラスをスキャンしているのと同じアプリケーション コンテキストにあることを確認してください。

于 2013-01-29T18:46:44.930 に答える
0

DAO オブジェクトでその「@Transactional」アノテーションを使用しないでください。サービスでそれを定義しており、サービスメソッド内で呼び出されたすべてのDAOメソッドが同じトランザクション内で実行されることを許可します。これは、「サービス全体のトランザクション」と言うと、まさにあなたが望むものと思われます。 ?

また、提案されているように、注釈を UserServiceImpl では "@Component" から "@Service" に、UserDaoImpl では "@Repository" に変更することをお勧めします。

よろしくお願いします。

于 2013-01-29T16:40:34.003 に答える