Spring - 没有可用于当前线程的具有实际事务的 EntityManager - 无法可靠地处理“持久”调用

新手上路,请多包涵

在我的 Spring MVC Web 应用程序中尝试调用“持久化”方法将实体模型保存到数据库时出现此错误。无法真正在互联网上找到与此特定错误相关的任何帖子或页面。 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>

注册控制器.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";

        }

    }

原文由 Michał Bil 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 560
2 个回答

我遇到了同样的问题,我将该方法注释为 @Transactional 并且它有效。

更新:检查 spring 文档,默认情况下 PersistenceContext 是事务类型,所以这就是为什么该方法必须是事务性的( http://docs.spring.io/spring/docs/current/spring-framework-reference/ html/orm.html ):

@PersistenceContext 注解有一个可选的属性类型,默认为 PersistenceContextType.TRANSACTION。此默认值是接收共享 EntityManager 代理所需的。替代方案 PersistenceContextType.EXTENDED 是完全不同的事情:这导致所谓的扩展 EntityManager,它不是线程安全的,因此不得在并发访问的组件(如 Spring 管理的单例 bean)中使用。 Extended EntityManager 只应该用在有状态的组件中,例如,驻留在会话中,EntityManager 的生命周期不依赖于当前事务,而是完全取决于应用程序。

原文由 mlg 发布,翻译遵循 CC BY-SA 3.0 许可协议

尝试在 spring 数据存储库中使用 deleteBy 自定义方法时出现此异常。该操作是从 JUnit 测试类中尝试的。

在 JUnit 类级别使用 @Transactional 注释时不会发生异常。

原文由 Kishore Guruswamy 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题