복붙노트

[SPRING] Spring 애플리케이션이 데이터를 지속하지 않는 것으로 보입니다.

SPRING

Spring 애플리케이션이 데이터를 지속하지 않는 것으로 보입니다.

내 데이터베이스에 무언가를 쓰려고하는데 "성공한 요청을 완료했습니다."라는보고에도 불구하고 작동하지 않습니다. 성공 후 모든 게 잘 작동하고 내 컨트롤러가 올바르게 리디렉션됩니다.

디버그

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 />

PaymentUser

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

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

PaymentService

@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

내 dataSource 빈에 를 추가했지만 변경 사항이 없습니다. 내 디버그 메시지처럼

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());

틀린 결과는 ... 확실한 이유가 없습니다. 활성 트랜잭션이 없습니다 ...

업데이트 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>

해결법

  1. ==============================

    1.두 xml 구성에서 정확히 중복되는 요소가 없는지 확인하십시오. 이 경우 기본적으로 모든 빈 인스턴스를 복제합니다. 처음에는 콩이 ContextLoaderListener에 의해로드되고 가 있기 때문에 프록시가로드됩니다.

    두 xml 구성에서 정확히 중복되는 요소가 없는지 확인하십시오. 이 경우 기본적으로 모든 빈 인스턴스를 복제합니다. 처음에는 콩이 ContextLoaderListener에 의해로드되고 가 있기 때문에 프록시가로드됩니다.

    이제 payment-servlet.xml에 동일한 이 있으면 다른 인스턴스를 만드는 모든 bean에 대해 다시 스캔 할 것입니다. 그러나 은 프록시 화되지 않고 트랜잭션이 적용되지 않습니다.

    이제는 @Service 주석이 달린 bean 중 하나가 필요하면 DispatcherServlet은 자신의 ApplicationContext를 먼저 살펴보고 요구를 만족시키는 bean이 있는지 확인합니다. 존재하지 않는 경우 (현재 사례) 부모 컨텍스트 (ContextLoaderListener에 의해로드 된 컨텍스트)를 참조합니다.

    당신이해야 할 일은 ContextLoaderListener를 설정하여 @Controller 주석이 달린 bean과 @Controller annotated beans에 대해서만 DispatcherServlet을 검사하는 것입니다. 이 작업은 을 올바르게 구성하여 수행 할 수 있습니다.

    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>
    

    이렇게하면 트랜잭션과 단 하나의 빈 인스턴스 만 제공됩니다. payment-servlet.xml 파일에서 를 제거해야합니다.

    JIRA의 오픈 이슈는 여전히 참고서에 포함되어 있습니다. 또한 이것을 설명하는 Spring Community Forums의 스레드.

  2. ==============================

    2.applicationContext.xml을 다시 살펴보면, entityManager에 transactionManager 선언을 할당하지 않는 것으로 나타났습니다. 나는 Spring이 암시 적으로 그것을 설정할 것인지 확신하지 못한다. 그러나 그렇지 않다면 당신의 지속자가 왜 작동하지 않는지를 설명 할 것이다.

    applicationContext.xml을 다시 살펴보면, entityManager에 transactionManager 선언을 할당하지 않는 것으로 나타났습니다. 나는 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 만 구성했습니다. 실제로 응용 프로그램 관리는 없습니다. 내가 아는 바로는 Container-managed with Spring에서 Persistent Unit을 구성 할 필요가 없다. 나는 이것이 도움이되지만 applicationContext.xml에서 entityManagerFactory가 선언되는 방법을 변경하려고 시도한다면 100 % 확실하지 않다.

    <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>
    
  3. ==============================

    3.어노테이션 기반 트랜잭션을 사용할 때는 @Transactional 어노테이션을 데이터베이스로 작업하는 메소드 앞에 두어야합니다. DAO 또는 서비스 방법 일 수 있습니다. PaymentServiceImpl 위에 @Transactional을 넣었 음을 알 수 있지만 그 주석에 적합한 위치는 아닙니다.

    어노테이션 기반 트랜잭션을 사용할 때는 @Transactional 어노테이션을 데이터베이스로 작업하는 메소드 앞에 두어야합니다. DAO 또는 서비스 방법 일 수 있습니다. PaymentServiceImpl 위에 @Transactional을 넣었 음을 알 수 있지만 그 주석에 적합한 위치는 아닙니다.

  4. ==============================

    4.DAO 구현 클래스의 시작 부분에서 @Transactional 주석을 놓친 것 같습니다. 그것은 왜 어떤 거래가 열리지 않았는지를 설명합니다.

    DAO 구현 클래스의 시작 부분에서 @Transactional 주석을 놓친 것 같습니다. 그것은 왜 어떤 거래가 열리지 않았는지를 설명합니다.

    문제를 해결하기에 충분하지 않은 경우 완전한 DAO 구현 클래스를 제공 할 수 있습니까?

  5. ==============================

    5.그 문제를 발견 할 수 있었다. Spring Docu "@EnableTransactionManagement에서 정의 된 동일한 응용 프로그램 컨텍스트의 Bean에 대해서만 @Transactional을 찾습니다." 내 payment-servlet.xml의 Meaing에는 활성 트랜잭션이없는 이유가 없었습니다.

    그 문제를 발견 할 수 있었다. Spring Docu "@EnableTransactionManagement에서 정의 된 동일한 응용 프로그램 컨텍스트의 Bean에 대해서만 @Transactional을 찾습니다." 내 payment-servlet.xml의 Meaing에는 활성 트랜잭션이없는 이유가 없었습니다.

  6. ==============================

    6.transactionManager bean을 생성 한 후에는 XML 파일에서 트랜잭션을 활성화해야하며,

    transactionManager bean을 생성 한 후에는 XML 파일에서 트랜잭션을 활성화해야하며,

    또는

    만약 당신이 DAO 클래스에서 @Transaction ()을 써야만한다면,

    어떤 메소드가 트랜잭션을 필요로한다면 그 write 전에

    @ 트랜잭션 (propagation = 전파 .REQUIRED, 읽기 전용 = 거짓)

    트랜잭션이 필요하고 readOnly = false는 데이터를 읽고 쓸 수 있음을 의미합니다.

  7. from https://stackoverflow.com/questions/18380595/spring-application-doesnt-appear-to-be-persisting-data by cc-by-sa and MIT license