错误:当前线程中的JPA + MySQL事务处于非活动状态

时间:2015-08-11 15:23:28

标签: java mysql multithreading jpa glassfish-4

早上好,当我运行我的应用程序时,我收到以下错误:

java.lang.IllegalStateException: Transaction is not active in the current thread.
at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.validateTransactionManager(JavaEETransactionManagerJTSDelegate.java:447)
at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:164)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:859)
at com.sun.enterprise.transaction.UserTransactionImpl.commit(UserTransactionImpl.java:212)
at com.surebetfinder.logic.GestoreScommesse.creaScriveEvento(GestoreScommesse.java:100)
at com.surebetfinder.logic.GestoreScommesse.lavoraScommessa(GestoreScommesse.java:63)
at com.surebetfinder.logic.GestoreScommesse.memorizzaGiocate(GestoreScommesse.java:56)
at sun.reflect.GeneratedMethodAccessor394.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:46)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
at sun.reflect.GeneratedMethodAccessor55.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy297.memorizzaGiocate(Unknown Source)
at com.surebetfinder.logic.__EJB31_Generated__GestoreScommesse__Intf____Bean__.memorizzaGiocate(Unknown Source)
at com.surebetfinder.logic.processi.WorkerThread.processCommand(WorkerThread.java:43)
at com.surebetfinder.logic.processi.WorkerThread.run(WorkerThread.java:33)
at sun.reflect.GeneratedMethodAccessor392.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
at sun.reflect.GeneratedMethodAccessor55.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
at com.sun.ejb.containers.EjbAsyncTask.call(EjbAsyncTask.java:101)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

我的设置如下。如。多线程环境中的GlassFish 4.1,MySQL DB,Java 1.7,JPA(BMT + datasourse JTA)

的persistence.xml

<persistence 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 persistence_1_0.xsd"
version="1.0">
<persistence-unit name="surebet-unit" transaction-type="JTA">
<jta-data-source>surebetDB</jta-data-source>
<class>com.surebetfinder.dao.ejb.Evento</class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/surebetdb" />
        <property name="javax.persistence.jdbc.user" value="" />
        <property name="javax.persistence.jdbc.password" value="" />
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="eclipselink.logging.level" value="ALL" />

    </properties>
</persistence-unit>

这是我的业务功能,它由异步bean

调用
@Stateless
@TransactionManagement(value = TransactionManagementType.BEAN)
public class GestoreScommesse {
    private final static Logger log = Logger.getLogger(GestoreScommesse.class);

    @Resource
    private UserTransaction userTransaction;

    @EJB
    private SurebetService service;

private Evento creaScriveEvento(EventoMod e) throws SureBetException {
    log.debug("Cerco sul DB evento con ID " + e.getIdEvento());
    try {
        this.userTransaction.begin();
        Evento evento = null;
        List<Evento> eV = this.service.findByNativeQuery("SELECT * FROM evento WHERE ID_EVENTO = " + e.getIdEvento() + "  LOCK IN SHARE MODE", Evento.class);
        if (eV == null || eV.size() == 0) {
            log.debug("Evento non presente sul DB con ID " + e.getIdEvento());
            evento = impostaEvento(e);
            this.service.create(evento);
            log.debug("Creato nuovo evento su " + e.getIdEvento());
            this.userTransaction.commit();

        } else {
            log.debug("Evento già presente con id " + e.getIdEvento());
            evento = eV.get(0);
        }
        this.userTransaction.commit();
        return evento;
    } catch (RuntimeException | NotSupportedException | SystemException | RollbackException
            | HeuristicMixedException | HeuristicRollbackException e1) {
        try {
            log.error("Errore nella scrittura dell'evento ", e1);
            userTransaction.rollback();
            throw new SureBetException(e1);
        } catch (IllegalStateException | SecurityException | SystemException e2) {
            log.error("Impossibile eseguire rollback sulla transazione ", e2);
            throw new SureBetException(e2);
        }
    }
}

来电者:

@Stateless
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class WorkerThread {

    private final Logger log = Logger.getLogger(WorkerThread.class);

    @EJB
    private GestoreScommesse gestore;

    @Asynchronous
    public void run(Risorsa bookmaker) throws SureBetException {
       log.debug("Eseguo esplorazione del bookmaker " + bookmaker.toString());
       gestore.creaScriveEvento(e);
       log.trace("Esplorazione terminata");
    }
}

虽然这是DAO:

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)

public class SurebetService {

    @PersistenceContext
    EntityManager em;

    public <T> T create(T t) {
        this.em.persist(t);
        this.em.flush();
        this.em.refresh(t);
        return t;
    }

    public void refresh(Class<?> type){
        this.em.refresh(type);
    }

    public <T> T find(Class<T> type, Object id) {
        this.em.flush();
        return (T) this.em.find(type, id);
    }

    public void delete(Class<?> type, Object id) {
        Object ref = this.em.getReference(type, id);
        this.em.remove(ref);
    }

    public <T> T update(T t) {
        return (T) this.em.merge(t);
    }

    @SuppressWarnings("rawtypes")
    public List findWithNamedQuery(String namedQueryName){
    return this.em.createNamedQuery(namedQueryName).getResultList();
    }
    @SuppressWarnings("rawtypes")
    public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters) {
        return findWithNamedQuery(namedQueryName, parameters, 0);
    }

    @SuppressWarnings("rawtypes")
    public List findWithNamedQuery(String queryName, int resultLimit) {
        return this.em.createNamedQuery(queryName).setMaxResults(resultLimit).getResultList();
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> findByNativeQuery(String sql, Class<T> type) {
        return this.em.createNativeQuery(sql, type).getResultList();
    }

    @SuppressWarnings("rawtypes")
    public List findWithNamedQuery(String namedQueryName, Map<String, Object> parameters, int resultLimit) {
        Set<Entry<String, Object>> rawParameters = parameters.entrySet();
        Query query = this.em.createNamedQuery(namedQueryName);
        if (resultLimit > 0)
            query.setMaxResults(resultLimit);
        for (Entry<String, Object> entry : rawParameters) {
            query.setParameter(entry.getKey(), entry.getValue());
        }
        return query.getResultList();
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }


}

错误不系统。有些想法?谢谢

1 个答案:

答案 0 :(得分:0)

我将从堆栈跟踪开始:

  

在   com.surebetfinder.logic.GestoreScommesse.creaScriveEvento(GestoreScommesse.java:100)

我的猜测是,if块之外的第二次调用userTransaction.commit失败,因为事务已经提交。

您可以重构代码以提交单点,或者在使用userTransaction.getStatus方法提交之前进行检查。