马上快过年了,今年的年过的很不一样,新冠也不知道啥时候可以彻底消灭。
财务不自由的我。决定留在大上海,过年如果没事干就写写文章。欧耶~
活着就去做想做的事!不推迟不放弃。
进入主题
一:目录总览
异常模块的东西看着是不多哈。相比之前的反射模块,这个看起来真的比较轻松。
实际上,mybatis的异常类并非全部定义在这个目录下。其他的包下也是有的。下面整理罗列了下
这些异常类代码都是相同的。所以,这里就简单整理如下:
reflection
包:ReflectionExceptionlogging
包:LogExceptionbuilder
包:BuilderException、IncompleteElementExceptionscripting
包:ScriptingExceptionbinding
包:BindingExceptiontype
包:TypeExceptionsession
包:SqlSessionExceptioncache
包:CacheExceptiontransaction
包:TransactionExceptiondatasource
包:DataSourceExceptionexecutor
包:ResultMapException、ExecutorException、BatchExecutorExceptionplugin
包:PluginException
二: IbatisException 类继承 RuntimeException,IBatis 的异常基类,具体代码如下。
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);
}
}
三: PersistenceException,继承 IbatisException 类,目前 MyBatis 真正的异常基类。代码如下:
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);
}
}
四:TooManyResultsException,继承 PersistenceException 类,查询返回过多结果的异常。期望返回一条,实际返回了多条。代码如下:
/**
* 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);
}
}
五: ExceptionFactory ,就是进行下异常的包装
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 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);
}
}
这个模块还是比较简单的~