我得到这个错误时,试图调用“持久”方法来保存实体模型到数据库在我的Spring MVC web应用程序。在互联网上找不到任何与这个特定错误有关的帖子或页面。似乎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";

        }




    }

当前回答

对于任何与我有相同问题的人,我从另一个类中调用了一个公共方法method1。 然后Method1在同一个类中调用另一个公共方法method2。 method2使用@Transactional注释,但method1没有。 method1所做的就是转换一些参数并直接调用method2,所以这里没有DB操作。

当我将@Transactional注释移到method1时,这个问题就解决了。

不知道原因,但这对我来说很有用。

其他回答

当我试图在spring数据存储库中使用deleteBy自定义方法时,我得到了这个异常。该操作是从JUnit测试类尝试的。

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

只是一个提示给其他用户搜索这个错误的答案。另一个常见的问题是:

通常不能在同一个类中调用@transactional方法。

(有使用AspectJ的方法和方法,但重构会更容易)

因此,您需要一个调用类和一个保存@transactional方法的类。

这就像你在使用共享的EntityManager,当你让它自动连接时,为了持久化spring告诉这个EntityManager bean是一个共享bean,为了持久化它需要持有这个bean,直到数据持久化没有完成,因此我们必须使用@Transactional,这样它就会在事务中启动并提交持久化,这样数据或操作就会完全保存或完全回滚。

我已经有了@Transactional,但仍然不起作用。事实证明,我必须摆脱并行才能使它工作。

如果你在做平行的事情,千万不要。

如果你有

@Transactional // Spring Transactional
class MyDao extends Dao {
}

和父类

class Dao {
    public void save(Entity entity) { getEntityManager().merge(entity); }
}

你打电话给我

@Autowired MyDao myDao;
myDao.save(entity);

你不会得到一个Spring TransactionInterceptor(给你一个事务)。

这是你需要做的:

@Transactional 
class MyDao extends Dao {
    public void save(Entity entity) { super.save(entity); }
}

难以置信,但事实如此。