在我的 Spring MVC Web 应用程序中尝试调用“persist”方法将实体模型保存到数据库时出现此错误。无法在互联网上真正找到与此特定错误相关的任何帖子或页面。EntityManagerFactory bean 似乎有问题,但我对 Spring 编程还很陌生,所以对我来说,似乎一切都初始化得很好,并且根据 web.xml 中的各种教程文章。
调度程序-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"; } }
我遇到了同样的问题,我将方法注释为@Transactional并且它有效。
@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。扩展的 EntityManager 只应该用在有状态的组件中,例如,驻留在会话中,EntityManager 的生命周期不依赖于当前事务,而是完全取决于应用程序。