3

データベースに何かを書き込もうとしていますが、「要求が正常に完了しました」と報告されても機能しません。成功した後、すべてが正常に機能しているように見え、コントローラーが正しくリダイレ​​クトされます。

デバッグ

DEBUG a.d.p.payment.PaymentServiceImpl - Requesting to persist new user'max_test@test.com'.
DEBUG a.d.p.payment.model.PaymentDAOImpl - Persisting com.app.payment.model.PaymentUser@86ceb985.
DEBUG o.s.o.j.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation
DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13771737739
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'redirectForm'
DEBUG o.s.web.servlet.DispatcherServlet - Rendering view [org.springframework.web.servlet.view.JstlView: name 'redirectForm'; URL [/WEB-INF/jsp/redirectForm.jsp]] in DispatcherServlet with name 'payment'
DEBUG o.s.web.servlet.view.JstlView - Forwarding to resource [/WEB-INF/jsp/redirectForm.jsp] in InternalResourceView 'redirectForm'
DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

appContext.xml (ルート コンテキスト)

<context:annotation-config />

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="username" value="test" />
    <property name="password" value="test" />
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <!--payment_test is the name of the schema -->
    <property name="url" value="jdbc:mysql://test1.com:3306/payment_test" /> 
</bean>

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

    <property name="persistenceUnitManager">
        <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
            <property name="defaultDataSource" ref="dataSource" />  
        </bean>
     </property>

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
            <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

        </bean>
    </property>
</bean>

<context:component-scan base-package="com.app.payment" />
<context:annotation-config />

<!-- Auto scan the components -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />

<tx:annotation-driven />

支払いユーザー

@Entity
@Table(name="PaymentUser")
public class PaymentUser {

    @Id
    @GeneratedValue
    private int id;
    ...    
}

支払いサービス

@Transactional("transactionManager")
@Service()
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentDAO paymentDAO;
        // ... service methods
}

支払いDAO

@Repository()
public class PaymentDAOImpl implements PaymentDAO {

    //@PersistenceContext(unitName="payment")
    @PersistenceContext()
    EntityManager em;
}

トランザクションすら開始していないようです。誰かが私を助けるのに十分な情報であることを願っています. 助けてくれてありがとう。

アップデート

データの取得はうまくいきます。永続化 (EntityManager em.persist()) と削除 ( em.remove) が機能していません。正しい問題があるでしょうか。読み取り権のみを意味し、書き込み権はありませんが、この場合、私が考えたエラーがあるはずです。

更新 2

<aop:scoped-proxy />私の dataSource Bean に追加されましたが、変更はありません。私のデバッグメッセージが言ったように

DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress

トランザクションはありませんが、どこからトランザクションを開始すればよいですか?

Spring: Annotation-driven Transaction Manager の問題も確認しまし たが、どうすればよいかわかりません。

新しい appContext

<?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:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- Auto scan the components 
            <bean id="paymentDao" class="com.app.payment.model.PaymentDAOImpl" />
            <bean id="paymentService" class="com.app.payment.PaymentServiceImpl" />
    should do the same      
    -->
    <context:component-scan base-package="com.appn.payment" /> 

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


    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" lazy-init="false" destroy-method="close"> 
        <aop:scoped-proxy />
        <property name="username" value="user" />
        <property name="password" value="pw" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://test1.com:3306/test" />
        <!--  <property name="testOnBorrow" value="true" />
        <property name="validationQuery" value="SELECT 1" />-->
    </bean>

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

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="payment" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
                <property name="defaultDataSource" ref="dataSource" />  
            </bean>
         </property>

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <!-- <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />  -->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

            </bean>
        </property>

        <property name="packagesToScan" value="com.app.payment" /> 
    </bean>

    <tx:annotation-driven />    

</beans>

更新 3

PaymentDAO をフラッシュしようとするem.flush()と、エラー メッセージが表示されます。

javax.persistence.TransactionRequiredException: no transaction is in progress   at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:792)

つまり:

public void flush() {
        if ( !isTransactionInProgress() ) {
            throw new TransactionRequiredException( "no transaction is in progress" );
        }
        try {
            getSession().flush();
        }
        catch ( RuntimeException e ) {
            throw convert( e );
        }
    }

特別なセッションが必要ですか?コントローラーにも記録しました

log.info("Is transaction active " + TransactionSynchronizationManager.isActualTransactionActive());

結果はfalseになります...アクティブなトランザクションがない理由がわかりません...

更新 4

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Repository
public class PaymentDAOImpl implements PaymentDAO {

    private final Logger log = LoggerFactory.getLogger(getClass());


    //@PersistenceContext()
    @PersistenceContext(unitName="payment")
    EntityManager em;

    @Override
    public void persist(PaymentUser user) {
        log.debug("Persisting {}.", user);
        em.persist(user);
        //em.flush();

    }

    @Override
    public void remove(PaymentUser user) {
        log.debug("Removing {}.", user);
        em.remove(user);
    }

    @Override
    public List<PaymentUser> getPaymentUsers() {
        log.debug("Fetching payment users.");
        return em.createQuery("FROM PaymentUser", PaymentUser.class).getResultList();
    }

    @Override
    public PaymentUser getPaymentUserById(String userId) {
        log.debug("Fetching payment users with id '{}'.",userId);
        return em.createQuery(
                "FROM PaymentUser WHERE userId = :userId", PaymentUser.class)
                .setParameter("userId", userId).getSingleResult();
    }

    @Override
    public void removePaymentUserById(String userId) {
        log.debug("Removing payment users with id '{}'.",userId);
        em.createQuery("DELETE FROM PaymentUser WHERE userId = :userId ", PaymentUser.class).
        setParameter("userId", userId).executeUpdate();

    }

    @Override
    public void mergePaymentUser(PaymentUser user) {
        log.debug("Merging payment user '{}'.",user);
        em.merge(user);
    }
}

更新 5

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

     <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

        <!-- springapp servlet -->
    <servlet>
        <servlet-name>payment</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>payment</servlet-name>
          <url-pattern>/payment/*</url-pattern> 
          <url-pattern>/paymentExternalData</url-pattern>
        <url-pattern>/paymentInternalData</url-pattern> 
    </servlet-mapping>

    <!-- Welcome files -->
    <welcome-file-list>
         <welcome-file>payment.jsp</welcome-file>
         <welcome-file>payment.html</welcome-file>
    </welcome-file-list>

    <!-- S P R I N G -->

    <!-- Add Support for Spring -->
    <!-- Default applicationContext location: /WEB-INF/applicationContext.xml -->


    <!-- UTF-8 filter -->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

更新 6

payment-servlet.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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <!-- Auto scan the components -->
    <context:component-scan base-package="com.app.payment" /> 

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

appContext.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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <context:annotation-config />
    <tx:annotation-driven />

    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" lazy-init="false" destroy-method="close"> 
        <aop:scoped-proxy />
        <property name="username" value="test" />
        <property name="password" value="test" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://test1.com/test" />
        <property name="testOnBorrow" value="true" />
        <property name="validationQuery" value="SELECT 1" />
    </bean>

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

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="payment" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" >       
                <property name="defaultDataSource" ref="dataSource" />  
            </bean>
         </property>

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

            </bean>
        </property>
    </bean>

</beans>
4

6 に答える 6

3

<context:component-scan .../>両方の xml 構成に正確に重複する要素がないことを確認してください。これがある場合、基本的にすべての Bean インスタンスを複製しています。あなたが最初に持っていたのは、すべての Bean が によってロードされ、ContextLoaderListenerそれらが の存在によりプロキシされるということでし<tx:annotation-driven />た。

<context:component-scan .../>payment-servlet.xml に同じものがある場合、別のインスタンスを作成するすべての Bean を再度スキャンしますが、存在<tx:annotation-driven />しないため、プロキシされず、トランザクションは適用されません。

@Serviceここで何が起こるかというと、注釈付きの Bean の1 つが必要になるとすぐに、ニーズを満たす Bean があるかどうかを確認するためにDispatcherServlet、最初にそれ自体が検索されます。ApplicationContext存在する場合は使用されます(現在のケース)。存在しない場合は、親コンテキスト(によってロードされたものContextLoaderListener)を参照します。

あなたがする必要があるのは、注釈付きの Bean 以外のすべてをスキャンするように を構成し、注釈付きContextLoaderListenerのBeanのみをスキャンするように構成することです。これは、正しく構成することで実行できます。 @ControllerDispatcherServlet@Controller<context:component-scan .../>

applicationContext.xml

<context:component-scan base-package="com.appn.payment">
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

payment-servlet.xml

<context:component-scan base-package="com.appn.payment" use-default-filters="false">
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

これにより、トランザクションと Bean の単一インスタンスのみが提供されます。<tx:annotation-driven />payment-servlet.xml ファイルからを削除する必要があります。

これをリファレンス ガイドに含めるには、未解決のJIRA の問題がまだあります。これを説明するSpring Community Forumsのスレッドもあります。

于 2013-08-27T08:57:35.290 に答える
2

applicationContext.xml をもう一度見てみると、transactionManager 宣言で entityManager を割り当てていないことに気付きました。Spring が暗黙的に設定するかどうかはわかりませんが、そうでない場合は、永続化が機能しない理由を説明できます。

たとえば、次のように変更します。

<bean id="transactionManager" 
   class="org.springframework.orm.jpa.JpaTransactionManager" />

to

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

アップデート

私はSpring + JPAをコンテナ管理のエンティティでのみ構成しました(あなたの意図のようにも見えます)-実際にはアプリケーション管理ではありません。私の知る限り、Spring を使用したコンテナー管理では、Persistent Unit を構成する必要は実際にはありません。これが役立つかどうかは 100% わかりませんが、applicationContext.xml での entityManagerFactory の宣言方法を変更してみてください。

<bean id="entityManagerFactory"
   class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

   <property name="dataSource" ref="dataSource" />

   <property name="packagesToScan" value="com.app.payment" />   

   <property name="persistenceProvider">
      <bean class="org.hibernate.ejb.HibernatePersistence" />
   </property>

   <property name="jpaProperties">
      <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
         <prop key="hiberate.show_sql">true</prop>
         ... //additional props
      </props> 
   </property>
</bean>
于 2013-08-22T15:06:03.183 に答える
1

アノテーション駆動のトランザクションを使用する場合@Transactional、データベースを操作するメソッドの前にアノテーションを配置する必要があります。これは、DAO メソッドまたはサービス メソッドのいずれかです。@Transactionalあなたが上に置いたことがわかりますがPaymentServiceImpl、それはその注釈の適切な場所ではありません.

于 2013-08-27T07:06:59.273 に答える
0

問題を見つけることができました。 Spring Docu「@EnableTransactionManagement であり、Bean が定義されているのと同じアプリケーション コンテキスト内の Bean で @Transactional のみを検索します。」私の payment-servlet.xml の意味は、<tx:annotation-driven />アクティブなトランザクションがなかった理由がありませんでした。

于 2013-08-27T08:39:39.763 に答える