Spring-현재 스레드에 사용 가능한 실제 트랜잭션이있는 EntityManager가 없음- ‘persist’호출을 안정적으로 처리 할 수 ​​없음 http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/data/jpa

Spring MVC 웹 애플리케이션에서 엔티티 모델을 데이터베이스에 저장하기 위해 “persist”메소드를 호출하려고 할 때이 오류가 발생합니다. 인터넷 에서이 특정 오류와 관련된 게시물이나 페이지를 실제로 찾을 수 없습니다. 그것은 EntityManagerFactory bean에 문제가있는 것처럼 보이지만 Spring 프로그래밍에 익숙하지 않기 때문에 모든 것이 잘 초기화되어 있고 웹의 다양한 자습서 기사에 따라 보입니다.

dispatcher-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:mvc="http://www.springframework.org/schema/mvc"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
 http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/jdbc
  http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
  http://www.springframework.org/schema/data/jpa
  http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
  http://www.springframework.org/schema/data/repository
  http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
  http://www.springframework.org/schema/jee
  http://www.springframework.org/schema/jee/spring-jee-3.2.xsd">

    <context:component-scan base-package="wymysl.Controllers" />
    <jpa:repositories base-package="wymysl.repositories"/>
    <context:component-scan base-package="wymysl.beans" />
    <context:component-scan base-package="wymysl.Validators" />
    <bean
     class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
     <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>

     <bean id="passwordValidator" class="wymysl.Validators.PasswordValidator"></bean>

     <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="system" />
        <property name="password" value="polskabieda1" />
    </bean>

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml" />
    <property name="dataSource" ref="dataSource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
            <property name="showSql" value="true" />
            <property name="generateDdl" value="false" />
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">10</prop>
        </props>
    </property>
</bean>

    <mvc:annotation-driven />

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
</bean>

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


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

    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/resources/*" location="/resources/css/"
    cache-period="31556926"/>



</beans>

RegisterController.java

@Controller
public class RegisterController {

    @PersistenceContext
    EntityManager entityManager;

    @Autowired
    PasswordValidator passwordValidator;

    @InitBinder
    private void initBinder(WebDataBinder binder) {
        binder.setValidator(passwordValidator);
    }

    @RequestMapping(value = "/addUser", method = RequestMethod.GET)
    public String register(Person person) {


        return "register";

    }

    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String register(@ModelAttribute("person") @Valid @Validated Person person, BindingResult result) {
        if(result.hasErrors()) {
            return "register";
        } else {
            entityManager.persist(person);
            return "index";

        }




    }


답변

나는 같은 문제가 있었고 그 방법에 주석을 달았고 @Transactional효과가있었습니다.

업데이트 : 기본적으로 PersistenceContext가 보이는 Spring 문서를 확인하는 것은 Transaction 유형이므로 메소드는 트랜잭션이어야합니다 ( http://docs.spring.io/spring/docs/current/spring-framework-reference/ html / orm.html ) :

@PersistenceContext 어노테이션에는 선택적 속성 유형이 있으며 기본값은 PersistenceContextType.TRANSACTION입니다. 이 기본값은 공유 EntityManager 프록시를 수신하는 데 필요한 것입니다. 대안 인 PersistenceContextType.EXTENDED는 완전히 다른 일입니다. 이로 인해 소위 확장 된 EntityManager가 생성되며 이는 스레드 안전이 아니므로 스프링 관리 싱글 톤 Bean과 같이 동시에 액세스되는 컴포넌트에서 사용해서는 안됩니다. 확장 된 EntityManager는 예를 들어 세션에 상주하는 상태 저장 구성 요소에서만 사용되어야합니다. EntityManager의 수명주기는 현재 트랜잭션에 연결되어 있지 않고 애플리케이션에 전적으로 달려 있습니다.


답변

스프링 데이터 저장소에서 deleteBy 사용자 정의 메소드를 사용하려고 시도하는 중에이 예외가 발생했습니다. JUnit 테스트 클래스에서 조작을 시도했습니다.

@TransactionalJUnit 클래스 레벨에서 주석을 사용할 때는 예외가 발생하지 않습니다 .


답변

이 오류로 인해 3 일 동안 여우가 나타 났으며, 내가 직면 한 상황에서도 같은 오류가 발생했습니다. 내가 찾은 모든 조언에 따라 구성을 가지고 놀았지만 아무 소용이 없었습니다.

결국 나는 그것이 실행중인 서비스가 일반적인 jar에 포함되어 있다는 차이점을 발견했습니다. 문제는 AspectJ가 서비스 인스턴스화를 동일하게 취급하지 않는 것으로 나타났습니다. 사실상 프록시는 단순히 메소드 호출 전에 모든 일반적인 Spring 매직이 실행되지 않고 기본 메소드를 호출하는 것입니다.

결국 예제에 따라 서비스에 배치 된 @Scope 주석이 문제를 해결했습니다.

@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
@Transactional
public class CoreServiceImpl implements CoreService {
    @PersistenceContext
    protected EntityManager entityManager;

    @Override
    public final <T extends AbstractEntity> int deleteAll(Class<T> clazz) {
        CriteriaDelete<T> criteriaDelete = entityManager.getCriteriaBuilder().createCriteriaDelete(clazz);
        criteriaDelete.from(clazz);
        return entityManager.createQuery(criteriaDelete).executeUpdate();
    }

}

내가 게시 한 방법은 삭제 방법이지만 주석은 동일한 방식으로 모든 지속성 방법에 영향을 미칩니다.

이 게시물이 항아리에서 서비스를로드 할 때 같은 문제로 어려움을 겪은 다른 사람에게 도움이되기를 바랍니다.


답변

XML에서 Java 구성으로 전환했기 때문에 동일한 오류가 발생했습니다.

요점은 <tx:annotation-driven/>Stone Feng이 제안한 것처럼 태그를 마이그레이션하지 않았다는 것 입니다.

그래서 방금 @Configuration Class에서 Spring에 주석 구동 트랜잭션 설정하기@EnableTransactionManagement 에서 제안한대로
추가 했습니다.


답변

boardRepo.deleteByBoardId (id);

같은 문제에 직면했다. GOT javax.persistence.TransactionRequiredException : 현재 스레드에 사용 가능한 실제 트랜잭션이있는 EntityManager가 없음

컨트롤러 / 서비스 위에 @Transactional 주석 을 추가하여 해결했습니다 .


답변

저도 같은 문제를 겪고 난 추가 tx:annotation-drivenapplicationContext.xml그것은했다.


답변

동일한 구성 요소 내에서 비 ​​트랜잭션 방식으로 이미 트랜잭션이 주석 처리 된 메소드에 액세스 할 때 동일한 오류가 발생했습니다.

Before:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          executeQuery(); //<-- Wrong
        }
    }

    //In another bean:
     marketObserver.startObserving();

자체 참조 구성 요소에서 executeQuery ()를 호출하여 오류를 수정했습니다.

Fixed version:
    @Component
    public class MarketObserver {
        @PersistenceContext(unitName = "maindb")
        private EntityManager em;

        @Autowired
        private GenericApplicationContext context;

        @Transactional(value = "txMain", propagation = Propagation.REQUIRES_NEW)
        public void executeQuery() {
          em.persist(....);
        }


        @Async
        public void startObserving() {
          context.getBean(MarketObserver.class).executeQuery(); //<-- Works
        }
    }