本文介绍了Spring + Eclipselink + JtaTransactionManager = javax.persistence.TransactionRequiredException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的希望你能帮助我.我一直在互联网上寻找答案,但都无济于事.

I really hope you can help me. I've been looking all over the internet for answers and none of them works.

我使用Spring 3 + JTA + EclipseLink,但在刷新事务时遇到了TransactionRequiredException.现在,我已经非常习惯于定义我的持久性上下文并注入EntityManager,并且事务由应用服务器处理.

I use Spring 3 + JTA + EclipseLink but i'm getting a TransactionRequiredException when flushing a transaction. Now i'm very used to just defining my persistence context and injecting the EntityManager and the transaction is handled by the app server.

这就是我所拥有的.

persistence.xml

persistence.xml

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="CartouchanPU" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>java:app/jdbc/CartouchanDS</jta-data-source>
        <class>com.cartouchan.locator.database.models.Authority</class>
        <class>com.cartouchan.locator.database.models.AuthorityPK</class>
        <class>com.cartouchan.locator.database.models.User</class>
        <class>com.cartouchan.locator.database.models.UserPK</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="eclipselink.ddl-generation" value="none"/>
            <property name="eclipselink.target-database" value="MySQL"/>
            <property name="eclipselink.jdbc.native-sql" value="true"/>
            <property name="eclipselink.jdbc.cache-statements" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

spring-config.xml

spring-config.xml

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<jee:jndi-lookup jndi-name="java:app/jdbc/CartouchanDS" id="CartouchanDS" />

  <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="autodetectUserTransaction" value="true" />
    <property name="autodetectTransactionManager" value="true" />
    <property name="transactionManagerName" value="java:appserver/TransactionManager"/>
</bean>

<context:annotation-config />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="CartouchanPU" />
    <property name="persistenceUnitManager">
        <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"/>
    </property>
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
    </property>
</bean>

CreateAccount.class

CreateAccount.class

import java.text.MessageFormat;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class CreateAccount implements Controller {
    private static final Logger logger = Logger.getLogger(CreateAccount.class);

    //    @Autowired
    //    private JtaTransactionManager transactionManager;

    @PersistenceContext
    private EntityManager       entityManager;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info(MessageFormat.format("Called handle request", ""));
        String username = ServletRequestUtils.getRequiredStringParameter(request, "username");
        logger.info(MessageFormat.format("username {0}", username));
        String password = ServletRequestUtils.getRequiredStringParameter(request, "password");
        logger.info(MessageFormat.format("password {0}", password));
        String passwordConfirm = ServletRequestUtils.getRequiredStringParameter(request, "passwordConfirm");
        logger.info(MessageFormat.format("passwordConfirm {0}", passwordConfirm));

        if (!password.equals(passwordConfirm)) {
            throw new ServletRequestBindingException("Passwords don't match");
        }

        //transactionManager.getUserTransaction().begin();
        User user = new User();
        //try {
        UserPK userPK = new UserPK();
        userPK.setUsername(username);
        user.setId(userPK);
        user.setPassword(passwordConfirm);
        user.setEnabled((byte) 1);

        logger.info(MessageFormat.format("persist the user {0}", username));
        entityManager.persist(user);
        entityManager.flush();
        //        logger.info(MessageFormat.format("Before Refresh user {0}", username));
        //        entityManager.refresh(user);
        //            transactionManager.getUserTransaction().commit();
        //        } catch (Exception e) {
        //            logger.error(MessageFormat.format("Got an exception {0}", e.getMessage()), e);
        //            transactionManager.getUserTransaction().rollback();
        //        }

        //        transactionManager.getUserTransaction().begin();

        //        AuthorityPK authorityPK = new AuthorityPK();
        //        //try {
        //        logger.info(MessageFormat.format("Refreshed user {0} = {1}", username, user.getId()));
        //
        //        authorityPK.setUserId(user.getId().getId());
        //        authorityPK.setAuthority(com.cartouchan.locator.models.Authority.ROLE_USER.toString());
        //        Authority authority = new Authority();
        //        authority.setId(authorityPK);
        //
        //        logger.info(MessageFormat.format("Save the authority {0}", com.cartouchan.locator.models.Authority.ROLE_USER.toString()));
        //        entityManager.persist(authority);

        //            transactionManager.getUserTransaction().commit();
        //        } catch (Exception e) {
        //            logger.error(MessageFormat.format("Got an exception {0}", e.getMessage()), e);
        //            transactionManager.getUserTransaction().rollback();
        //        }

        logger.info(MessageFormat.format("Go to /index.zul", ""));
        ModelAndView modelAndView = new ModelAndView("index");

        logger.info(MessageFormat.format("Return ", ""));
        return modelAndView;
    }
}

这就是问题,当我取消注释transactionManager部分时,程序将按预期运行,这是我可以看到插入语句的地方.但是,当使用上面的代码时,我得到以下stacktrace:

So here's the deal, when I uncomment the transactionManager parts, the program operates as expected, which is I can see the insert statements. However, when using the above code, I get the following stacktrace :

INFO: Starting ZK 5.0.7.1 CE (build: 2011051910)
INFO: Parsing jndi:/server/Cartouchan/WEB-INF/zk.xml
INFO: WEB0671: Loading application [Cartouchan-Web] at [/Cartouchan]
INFO: Cartouchan-Web was successfully deployed in 1,537 milliseconds.

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] Called handle request

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] username blah

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] password test

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] passwordConfirm test

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] persist the user blah

INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913
CONFIG: connecting(DatabaseLogin(
    platform=>MySQLPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:mysql://localhost:3306/Cartouchan
    User: root@localhost
    Database: MySQL  Version: 5.1.51
    Driver: MySQL-AB JDBC Driver  Version: mysql-connector-java-5.1.11 ( Revision: ${svn.Revision} )
CONFIG: connecting(DatabaseLogin(
    platform=>MySQLPlatform
    user name=> ""
    connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:mysql://localhost:3306/Cartouchan
    User: root@localhost
    Database: MySQL  Version: 5.1.51
    Driver: MySQL-AB JDBC Driver  Version: mysql-connector-java-5.1.11 ( Revision: ${svn.Revision} )
INFO: file:/Applications/NetBeans/glassfish-3.1/glassfish/domains/domain1/eclipseApps/Cartouchan-Web/WEB-INF/classes/_CartouchanPU login successful
WARNING: StandardWrapperValve[cartouchan]: PWC1406: Servlet.service() for servlet cartouchan threw exception
javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently active for this thread
    at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:86)
    at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.checkForTransaction(JTATransactionWrapper.java:46)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1666)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:744)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at $Proxy151.flush(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy151.flush(Unknown Source)
    at com.cartouchan.locator.controllers.CreateAccount.handleRequest(CreateAccount.java:56)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:680)

因此,如您所见,它可以正确连接到数据库,并且可以持久化"数据,但是从不实际执行insert语句.然后在刷新EM时,它将引发异常.

So as you can see, it connects correctly to the database, and it "persists" the data, but never actually execute the insert statement. Then when flushing the EM, it throws the exception.

我们将非常感谢您的帮助.

Your help will be greatly appreciated.

最好的问候.

推荐答案

好,所以我想出了如何使它100%工作的方法.

Ok, so I figured out how to get this working 100%.

首先,我不必在web.xml中定义任何持久性(上下文/单元).接下来,我删除了transactionmanager和EntityManagerFactory bean.还删除了context:driven行.我还制作了"beans"无状态会话bean.然后,我会在春季通过jndi上下文查找实例化它.这完全按照我想要的方式自动连接了entitymanager.无需担心交易,应用服务器即可处理.

First of all, I don't have to define any persistence(context/unit) in web.xml. Next I removed the transactionmanager and the entityManagerFactory beans. Also removed the context:driven line.I also made my "beans" Stateless session beans. I then instantiate it through spring through jndi context lookups. This autowires the entitymanager exactly as i want it. No more worrying about transactions, the app server handles that.

所以我的最终配置是:

spring-config.xml:

spring-config.xml :

<jee:jndi-lookup jndi-name="java:global/Cartouchan-Web/CategoryController" id="categoryController"/>
<jee:jndi-lookup jndi-name="java:global/Cartouchan-Web/UserController" id="userController"/>

<bean id="applicationContextProvider" class="com.cartouchan.locator.beans.CustomApplicationContext"></bean>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

豆样品:

import java.text.MessageFormat;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;

@Stateless
public class CategoryController {
    private static final Logger logger = Logger.getLogger(CategoryController.class);

    @PersistenceContext
    private EntityManager       entityManager;

    public CategoryController() {
        // TODO Auto-generated constructor stub
    }

    public boolean createCategory(final String name) {
        boolean result = false;
        try {
            com.cartouchan.locator.database.models.Category category = new com.cartouchan.locator.database.models.Category();
            category.setName(name);
            entityManager.persist(category);
            entityManager.flush();
            result = true;
        } catch (Exception ex) {
            logger.error(MessageFormat.format("Could not create the category {0}", name), ex);
        }

        return result;
    }

    public boolean updateCategory(final int id, final String name) {
        boolean result = false;
        try {
            com.cartouchan.locator.database.models.Category category = getCategory(id);
            category.setName(name);
            entityManager.merge(category);
            entityManager.flush();
            result = true;
        } catch (Exception ex) {
            logger.error(MessageFormat.format("Could not update for the category {0} -{1}", id, name), ex);
        }

    return result;
    }

    public boolean deleteCategory(final int id) {
        boolean result = false;
        try {
            com.cartouchan.locator.database.models.Category category = getCategory(id);
            entityManager.remove(entityManager.merge(category));
            entityManager.flush();
            result = true;
        } catch (Exception ex) {
            logger.error(MessageFormat.format("Could not delete for the category {0}", id), ex);
        }

        return result;
    }

    public com.cartouchan.locator.database.models.Category getCategory(final int id) {
        return (com.cartouchan.locator.database.models.Category) entityManager.createQuery("select p from Category p where p.id=:id").setParameter("id", id).getSingleResult();
    }

    public List<com.cartouchan.locator.database.models.Category> getAllCategories() {
        return (List<com.cartouchan.locator.database.models.Category>) entityManager.createQuery("select p from Category p").getResultList();
    }
}

然后使用Bean,只需对Bean进行标准的Spring查找即可.像馅饼一样简单.

Then to use the bean, just do a standard spring lookup of the bean. Easy as pie.

这篇关于Spring + Eclipselink + JtaTransactionManager = javax.persistence.TransactionRequiredException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 07:03
查看更多