Older rookie-"mybatis source code reading -" exceptions abnormal module

The Chinese New Year is coming soon, this year's New Year is very different, and the new crown does not know when it will be completely wiped out.

I am not financially free. Decided to stay in Shanghai and write articles if there is nothing to do during the New Year. Oye~

Do what you want to do while you are alive! Don't postpone, don't give up.

enter the theme

1: Directory overview

Things in the abnormal module do not seem to be Doha. Compared to the previous reflection module, this one looks really easy.

In fact, not all the exception classes of mybatis are defined in this directory. Other packages are also available. Listed below

These exception codes are the same. So, here is simply organized as follows:

  • reflection 包:ReflectionException
  • logging Package: LogException
  • builder 包:BuilderException、IncompleteElementException
  • scripting Package: ScriptingException
  • binding 包:BindingException
  • type Package: TypeException
  • session Package: SqlSessionException
  • cache 包 : CacheException
  • transaction 包:TransactionException
  • datasource 包:DataSourceException
  • executor 包:ResultMapException、ExecutorException、BatchExecutorException
  • plugin 包:PluginException

 

Two: IbatisException class inherits RuntimeException, the abnormal base class of Ibatis , the specific code is as follows.

package org.apache.ibatis.exceptions;

/**
 * @author Clinton Begin
 */
@Deprecated
public class IbatisException extends RuntimeException {

  private static final long serialVersionUID = 3880206998166270511L;

  public IbatisException() {
    super();
  }

  public IbatisException(String message) {
    super(message);
  }

  public IbatisException(String message, Throwable cause) {
    super(message, cause);
  }

  public IbatisException(Throwable cause) {
    super(cause);
  }

}

Three: PersistenceException, inherits the IbatisException class, currently the real exception base class of MyBatis . code show as below:

package org.apache.ibatis.exceptions;

/**
 * @author Clinton Begin
 */
@SuppressWarnings("deprecation")
public class PersistenceException extends IbatisException {

  private static final long serialVersionUID = -7537395265357977271L;

  public PersistenceException() {
    super();
  }

  public PersistenceException(String message) {
    super(message);
  }

  public PersistenceException(String message, Throwable cause) {
    super(message, cause);
  }

  public PersistenceException(Throwable cause) {
    super(cause);
  }
}

Four: TooManyResultsException, inherits the PersistenceException class, the query returns an exception with too many results. Expected to return one, but actually returned many. code show as below:

/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.exceptions;

/**
 * 继承 PersistenceException 类,查询返回过多结果的异常
 * 期望返回一条,实际返回了多条。代码如下:
 * @author Clinton Begin
 */
public class TooManyResultsException extends PersistenceException {

  private static final long serialVersionUID = 8935197089745865786L;

  public TooManyResultsException() {
    super();
  }

  public TooManyResultsException(String message) {
    super(message);
  }

  public TooManyResultsException(String message, Throwable cause) {
    super(message, cause);
  }

  public TooManyResultsException(Throwable cause) {
    super(cause);
  }
}

Five: ExceptionFactory, which is the packaging of the next exception

package org.apache.ibatis.exceptions;

import org.apache.ibatis.executor.ErrorContext;

/**
 * @author Clinton Begin
 */
public class ExceptionFactory {

  private ExceptionFactory() {
    // Prevent Instantiation
  }
  /**
   * 包装异常成 PersistenceException
   *
   * @param message 消息
   * @param e 发生的异常
   * @return PersistenceException
   */
  public static RuntimeException wrapException(String message, Exception e) {
    // 因为instance 和 message 和 cause 这些方法都是单独调用的,
    // 所以 instance用了本地线程变量。来保存线程上下的值。
    return new PersistenceException(ErrorContext.instance().message(message).cause(e).toString(), e);
  }

}


/**
 *  ErrorContext  对象
 *    Copyright 2009-2020 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.executor;

/**
 * @author Clinton Begin
 */
public class ErrorContext {

  private static final String LINE_SEPARATOR = System.lineSeparator();
  // 创建一个 本地线程的  ErrorContext 对象
  private static final ThreadLocal<ErrorContext> LOCAL = ThreadLocal.withInitial(ErrorContext::new);

  private ErrorContext stored;
  private String resource;
  private String activity;
  private String object;
  private String message;
  private String sql;
  private Throwable cause;

  private ErrorContext() {
  }

  public static ErrorContext instance() {
    return LOCAL.get();
  }

  public ErrorContext store() {
    ErrorContext newContext = new ErrorContext();
    newContext.stored = this;
    LOCAL.set(newContext);
    return LOCAL.get();
  }

  public ErrorContext recall() {
    if (stored != null) {
      LOCAL.set(stored);
      stored = null;
    }
    return LOCAL.get();
  }

  public ErrorContext resource(String resource) {
    this.resource = resource;
    return this;
  }

  public ErrorContext activity(String activity) {
    this.activity = activity;
    return this;
  }

  public ErrorContext object(String object) {
    this.object = object;
    return this;
  }

  public ErrorContext message(String message) {
    this.message = message;
    return this;
  }

  public ErrorContext sql(String sql) {
    this.sql = sql;
    return this;
  }

  public ErrorContext cause(Throwable cause) {
    this.cause = cause;
    return this;
  }

  public ErrorContext reset() {
    resource = null;
    activity = null;
    object = null;
    message = null;
    sql = null;
    cause = null;
    LOCAL.remove();
    return this;
  }

  @Override
  public String toString() {
    StringBuilder description = new StringBuilder();

    // message
    if (this.message != null) {
      description.append(LINE_SEPARATOR);
      description.append("### ");
      description.append(this.message);
    }

    // resource
    if (resource != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error may exist in ");
      description.append(resource);
    }

    // object
    if (object != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error may involve ");
      description.append(object);
    }

    // activity
    if (activity != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error occurred while ");
      description.append(activity);
    }

    // sql
    if (sql != null) {
      description.append(LINE_SEPARATOR);
      description.append("### SQL: ");
      description.append(sql.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').trim());
    }

    // cause
    if (cause != null) {
      description.append(LINE_SEPARATOR);
      description.append("### Cause: ");
      description.append(cause.toString());
    }

    return description.toString();
  }

}

/**
*
* 单测类
**/
package org.apache.ibatis.exceptions;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.lang.reflect.InvocationTargetException;

import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.builder.BuilderException;
import org.apache.ibatis.cache.CacheException;
import org.apache.ibatis.datasource.DataSourceException;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.logging.LogException;
import org.apache.ibatis.parsing.ParsingException;
import org.apache.ibatis.plugin.PluginException;
import org.apache.ibatis.reflection.ReflectionException;
import org.apache.ibatis.scripting.ScriptingException;
import org.apache.ibatis.session.SqlSessionException;
import org.apache.ibatis.transaction.TransactionException;
import org.apache.ibatis.type.TypeException;
import org.junit.jupiter.api.Test;

class GeneralExceptionsTest {

  private static final String EXPECTED_MESSAGE = "Test Message";
  private static final Exception EXPECTED_CAUSE = new Exception("Nested Exception");

  @Test
  void should() {
    RuntimeException thrown = ExceptionFactory.wrapException(EXPECTED_MESSAGE, EXPECTED_CAUSE);
    assertTrue(thrown instanceof PersistenceException, "Exception should be wrapped in RuntimeSqlException.");
    testThrowException(thrown);
  }
}

This module is relatively simple~

 

Guess you like

Origin blog.csdn.net/lileronglilerong/article/details/113756238