代码之家  ›  专栏  ›  技术社区  ›  Mitch Talmadge

未捕获NonUniqueResultException[duplicate]

  •  1
  • Mitch Talmadge  · 技术社区  · 8 年前

    我很难赶上 NonUniqueResultException 从我的一颗豆子的方法。

    这是方法。它位于 @Stateful

    public Field findByTitle(String title) {
        if (title == null)
            return null;
    
        try {
            return entityManager
                    .createQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class)
                    .setParameter(1, title)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        } 
    }
    

    简单地说,我想抓住未经检查的 非唯一结果异常 来自另一个调用此方法的bean。

    下面是调用bean的try/catch:

    try {
        Field field = fieldService.findByTitle(title);
    } catch (NonUniqueResultException e) {
        LogManager.logError("Oh no!");
    }
    

    我的期望是“哦,不!”将打印到控制台。相反 非唯一结果异常 已打印。接听电话从未被触及!

    堆栈跟踪:(指此行: .getSingleResult(); )

    03:39:07,228 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-93) javax.ejb.EJBException: javax.persistence.NonUniqueResultException: result returns more than one elements
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:187)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:277)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:327)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
        at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636)
        at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
        at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195)
        at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73)
        at me.mitcht.myapp.core.entities.services.FieldService$$$view157.findByTitle(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.jboss.weld.util.reflection.Reflections.invokeAndUnwrap(Reflections.java:436)
        at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:127)
        at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
        at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100)
        at me.mitcht.myapp.core.entities.services.FieldService$Proxy$_$$_Weld$EnterpriseProxy$.findByTitle(Unknown Source)
        at me.mitcht.myapp.web.validators.UniqueFieldValidator.validate(UniqueFieldValidator.java:39)
        at javax.faces.component.UIInput.validateValue(UIInput.java:1164)
        at javax.faces.component.UIInput.validate(UIInput.java:982)
        at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
        at javax.faces.component.UIInput.processValidators(UIInput.java:712)
        at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
        at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
        at javax.faces.component.UIForm.processValidators(UIForm.java:253)
        at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:575)
        at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
        at javax.faces.component.UIForm.visitTree(UIForm.java:371)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
        at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
        at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
        at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57)
        at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:219)
        at org.omnifaces.context.OmniPartialViewContext.processPartial(OmniPartialViewContext.java:144)
        at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193)
        at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
        at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
        at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:81)
        at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:265)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:200)
        at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:193)
        at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:106)
        at me.mitcht.myapp.web.filters.TenantFilter.doFilter(TenantFilter.java:73)
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
        at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
        at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
        at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
        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)
    Caused by: javax.persistence.NonUniqueResultException: result returns more than one elements
        at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:539)
        at me.mitcht.myapp.core.entities.services.FieldService.findByTitle(FieldService.java:30)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
        at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82)
        at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93)
        at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.jpa.interceptor.SBInvocationInterceptor.processInvocation(SBInvocationInterceptor.java:47)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.jpa.interceptor.SFSBInvocationInterceptor.processInvocation(SFSBInvocationInterceptor.java:57)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.stateful.StatefulSessionSynchronizationInterceptor.processInvocation(StatefulSessionSynchronizationInterceptor.java:125)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
        at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:64)
        at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.stateful.StatefulComponentInstanceInterceptor.processInvocation(StatefulComponentInstanceInterceptor.java:65)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275)
        ... 112 more
    

    我做错了什么?

    public Field findByTitle(String title) {
        if (title == null)
            return null;
    
        try {
            return entityManager
                    .createQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class)
                    .setParameter(1, title)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        } catch (NonUniqueResultException e) {
            throw e;
        }
    }
    

    try {
        Field field = fieldService.findByTitle(title);
    } catch (EJBException e) {
        if (e.getCause() instanceof NonUniqueResultException) {
            LogManager.logInfo("Oh no!");
        }
        return;
    }
    
    4 回复  |  直到 8 年前
        1
  •  2
  •   MWiesner    8 年前

    当从 @Stateful 注释容器托管bean,您将收到一个 EJBException 因此,你需要抓住这一点(正如德米特里·金兹伯格(Dmitry Ginzburg)的回答所述)。

    然而,问题的一个更一致的方法(解决方案)是按如下方式更改方法签名和实现:

    public List<Field> findByTitle(String title) {
        if (title == null)
            return null;
    
        try {
            TypedQuery<Field> query =  entityManager
                    .createTypedQuery("SELECT f FROM Field f WHERE f.title = ?1", Field.class);
            query.setParameter(1, title)
            return query.getResultList();
        } catch (NoResultException e) {
            return null;
        } 
    }
    

    引发/接受异常处理几乎从来都不是一种有效的方法。始终选择设计合理的界面,以反映您尝试实现的情况。

        2
  •  0
  •   Aleksandar Đokić    8 年前

    您可以尝试通过在查询末尾添加限制来修复它。

    public Field findByTitle(String title) {
        if (title == null)
            return null;
    
        try {
            return entityManager
                    .createQuery("SELECT f FROM Field f WHERE f.title = ?1 LIMIT 1,1", Field.class)
                    .setParameter(1, title)
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }
    
        3
  •  0
  •   Dmitry Ginzburg    8 年前

    引发的实际异常是 javax.ejb.EJBException ,因此您必须抓住它,然后重新提出原因:

    try {
        ....
    } catch (EJBException ex) {
        if (ex.getCause() instanceof NonUniqueResultException) {
            throw (NonUniqueResultException)ex.getCause();
        }
    }
    
        4
  •  0
  •   Community CDub    7 年前

    事实证明,由于我将bean作为代理进行访问 真实的 引发的异常是 javax.ejb.EJBException 。从堆栈跟踪中查看此行:

    javax.ejb.EJBException: javax.persistence.NonUniqueResultException: result returns more than one elements
    

    EJBException 而不是 NonUniqueResultException ,然后检查原因以确保其符合我的预期:

    try {
        Field field = fieldService.findByTitle(title);
    } catch (EJBException e) {
        if (e.getCause() instanceof NonUniqueResultException) {
            LogManager.logInfo("Oh no!");
        }
        return;
    }
    

    这很管用,但看起来很糟糕,你可以看出这只是糟糕的设计。

    因此,我选择使用建议的解决方案 MWiesner 返回 Collection 而不仅仅是一个结果。这样我可以简单地检查集合的大小。如果它大于1,显然结果不是唯一的。