8

Spring、JPA、組み込みH2データベースを使用して簡単なアプリケーションを作成しようとしています。最近、宣言型トランザクションでこの奇妙な問題に遭遇しました。@Repositoryアノテーションを使用してDAOを自動配線すると、コミットされません。具体的には、フラッシュで例外が発生します。

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

これが私の設定です:

persistence.xml

<persistence-unit name="schedulePU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/scheduleDB" />
        <property name="javax.persistence.jdbc.user" value="sa" />
        <property name="javax.persistence.jdbc.password" value="" />
        <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.H2Platform" />
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
        <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
</persistence-unit>

実在物

@Entity
@Table(name = "Professors")
public class Professor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;

    public Professor() { }

    public Professor(String name) {
        this.name = name;
    }
}

DAO

@Repository
public class JpaDao {

    @PersistenceContext
    private EntityManager em;

    @Transactional
    public void addProfessor(Professor professor) {
        em.persist(professor);
        em.flush();
    }
}

database.xml(ルートスプリングコンテキストから含まれる)

<beans>
    <context:component-scan base-package="com.spybot.schedule.dao" />

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="schedulePU" />
    </bean>

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

    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

コントローラ

@Controller
public class HomeController {

    @Inject
    JpaDao dao;

    @RequestMapping("/add")
    public @ResponseBody String add(String name) {
        Professor p = new Professor(name);
        dao.addProfessor(p);
        return ":)";
    }
}

そして今、興味深い部分です。DAOから@Repositoryアノテーションを削除し、それをdatabase.xmlで明示的に指定すると、すべてが正常に機能します。

アップデート

別のサーブレット構成<tx:annotation-driven />のサーブレット構成に入れると問題が解決しますが、なぜですか?

4

3 に答える 3

5

おそらく、はスキャンにDAOクラスを含めているためcomponent-scanspring-servlet.xmlアプリケーションコンテキスト(「データベース」のものではない)でそれらのインスタンスを作成しているためです。これにより、WebがWebコントローラーからこれらのDAOにアクセスするときに、それらの非トランザクションバージョン(そのtx:annotation-drivenタグを追加しない限り)。

したがって、そのタグを追加すると、DAOインスタンスが間違ったアプリケーションコンテキストで作成されるため、実際には悪い解決策になりbase-packageます。Webレイヤーコンポーネントを作成するためのより具体的な構成を作成する方が適切です。

<context:include-filter>私はこれと同じ問題を抱えていました。なぜなら、私の中spring-servlet.xmlではスキャンクラスのみを処理していると思っていたから@Controllerです...しかし、:-(

于 2012-06-03T10:11:57.213 に答える
0

@Transactionalアノテーションは、インターフェース定義、インターフェース上のメソッド、クラス定義、またはクラス上のパブリックメソッドの前に配置できます。@Transactionalただし、アノテーションが存在するだけでは、トランザクションの動作を実際にオンにするのに十分ではないことに注意してください。アノテーション@Transactionalは、@Transactional認識しているものが使用できるメタデータであり、メタデータを使用してトランザクションで適切なBeanを構成できます。行動。上記の例の場合<tx:annotation-driven/>、トランザクション動作をオンにするのは要素の存在です。

春のドキュメントからhttp://static.springsource.org/spring/docs/2.0.8/reference/transaction.html

于 2012-01-29T11:23:25.873 に答える
0

推測ですが、自動的に登録されるPersistenceAnnotationBeanPostProcessorため、自分で登録する必要はありません<context:component-scan>。2つが互いに干渉している可能性があります。

私が言ったように、しかし、ただの予感。

于 2012-01-29T11:31:38.623 に答える