当尝试调用“ persist”方法将实体模型保存到Spring MVC Web应用程序中的数据库时,出现此错误。在Internet上找不到与该特定错误相关的任何帖子或页面。似乎似乎EntityManagerFactory bean出了点问题,但是我对Spring编程还是比较陌生,所以对我来说,似乎一切都已初始化好,并且根据Web上的各种教程文章。
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并且该方法有效。
@Transactional
更新:检查spring文档,默认情况下PersistenceContext看起来是Transaction类型,因此这就是为什么该方法必须是事务性的(http://docs.spring.io/spring/docs/current/spring-framework-reference/ html / orm.html):
@PersistenceContext批注具有可选的属性类型,默认为PersistenceContextType.TRANSACTION。此默认设置是你需要接收共享的EntityManager代理的条件。替代方案PersistenceContextType.EXTENDED是完全不同的事情:这导致所谓的扩展EntityManager,它不是线程安全的,因此不能在并发访问的组件(例如Spring管理的Singleton bean)中使用。扩展的EntityManager仅应用于有状态的组件(例如,驻留在会话中),并且EntityManager的生命周期不依赖于当前事务,而完全取决于应用程序。