问题:
使用spring经常会遇到类似的问题
error create bean name xxx failed nest exception class not found...想知道是由于前面创建的错误导致后边的异常,还是后边的异常导致前面的创建错误,nest exception(嵌套异常)的真正含义是什么?
回答:
重新贴一下 格式化的,
1、伪代码代码示例
- action {//表现层
- save() {
- service.save();
- }
- }
service {//服务层 该层一般会由spring进行动态代理 如完成事务处理
- save() {
- dao.save();
- }
- dao {//数据访问层
- save() {
- //调用如Hibernate访问数据库,,此时假设数据库没有打开将会抛出 无法建立连接的异常
- }
- }
即调用顺序是 action--->service--->dao---->hibernate--->jdbc
抛出异常顺序是 jdbc---->hibernate---->dao--抛出-->service--继续抛出-->action
具体异常如下所示:
org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is
org.hibernate.exception.GenericJDBCException: Cannot open connection 3、service接到异常,因为我集成了spring事务管理切面,因此spring对异常进行封装
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy4.countAll(Unknown Source)
at cn.javass.budget.sample.web.action.SampleAction.toList(SampleAction.java:42)
at cn.javass.budget.sample.web.action.SampleAction.execute(SampleAction.java:33)
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 com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:452)
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:291)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:254)
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:263)
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:133)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:142)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:166)
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:190)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:485)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at cn.javass.common.web.filter.SetCurrentURLAndContextPathFilter.doFilter(SetCurrentURLAndContextPathFilter.java:55)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection 2、此时hibernate将jdbc异常进行封装 抛出无法打开链接
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:555)
... 78 more
Caused by: java.sql.SQLException: Io 异常: The Network Adapter could not establish the connection 1、首先jdbc抛出无法建立连接
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:414)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at org.logicalcobwebs.proxool.DefaultConnectionBuilder.buildConnection(DefaultConnectionBuilder.java:39)
at org.logicalcobwebs.proxool.Prototyper.buildConnection(Prototyper.java:159)
at org.logicalcobwebs.proxool.ConnectionPool.getConnection(ConnectionPool.java:211)
at org.logicalcobwebs.proxool.ProxoolDataSource.getConnection(ProxoolDataSource.java:97)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
... 83 more
也就是说异常其实是栈调用的快照
1、最下层的异常是出错的原因,上边的异常是对下边的封装,目的是一致性 和 更可读; (即下边异常是引起上边异常的原因,每一个Exception 都有一个couse,如hibernate异常的couse就是jdbc的异常)
2、对于每一段异常,方法调用顺序是从下往上;
你的困惑是service处的异常
org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Cannot open connection
1、想知道是由于前面创建的错误导致后边的异常,还是后边的异常导致前面的创建错误,
后边导致前面,,,前面对后面的进行了封装,,目的是提供一致的异常(并且把原始错误显示出来 就是 nested exception 后边部分)
2、nest exception(嵌套异常)的真正含义是什么?
这个是spring实现的,首先我们看一下NestedRuntimeException
- public abstract class NestedRuntimeException extends RuntimeException {
- /** Use serialVersionUID from Spring 1.2 for interoperability */
- private static final long serialVersionUID = 5439915454935047936L;
- static {
- // Eagerly load the NestedExceptionUtils class to avoid classloader deadlock
- // issues on OSGi when calling getMessage(). Reported by Don Brown; SPR-5607.
- NestedExceptionUtils.class.getName();
- }
- /**
- * Construct a <code>NestedRuntimeException</code> with the specified detail message.
- * @param msg the detail message
- */
- public NestedRuntimeException(String msg) {
- super(msg);
- }
- /**
- * Construct a <code>NestedRuntimeException</code> with the specified detail message
- * and nested exception.
- * @param msg the detail message
- * @param cause the nested exception
- */
- public NestedRuntimeException(String msg, Throwable cause) {
- super(msg, cause);
- }
- /**
- * Return the detail message, including the message from the nested exception
- * if there is one.
- */
- @Override
- public String getMessage() {
- return NestedExceptionUtils.buildMessage(super.getMessage(), getCause());
- }
- ……
- }
NestedExceptionUtils 工具类
- public static String buildMessage(String message, Throwable cause) {
- if (cause != null) {
- StringBuilder sb = new StringBuilder();
- if (message != null) {
- sb.append(message).append("; ");
- }
- sb.append("nested exception is ").append(cause);
- return sb.toString();
- }
- else {
- return message;
- }
- }
//此处可以看出是异常消息当前异常的错误信息 append上 cause
Spring总共提供了两种嵌套异常的抽象类
NestedCheckedException ----> 受查的嵌套异常
NestedRuntimeException ----> 非受查的嵌套异常
来看一下 NestedRuntimeException javadoc描述
Handy class for wrapping runtime Exceptions with a root cause.
用root couse(就是真正的异常,如之上的hibernate异常 spring包装它)包装运行时异常的一个脚手架类。
This class is abstract to force the programmer to extend the class. getMessage will include nested exception information; printStackTrace and other like
methods will delegate to the wrapped exception, if any.
这个类是抽象的 强制程序员去继承它。getMessage方法将包含嵌套的异常信息(如之前的hibernate异常);printStackTrace 和其他的方法 将委托给包装的异常(如果存在)。
也就是说这个嵌套异常 做的最重要的工作就是修改了getMessage方法的行为,打印当前异常信息并且把包装的异常通过在 [nested exception is ]之后打印,,其他行为直接委托给原始异常。
在spring中继承NestedRuntimeException异常的有
AopConfigException, AopInvocationException, BeansException, BshScriptUtils.BshExecutionException, ConversionException, DataAccessException,
EjbAccessException, HandlerMethodInvocationException, HttpMessageConversionException, JmsException, JmxException, JndiLookupFailureException,
JobMethodInvocationFailedException, JRubyScriptUtils.JRubyExecutionException, MailException, MultipartException, RemoteAccessException, RestClientException,
SchedulingException, ScriptCompilationException, SerializationFailedException, TransactionException, XmlMappingException
我们最熟悉的就是 DataAccessException ----> 这个是spring为dao层提供的一致的异常体系,建议去看一下spring官方文档;
因此 nest exception(嵌套异常)的真正含义是什么?
就是spring中又做了一个一致的异常体系,目的是除了打印spring自己的异常信息 还将包装的异常 在 [nested exception is ] 之后显示出来。