首页 Java java教程 深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)

深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)

Mar 02, 2017 am 10:48 AM

上篇文章《深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)》为大家介绍了mybatis中别名的使用,以及其源码。本篇将为大家介绍TypeHandler, 并简单分析其源码。

Mybatis中的TypeHandler是什么?

  无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。Mybatis默认为我们实现了许多TypeHandler, 当我们没有配置指定TypeHandler时,Mybatis会根据参数或者返回结果的不同,默认为我们选择合适的TypeHandler处理。

那么,Mybatis为我们实现了哪些TypeHandler呢?  我们怎么自定义实现一个TypeHandler ?  这些都会在接下来的mybatis的源码中看到。

在看源码之前,还是像之前一样,先看看怎么配置吧?

配置TypeHandler:

<configuration>
    <typeHandlers>
      <!-- 
          当配置package的时候,mybatis会去配置的package扫描TypeHandler
          <package name="com.dy.demo"/>       -->
      
      <!-- handler属性直接配置我们要指定的TypeHandler -->
      <typeHandler handler=""/>
      
      <!-- javaType 配置java类型,例如String, 如果配上javaType, 那么指定的typeHandler就只作用于指定的类型 -->
      <typeHandler javaType="" handler=""/>
      
      <!-- jdbcType 配置数据库基本数据类型,例如varchar, 如果配上jdbcType, 那么指定的typeHandler就只作用于指定的类型  -->
      <typeHandler jdbcType="" handler=""/>
      
      <!-- 也可两者都配置 -->
      <typeHandler javaType="" jdbcType="" handler=""/>
      
  </typeHandlers>
  
  ......  
</configuration>
登录后复制

上面简单介绍了一下TypeHandler,  下面就看看mybatis中TypeHandler的源码了。


=========================================================我是源码分割线==========================================================

老规矩,先从对xml的解析讲起:


/**
 * 解析typeHandlers节点 */private void typeHandlerElement(XNode parent) throws Exception {    if (parent != null) {      for (XNode child : parent.getChildren()) {        //子节点为package时,获取其name属性的值,然后自动扫描package下的自定义typeHandler
        if ("package".equals(child.getName())) {
          String typeHandlerPackage = child.getStringAttribute("name");
          typeHandlerRegistry.register(typeHandlerPackage);
        } else {          //子节点为typeHandler时, 可以指定javaType属性, 也可以指定jdbcType, 也可两者都指定          //javaType 是指定java类型          //jdbcType 是指定jdbc类型(数据库类型: 如varchar)
          String javaTypeName = child.getStringAttribute("javaType");
          String jdbcTypeName = child.getStringAttribute("jdbcType");          //handler就是我们配置的typeHandler
          String handlerTypeName = child.getStringAttribute("handler");          //resolveClass方法就是我们上篇文章所讲的TypeAliasRegistry里面处理别名的方法
          Class<?> javaTypeClass = resolveClass(javaTypeName);          //JdbcType是一个枚举类型,resolveJdbcType方法是在获取枚举类型的值
          JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
          Class<?> typeHandlerClass = resolveClass(handlerTypeName);          //注册typeHandler, typeHandler通过TypeHandlerRegistry这个类管理
          if (javaTypeClass != null) {            if (jdbcType == null) {
              typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
            } else {
              typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
            }
          } else {
            typeHandlerRegistry.register(typeHandlerClass);
          }
        }
      }
    }
}
登录后复制


接下来看看TypeHandler的管理注册类:

TypeHandlerRegistry:

/**
 * typeHandler注册管理类 */public final class TypeHandlerRegistry {  
 //源码一上来,二话不说,几个大大的HashMap就出现,这不又跟上次讲的typeAliases的注册类似么  
 //基本数据类型与其包装类
  private static final Map<Class<?>, Class<?>> reversePrimitiveMap = new HashMap<Class<?>, Class<?>>() {    private static final long serialVersionUID = 1L;
    {
      put(Byte.class, byte.class);
      put(Short.class, short.class);
      put(Integer.class, int.class);
      put(Long.class, long.class);
      put(Float.class, float.class);
      put(Double.class, double.class);
      put(Boolean.class, boolean.class);
      put(Character.class, char.class);
    }
  };  //这几个MAP不用说就知道存的是什么东西吧,命名的好处
  private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);  private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new HashMap<Type, Map<JdbcType, TypeHandler<?>>>();  private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this);  private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();  //就像上篇文章讲的typeAliases一样,mybatis也默认给我们注册了不少的typeHandler  //具体如下
  public TypeHandlerRegistry() {
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());

    register(Byte.class, new ByteTypeHandler());
    register(byte.class, new ByteTypeHandler());
    register(JdbcType.TINYINT, new ByteTypeHandler());

    register(Short.class, new ShortTypeHandler());
    register(short.class, new ShortTypeHandler());
    register(JdbcType.SMALLINT, new ShortTypeHandler());

    register(Integer.class, new IntegerTypeHandler());
    register(int.class, new IntegerTypeHandler());
    register(JdbcType.INTEGER, new IntegerTypeHandler());

    register(Long.class, new LongTypeHandler());
    register(long.class, new LongTypeHandler());

    register(Float.class, new FloatTypeHandler());
    register(float.class, new FloatTypeHandler());
    register(JdbcType.FLOAT, new FloatTypeHandler());

    register(Double.class, new DoubleTypeHandler());
    register(double.class, new DoubleTypeHandler());
    register(JdbcType.DOUBLE, new DoubleTypeHandler());

    register(String.class, new StringTypeHandler());
    register(String.class, JdbcType.CHAR, new StringTypeHandler());
    register(String.class, JdbcType.CLOB, new ClobTypeHandler());
    register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
    register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
    register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
    register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
    register(JdbcType.CHAR, new StringTypeHandler());
    register(JdbcType.VARCHAR, new StringTypeHandler());
    register(JdbcType.CLOB, new ClobTypeHandler());
    register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
    register(JdbcType.NVARCHAR, new NStringTypeHandler());
    register(JdbcType.NCHAR, new NStringTypeHandler());
    register(JdbcType.NCLOB, new NClobTypeHandler());

    register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
    register(JdbcType.ARRAY, new ArrayTypeHandler());

    register(BigInteger.class, new BigIntegerTypeHandler());
    register(JdbcType.BIGINT, new LongTypeHandler());

    register(BigDecimal.class, new BigDecimalTypeHandler());
    register(JdbcType.REAL, new BigDecimalTypeHandler());
    register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
    register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

    register(Byte[].class, new ByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
    register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
    register(byte[].class, new ByteArrayTypeHandler());
    register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
    register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
    register(JdbcType.BLOB, new BlobTypeHandler());

    register(Object.class, UNKNOWN_TYPE_HANDLER);
    register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
    register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);

    register(Date.class, new DateTypeHandler());
    register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
    register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
    register(JdbcType.TIMESTAMP, new DateTypeHandler());
    register(JdbcType.DATE, new DateOnlyTypeHandler());
    register(JdbcType.TIME, new TimeOnlyTypeHandler());

    register(java.sql.Date.class, new SqlDateTypeHandler());
    register(java.sql.Time.class, new SqlTimeTypeHandler());
    register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());    // issue #273
    register(Character.class, new CharacterTypeHandler());
    register(char.class, new CharacterTypeHandler());
  }  public boolean hasTypeHandler(Class<?> javaType) {    return hasTypeHandler(javaType, null);
  }  public boolean hasTypeHandler(TypeReference<?> javaTypeReference) {    return hasTypeHandler(javaTypeReference, null);
  }  public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {    return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
  }  public boolean hasTypeHandler(TypeReference<?> javaTypeReference, JdbcType jdbcType) {    return javaTypeReference != null && getTypeHandler(javaTypeReference, jdbcType) != null;
  }  public TypeHandler<?> getMappingTypeHandler(Class<? extends TypeHandler<?>> handlerType) {    return ALL_TYPE_HANDLERS_MAP.get(handlerType);
  }  public <T> TypeHandler<T> getTypeHandler(Class<T> type) {    return getTypeHandler((Type) type, null);
  }  public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference) {    return getTypeHandler(javaTypeReference, null);
  }  public TypeHandler<?> getTypeHandler(JdbcType jdbcType) {    return JDBC_TYPE_HANDLER_MAP.get(jdbcType);
  }  public <T> TypeHandler<T> getTypeHandler(Class<T> type, JdbcType jdbcType) {    return getTypeHandler((Type) type, jdbcType);
  }  public <T> TypeHandler<T> getTypeHandler(TypeReference<T> javaTypeReference, JdbcType jdbcType) {    return getTypeHandler(javaTypeReference.getRawType(), jdbcType);
  }  private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
    TypeHandler<?> handler = null;    if (jdbcHandlerMap != null) {
      handler = jdbcHandlerMap.get(jdbcType);      if (handler == null) {
        handler = jdbcHandlerMap.get(null);
      }
    }    if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) {
      handler = new EnumTypeHandler((Class<?>) type);
    }
    @SuppressWarnings("unchecked")    // type drives generics here
    TypeHandler<T> returned = (TypeHandler<T>) handler;    return returned;
  }  public TypeHandler<Object> getUnknownTypeHandler() {    return UNKNOWN_TYPE_HANDLER;
  }  public void register(JdbcType jdbcType, TypeHandler<?> handler) {
    JDBC_TYPE_HANDLER_MAP.put(jdbcType, handler);
  }  //
  // REGISTER INSTANCE  
  //
  /**
   * 只配置了typeHandler, 没有配置jdbcType 或者javaType   
   */
  @SuppressWarnings("unchecked")  public <T> void register(TypeHandler<T> typeHandler) {    
  boolean mappedTypeFound = false;    
  //在自定义typeHandler的时候,可以加上注解MappedTypes 去指定关联的javaType    
  //因此,此处需要扫描MappedTypes注解
    MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);    
    if (mappedTypes != null) {      
    for (Class<?> handledType : mappedTypes.value()) {
        register(handledType, typeHandler);
        mappedTypeFound = true;
      }
    }    // @since 3.1.0 - try to auto-discover the mapped type
    if (!mappedTypeFound && typeHandler instanceof TypeReference) {      try {
        TypeReference<T> typeReference = (TypeReference<T>) typeHandler;
        register(typeReference.getRawType(), typeHandler);
        mappedTypeFound = true;
      } catch (Throwable t) {        
      // maybe users define the TypeReference with a different type and are not assignable, so just ignore it     
       }
    }    if (!mappedTypeFound) {
      register((Class<T>) null, typeHandler);
    }
  }  /**
   * 配置了typeHandlerhe和javaType   */
  public <T> void register(Class<T> javaType, TypeHandler<? extends T> typeHandler) {
    register((Type) javaType, typeHandler);
  }  private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {    
  //扫描注解MappedJdbcTypes
    MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);    
    if (mappedJdbcTypes != null) {      
    for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
        register(javaType, handledJdbcType, typeHandler);
      }      if (mappedJdbcTypes.includeNullJdbcType()) {
        register(javaType, null, typeHandler);
      }
    } else {
      register(javaType, null, typeHandler);
    }
  }  public <T> void register(TypeReference<T> javaTypeReference, TypeHandler<? extends T> handler) {
    register(javaTypeReference.getRawType(), handler);
  }  /**
   * typeHandlerhe、javaType、jdbcType都配置了   */
  public <T> void register(Class<T> type, JdbcType jdbcType, TypeHandler<? extends T> handler) {
    register((Type) type, jdbcType, handler);
  }  /**
   * 注册typeHandler的核心方法
   * 就是向Map新增数据而已   */
  private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {    
  if (javaType != null) {
      Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);      
      if (map == null) {
        map = new HashMap<JdbcType, TypeHandler<?>>();
        TYPE_HANDLER_MAP.put(javaType, map);
      }
      map.put(jdbcType, handler);      
      if (reversePrimitiveMap.containsKey(javaType)) {
        register(reversePrimitiveMap.get(javaType), jdbcType, handler);
      }
    }
    ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
  }  //
  // REGISTER CLASS  //

  // Only handler type

  public void register(Class<?> typeHandlerClass) {    
  boolean mappedTypeFound = false;
    MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);    
    if (mappedTypes != null) {      
    for (Class<?> javaTypeClass : mappedTypes.value()) {
        register(javaTypeClass, typeHandlerClass);
        mappedTypeFound = true;
      }
    }    if (!mappedTypeFound) {
      register(getInstance(null, typeHandlerClass));
    }
  }  // java type + handler type

  public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
    register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));
  }  // java type + jdbc type + handler type

  public void register(Class<?> javaTypeClass, JdbcType jdbcType, Class<?> typeHandlerClass) {
    register(javaTypeClass, jdbcType, getInstance(javaTypeClass, typeHandlerClass));
  }  // Construct a handler (used also from Builders)
  @SuppressWarnings("unchecked")  public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {    if (javaTypeClass != null) {      try {
        Constructor<?> c = typeHandlerClass.getConstructor(Class.class);        
        return (TypeHandler<T>) c.newInstance(javaTypeClass);
      } catch (NoSuchMethodException ignored) {        
      // ignored
      } catch (Exception e) {        
      throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
      }
    }    try {
      Constructor<?> c = typeHandlerClass.getConstructor();      
      return (TypeHandler<T>) c.newInstance();
    } catch (Exception e) {     
     throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
    }
  } 
  /**
   * 根据指定的pacakge去扫描自定义的typeHander,然后注册   */
  public void register(String packageName) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
    Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();    
    for (Class<?> type : handlerSet) {      
    //Ignore inner classes and interfaces (including package-info.java) and abstract classes
      if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
        register(type);
      }
    }
  }  
  // get information
  
  /**
   * 通过configuration对象可以获取已注册的所有typeHandler   */
  public Collection<TypeHandler<?>> getTypeHandlers() {    
  return Collections.unmodifiableCollection(ALL_TYPE_HANDLERS_MAP.values());
  }
  
}
登录后复制


由源码可以看到, mybatis为我们实现了那么多TypeHandler,  随便打开一个TypeHandler,看其源码,都可以看到,它继承自一个抽象类:BaseTypeHandler, 那么我们是不是也能通过继承BaseTypeHandler,从而实现自定义的TypeHandler ? 答案是肯定的, 那么现在下面就为大家演示一下自定义TypeHandler:

=====================================================自定义TypeHandler分割线============================================================

ExampleTypeHandler:

@MappedJdbcTypes(JdbcType.VARCHAR)  
//此处如果不用注解指定jdbcType, 那么,就可以在配置文件中通过"jdbcType"属性指定, 同理, javaType 也可通过 @MappedTypes指定public class ExampleTypeHandler extends BaseTypeHandler<String> {

  @Override  public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    ps.setString(i, parameter);
  }

  @Override  public String getNullableResult(ResultSet rs, String columnName) throws SQLException {    return rs.getString(columnName);
  }

  @Override  public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {    return rs.getString(columnIndex);
  }

  @Override  public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {    return cs.getString(columnIndex);
  }
}
登录后复制


然后,就该配置我们的自定义TypeHandler了:


<configuration>
  <typeHandlers>
      <!-- 由于自定义的TypeHandler在定义时已经通过注解指定了jdbcType, 所以此处不用再配置jdbcType -->
      <typeHandler handler="ExampleTypeHandler"/>
  </typeHandlers>
  
  ......  
</configuration>
登录后复制


也就是说,我们在自定义TypeHandler的时候,可以在TypeHandler通过@MappedJdbcTypes指定jdbcType, 通过 @MappedTypes 指定javaType, 如果没有使用注解指定,那么我们就需要在配置文件中配置。

好啦,本篇文章到此结束。

 以上就是深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

iBatis和MyBatis:哪个更适合你? iBatis和MyBatis:哪个更适合你? Feb 19, 2024 pm 04:38 PM

iBatis与MyBatis:你应该选择哪个?简介:随着Java语言的快速发展,许多持久化框架也应运而生。iBatis和MyBatis是两个备受欢迎的持久化框架,它们都提供了一种简单而高效的数据访问解决方案。本文将介绍iBatis和MyBatis的特点和优势,并给出一些具体的代码示例,帮助你选择合适的框架。iBatis简介:iBatis是一个开源的持久化框架

详解MyBatis动态SQL标签中的Set标签功能 详解MyBatis动态SQL标签中的Set标签功能 Feb 26, 2024 pm 07:48 PM

MyBatis动态SQL标签解读:Set标签用法详解MyBatis是一个优秀的持久层框架,它提供了丰富的动态SQL标签,可以灵活地构建数据库操作语句。其中,Set标签是用于生成UPDATE语句中SET子句的标签,在更新操作中非常常用。本文将详细解读MyBatis中Set标签的用法,以及通过具体的代码示例来演示其功能。什么是Set标签Set标签用于MyBati

对比分析JPA和MyBatis的功能和性能 对比分析JPA和MyBatis的功能和性能 Feb 19, 2024 pm 05:43 PM

JPA和MyBatis:功能与性能对比分析引言:在Java开发中,持久化框架扮演着非常重要的角色。常见的持久化框架包括JPA(JavaPersistenceAPI)和MyBatis。本文将对这两个框架的功能和性能进行对比分析,并提供具体的代码示例。一、功能对比:JPA:JPA是JavaEE的一部分,提供了一种面向对象的数据持久化解决方案。它通过注解或X

实现MyBatis中批量删除操作的多种方式 实现MyBatis中批量删除操作的多种方式 Feb 19, 2024 pm 07:31 PM

MyBatis中实现批量删除语句的几种方式,需要具体代码示例近年来,由于数据量的不断增加,批量操作成为了数据库操作的一个重要环节之一。在实际开发中,我们经常需要批量删除数据库中的记录。本文将重点介绍在MyBatis中实现批量删除语句的几种方式,并提供相应的代码示例。使用foreach标签实现批量删除MyBatis提供了foreach标签,可以方便地遍历一个集

MyBatis批量删除语句的使用方法详解 MyBatis批量删除语句的使用方法详解 Feb 20, 2024 am 08:31 AM

MyBatis批量删除语句的使用方法详解,需要具体代码示例引言:MyBatis是一款优秀的持久层框架,提供了丰富的SQL操作功能。在实际项目开发中,经常会遇到需要批量删除数据的情况。本文将详细介绍MyBatis批量删除语句的使用方法,并附上具体的代码示例。使用场景:在数据库中删除大量数据时,逐条执行删除语句效率低下。此时,可以使用MyBatis的批量删除功能

MyBatis 一级缓存详解:如何提升数据访问效率? MyBatis 一级缓存详解:如何提升数据访问效率? Feb 23, 2024 pm 08:13 PM

MyBatis一级缓存详解:如何提升数据访问效率?在开发过程中,高效的数据访问一直是程序员们关注的焦点之一。而对于MyBatis这样的持久层框架而言,缓存是提升数据访问效率的关键方法之一。MyBatis提供了一级缓存和二级缓存两种缓存机制,其中一级缓存是默认开启的。本文将详细介绍MyBatis一级缓存的机制,并提供具体的代码示例,帮助读者更好地理

MyBatis缓存机制详解:一文读懂缓存存储原理 MyBatis缓存机制详解:一文读懂缓存存储原理 Feb 23, 2024 pm 04:09 PM

MyBatis缓存机制详解:一文读懂缓存存储原理引言在使用MyBatis进行数据库访问时,缓存是一个非常重要的机制,能够有效减少对数据库的访问,提高系统性能。本文将详细介绍MyBatis的缓存机制,包括缓存的分类、存储原理和具体的代码示例。一、缓存的分类MyBatis的缓存主要分为一级缓存和二级缓存两种。一级缓存一级缓存是SqlSession级别的缓存,当在

解析MyBatis的缓存机制:比较一级缓存和二级缓存的特点和用法 解析MyBatis的缓存机制:比较一级缓存和二级缓存的特点和用法 Feb 25, 2024 pm 12:30 PM

MyBatis的缓存机制解析:一级缓存与二级缓存的区别与应用在MyBatis框架中,缓存是一个非常重要的特性,可以有效提升数据库操作的性能。其中,一级缓存和二级缓存是MyBatis中常用的两种缓存机制。本文将详细解析一级缓存与二级缓存的区别与应用,并提供具体的代码示例进行说明。一、一级缓存一级缓存也被称为本地缓存,它默认开启且不可关闭。一级缓存是SqlSes

See all articles