【问题标题】:Not able to catch Hibernate Exceptions in spring春季无法捕获休眠异常
【发布时间】:2018-09-01 03:19:23
【问题描述】:

我是 Spring 框架的新手。使用 Spring 4.3 和 Hibernate 4 开发 Web 应用程序。

我配置了所需的 bean。

<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName"
        value="${oracle.driver-calss}" />
    <property name="url" value="${oracle.Url}" />
    <property name="username" value="${oracle.userName}" />
    <property name="password" value="${oracle.password}" />
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${oracle.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${oracle.hbm2ddl}</prop>
            <prop key="hibernate.show-sql">${oracle.show-sql}</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.wmosIIBL.model"></property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

这是我的服务类

@Service
public class ItemIBLService {

    @Autowired
    ItemIBLDaoImpl itemIBLDaoImpl;

    @Transactional
    public ItemInvnByLcn getItemIBLByDspLocn(String dspLocn) {
        ItemInvnByLcn itemInvnByLcn = null;
        try {
            itemIBLDaoImpl.getIBLByDspLocn(dspLocn);
        } catch (DataAccessException dataAccessException) {
            System.out.println(dataAccessException.getMessage().toString());
        }
        return itemInvnByLcn;
    }

}

DAO Impl Code:我故意犯一些错误来创建异常。所以请忽略代码错误并帮助我找到如何捕获抛出的异常。

@Repository
public class ItemIBLDaoImpl {

    @Autowired
    SessionFactory sessionFactory;

    public ItemInvnByLcn getIBLByDspLocn(String dspLocn) {
        Session currentSession = sessionFactory.getCurrentSession();
        SQLQuery sqlQuery = currentSession.createSQLQuery("SELECT * FROM WHERE ITEMINVNBYLOCN WHERE LOCATION= :DSPLOCN");
        sqlQuery.setParameter("SDPLOCN", dspLocn);
        List iiblList = sqlQuery.list();
        System.out.println(iiblList.toString());
        return (ItemInvnByLcn) iiblList.get(0);
    }

}

Hibernate 抛出以下异常,我无法在服务类中捕获异常。

org.hibernate.QueryParameterException: could not locate named parameter [SDPLOCN]
    at org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterDescriptor(ParameterMetadata.java:148)
    at org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterExpectedType(ParameterMetadata.java:165)
    at org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:523)
    at org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:493)
    at com.wmosIIBL.dao.ItemIBLDaoImpl.getIBLByDspLocn(ItemIBLDaoImpl.java:22)
    at com.wmosIIBL.service.ItemIBLService.getItemIBLByDspLocn(ItemIBLService.java:22)
    at com.wmosIIBL.service.ItemIBLService$$FastClassBySpringCGLIB$$51d359cb.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
    at com.wmosIIBL.service.ItemIBLService$$EnhancerBySpringCGLIB$$eecd7652.getItemIBLByDspLocn(<generated>)
    at com.wmosIIBL.controller.ItemIBLController.getItemInvnByLocn(ItemIBLController.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:180)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1136)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

我想我在使用过程中遗漏了一些东西。请告诉我为什么即使我在服务层使用@Service 和@Transactional 并在Dao 层使用@Repository,我也无法捕获spring 服务类中的hibernate 引发的异常。

【问题讨论】:

  • 存储库类中的问题,正如堆栈跟踪所解释的那样。请提供ItemIBLDaoImpl.getIBLByDspLocn的代码,并注明哪一行是#22。
  • 嗨 Luiggi,现在请检查,我添加了代码。
  • 在您的代码中,您的 HQL 查询是 SELECT * FROM WHERE ITEMINVNBYLOCN WHERE LOCATION= :DSPLOCN,您定义了一个名为 DSPLOCN 的变量,但您正在设置名称为 SDPLOCN 的参数。
  • Dao 层抛出 QueryParameterException 并且服务层正在捕获 DataAccessException 只需在服务类中捕获 Exception 并检查它是否有效
  • 我明确提到我故意犯了一些错误来创建异常。所以请忽略那些错误。我需要了解@Repository是如何将hibernate异常转换为SpringException的。

标签: java spring hibernate spring-transactions


【解决方案1】:

org.hibernate.QueryParameterException 不是DataAccessException 的子类(您要捕获的那个),正如您在javadoc 中看到的那样。 如果您想捕获它,您应该将此异常添加到您的 catch 块中。这是一个RuntimeException,所以如果你像以前一样省略它,编译器不会说任何东西。

试试这个:

try {
    itemIBLDaoImpl.getIBLByDspLocn(dspLocn);
} catch (DataAccessException | QueryParameterException exception) {
    System.out.println(exception.getMessage());
}

【讨论】:

  • 小心。通常QueryParameterException 表示您的代码有问题,因此您应该检查代码并相应地修复它,而不是发现它。
  • 如果你知道,请告诉我 Hibernate Exception 是如何转换为 Spring 异常的,因为 spring 文档说你可以使用 Spring DataAcessException 捕获 Hibernate Exceptions
【解决方案2】:

如果您想捕获 QueryParameterException,您将捕获不正确的 DataAccessException。您可以直接捕获 QueryParameterException,也可以捕获 QueryException 或 HibernateException。

我建议为所有与查询相关的异常捕获 HibernateException

您可以在此处遵循 DataAccessException 的层次结构 https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/dao/DataAccessException.html

和 QueryParameterException https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/QueryParameterException.html

DataAccessException 更像是一种可恢复的东西,这意味着从代码的角度来看,一切都很好,当遇到数据库时,就会发生一些不好的事情。

但是您尝试做的是没有到达数据库,尝试创建查询失败,因此未处理 DataAccessException。

【讨论】:

  • 那么,为什么 spring 提到 Spring 可以使用 DataAccessException 捕获休眠异常
  • 因为QueryParameterException 不是你应该抓住的东西。相反,这意味着您的代码中有一个错误,您应该修复它。
  • @Abdul 我更新了我的答案来回答你的具体问题
猜你喜欢
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 2016-12-14
相关资源
最近更新 更多