4

私の Web アプリケーションは、Tomcat 6.0.18 と Spring 3.0.5、eclipselink 2.0.1 と javax.persistence 2.0.0、SQL Server データベースを使用しています。構成を理解できず、そのような構成での実際の例を見つけることもできませんでした。loadTimeWeaver のプロパティを entityManagerFacotory に追加しようとしましたが、Spring 3 で AutoWired アノテーションが壊れます。以下の applicationContext.xml のように:

<context:load-time-weaver/>

appname-servlet.xml で:

しかし、LoadTimeWeaver を無効にすると、アプリケーションは JPA コードからデータベースを作成できますが、データをデータベースに永続化できませんでした。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
        <property name="dataSource" ref="dataSource" />         
        <property name="persistenceUnitName" value="restfulPU" />
        <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="true"/>
            <property name="databasePlatform" value="org.eclipse.persistence.platform.database.SQLServerPlatform"/>
        </bean>
        </property>
        <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
        </property>         
        <property name="jpaPropertyMap">
        <props>
            <prop key="eclipselink.weaving">false</prop>
        </props>
        </property>         
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean> 
<tx:annotation-driven transaction-manager="transactionManager"/>
  Persistence.xml
<persistence-unit name="restfulPU" transaction-type="RESOURCE_LOCAL">
    <class>com.generalform.eclipselink.model.Todo</class>
    <properties>
        <!-- EclipseLink should create the database schema automatically -->
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
        <property name="eclipselink.ddl-generation.output-mode"
           value="database" />
    </properties>

Spring 3 と Tomcat への EclipseLink の統合に関するガイドまたはチュートリアルを教えていただければ幸いです。

4

3 に答える 3

5

ありがとう、ジェームズ。

http://static.springsource.org/spring/docs/3.0.0.M4/reference/html/ch13s05.htmlのSpringsource のガイダンスに従って、Tomcat 6 がウィービングに取り組んでいます。ガイダンスに記載され、ここにコピーされた手順:

Step1. spring-tomcat-weaver.jar を $CATALINA_HOME/lib にコピーします。ここで、$CATALINA_HOME は Tomcat インストールのルートを表します)

ステップ2。context.xml を変更して、Tomcat にカスタム クラスローダーを使用するように指示します。

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
        useSystemClassLoaderAsParent="false"/>
</Context>

$CATALINA_HOME/conf/context.xml に入れたので、パスと docBase 属性を指定しませんでした

Step3. LocalContainerEntityManagerFactoryBean の loadTimeWeaver プロパティを有効にする

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
  </property>
</bean> 

その後、Tomcat 6 を再起動すると、起動プロセスがクリーンになります。ただし、データをデータベースに永続化することはできませんでした。エラーは次のようになります。

共有 EntityManager でのトランザクションの作成は許可されていません - 代わりに Spring トランザクションまたは EJB CMT を使用してください

私の同僚は、@Transactional を使用した Spring トランザクション処理と、上記の問題を回避するためにエンティティ マネージャーでトランザクションを使用しないことを指摘して、この時点で私を救ってくれました。次に、em.getTransaction().begin() と em.getTransaction().commit() をコメントアウトして、em.persist(todo) だけを残しました。ここでのエンティティは todo です。すぐに機能します。ここで、開発者は JPA トランザクションと Spring トランザクションの違いに注意する必要があります。実際、EclipseLink/JPA が Spring Transaction Management と連携する場合、これは混乱する部分です。

Tomcat に関係があるのではないかと思っていたので、Tomcat 7 も試してみました。実際、この問題は Tomcat のバージョンとは関係ありません。

LoadTimeWeaver を有効にすると、データの永続性が向上します。applicationname-servlet.xml の transactionManager 構成部分の作業バージョンを次に示します。

   <context:property-placeholder location="classpath:generalform.properties"/>
   <context:component-scan base-package="com.generalform" />

   <tx:annotation-driven transaction-manager="transactionManager"/> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${mysql.database.driver}" />
    <property name="url" value="${mysql.database.url}" />
    <property name="username" value="${mysql.database.user}" />
    <property name="password" value="${mysql.database.password}" />
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
        <property name="dataSource" ref="dataSource" />         
        <property name="persistenceUnitName" value="restfulPU" />
        <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="true"/>
            <property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform"/>
        </bean>
        </property>
        <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
        </property>
        <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" />
        </property>         

</bean> 

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

以下は私の Dao クラスです。正式な方法では、try/catch をメソッド内のコードにラップする必要があります。

@Repository("todoDao")
public class TodoDao {  

    @PersistenceContext
    private EntityManager em;


    public void saveTodo(Todo todo) {

        System.out.println("TodoDao:saveTodo into DB >>>");
        //em.getTransaction().begin();
        em.persist(todo);
        //em.getTransaction().commit();
        em.close();
        System.out.println("TodoDao: complete saveTodo into DB close()>>>");
    }   

}   

TodoService クラスは @Transactional アノテーションを使用して Spring トランザクションを宣言し、LoadTimeWeaver を有効にすると @Autowired も機能します。

@Service("todoService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class TodoService {
    @Autowired
    private TodoDao todoDao;

    public TodoService() {
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    public void saveTodo(Todo todo) {
        System.out.println("TodoService -> saveTodo is called!");
        todoDao.saveTodo(todo);
    }
}   
于 2012-05-03T22:14:25.680 に答える
0

永続化しようとすると、どのようなエラーが発生しますか?

LoadTimeWeaver は機能するはずですが、必須ではありません。代わりに静的織りを使用できます。

于 2012-05-03T14:12:59.597 に答える