mybatis笔记

     mybatis使用官方文档已经比较好,此处边笔记边学习(大部分复制粘贴)

    开发环境:SpringBoot(借用上篇开发环境)

     MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

SqlSessionFactory

       每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的,通过SqlSessionFactory 创建session连接操作DB,基本使用

      SqlSessionFactory 有六个方法可以用来创建 SqlSession 实例。通常来说,如何决定是你 选择下面这些方法时:

  • Transaction (事务): 你想为 session 使用事务或者使用自动提交(通常意味着很多 数据库和/或 JDBC 驱动没有事务)?
  • Connection (连接): 你想 MyBatis 获得来自配置的数据源的连接还是提供你自己
  • Execution (执行): 你想 MyBatis 复用预处理语句和/或批量更新语句(包括插入和 删除)?
  SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)

默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession:

  • 会开启一个事务(也就是不自动提交)
  • 连接对象会从由活动环境配置的数据源实例中得到。
  • 事务隔离级别将会使用驱动或数据源的默认设置。
  • 预处理语句不会被复用,也不会批量处理更新。

       开启自动提交, “true” 传递 给可选的 autoCommit 参数。 提供自定义的连接,传递一个 Connection 实例给 connection 参数。注意没有覆盖同时设置 Connection 和 autoCommit 两者的方法,因为 MyBatis 会使用当前 connection 对象提供的设 置。 MyBatis 为事务隔离级别调用使用一个 Java 枚举包装器, 称为 TransactionIsolationLevel, 否则它们按预期的方式来工作,并有 JDBC 支持的 5 级 ( NONE,READ_UNCOMMITTED,READ_COMMITTED,REPEA TABLE_READ,SERIALIZA BLE)

还有一个可能对你来说是新见到的参数,就是 ExecutorType。这个枚举类型定义了 3 个 值:

  • ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
  • ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
  • ExecutorType.BATCH: 这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为
        可以通过session操作原生的sql语句,或使用Mapper印射(推荐)

   基于Mapper

package mybatis;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import mybatis.mapper.CityMapper;
import mybatis.model.City;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MybatisApplicationTests {
	
	@Autowired
	SqlSessionFactory sqlSessionFactory;
	
	@Test
	public void selectBySql() {
		System.out.println("");
		SqlSession session = sqlSessionFactory.openSession();
		try {
		  CityMapper cityMapper = session.getMapper(CityMapper.class);
		  System.out.println(cityMapper.selectCityById(1));
		  // 此种不推荐
		  //System.out.println((City)session.selectOne("mybatis.mapper.CityMapper.selectCityById", 1));
		} finally {
		  session.close();
		}
	}

}
        不过我们在配置 SqlSessionFactory通过设置setMapperLocations已经实例化一批Mapper,直接注入使用即可

        依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器(mapper)并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。对于显示创建或这是需要注意其作用域与生命周期

     作用域与生命周期

  • SqlSessionFactoryBuilder  创建SqlSessionFactory,方法作用域即可
  • SqlSessionFactory  应用运行期
  • SqlSession  线程不安全,请求或方法作用域,用完即关(保证线程专属)
  • mapper  作用域通SqlSession.最好控制在方法作用域

基于注解

     基于注解对复杂sql语句局限想较大,不推荐使用.

xml配置

properties

     这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:
<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>
      属性也可以被传递到 SqlSessionFactoryBuilder.build()方法中。例如:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);
       加载顺序
  • 在 properties 元素体内指定的属性首先被读取。
  • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
  • 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
    从MyBatis 3.4.2开始,你可以为占位符指定一个默认值。

<dataSource type="POOLED">
  <property name="username" value="${username:ut_user}"/> <!-- If 'username' property not present, username become 'ut_user' -->
</dataSource>
    默认关闭,开启,可自定义分隔符
<properties resource="org/mybatis/example/config.properties">
  <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- Enable this feature -->
 <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Change default value of separator -->
</properties>

settings

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

typeAliases


<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/><!--bean-->
  <package name="domain.blog"/><!--package-->
</typeAliases>
     每一个在包  domain.blog  中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如  domain.blog.Author  的别名为  author ;若有注解,则别名为其注解值。(测试,首字母大写也可)
@Alias("author")
public class Author {
    ...
}
     已经为许多常见的 Java 类型内建了相应的类型别名,如int -> _int, Integer ->integer

typeHandlers

      无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型,如DateOnlyTypeHandler 将DB的Date转换成java的java.util.Date
     可自定义
@MappedJdbcTypes(JdbcType.VARCHAR)//JDBC type,或xml的typeHandler 中配置jdbcType="VARCHAR"(xml优先级高)
@MappedTypes(String.class)// java type,或xml的typeHandler 中配置 javaType="String"
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);
  }
}
     注入mybatis
    
<!-- mybatis-config.xml -->
<typeHandlers>
 <package name="org.mybatis.example"/><!--batch scan-->
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>
       当决定在 ResultMap 中使用某一TypeHandler时,此时java类型是已知的(从结果类型中获得),但是JDBC类型是未知的。 因此Mybatis使用 javaType=[TheJavaType], jdbcType=null 的组合来选择一个TypeHandler。 这意味着使用 @MappedJdbcTypes 注解可以 限制 TypeHandler的范围,同时除非显示的设置,否则TypeHandler在 ResultMap 中将是无效的。 如果希望在 ResultMap 中使用TypeHandler,那么设置 @MappedJdbcTypes 注解的 includeNullJdbcType=true 即可。 然而从Mybatis 3.4.0开始,如果 只有一个 注册的TypeHandler来处理Java类型,那么它将是 ResultMap 使用Java类型时的默认值(即使没有 includeNullJdbcType=true )。

Enum

  • EnumTypeHandler   默认,映射名称
  • EnumOrdinalTypeHandler  映射ordinal
     可在typeHandlers中统一配置或在单个result中配置typeHandler,可自定义枚举处理器

objectFactory

        MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。可自定义

// ExampleObjectFactory.java
public class ExampleObjectFactory extends DefaultObjectFactory {
  public Object create(Class type) {
    return super.create(type);
  }
  public Object create(Class type, List<Class> constructorArgTypes, List<Object> constructorArgs) {
    return super.create(type, constructorArgTypes, constructorArgs);
  }
  public void setProperties(Properties properties) {
    super.setProperties(properties);
  }
  public <T> boolean isCollection(Class<T> type) {
    return Collection.class.isAssignableFrom(type);
  }}
     配置

<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
  <property name="someProperty" value="100"/>
</objectFactory>

plugins

     MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

environments 

       MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者共享相同 Schema 的多个生产数据库, 想使用相同的 SQL 映射。许多类似的用例.

      如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个

  • 尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一
  • 每个数据库对应一个 SqlSessionFactory 实例
<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

databaseIdProvider

     MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃
<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>        
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

Mappers

     映射mapper
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<package name="org.mybatis.builder"/>
</mappers>


Mapper XML 文件


SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
  • cache – 给定命名空间的缓存配置。
  • cache-ref – 其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

select

insert,update,delete

     
<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">



sql

定义
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
引用
<select id="selectUsers" resultType="map">
  select
    <include refid="userColumns"><property name="alias" value="t1"/></include>,
    <include refid="userColumns"><property name="alias" value="t2"/></include>
  from some_table t1
    cross join some_table t2
</select>
     <property>中定义的属性sql中可以通过${}进行调用

Parameters

        当参数基本类型如int时,其参数名没有要求,当类型为对象时则需要正确匹配,但也可以设置别名.通过#{}调用(注意和${}的区别,后者一般使用不变的字符串),同时可以设置javaType,jdbcType,typeHandler,numericScale,resultMap,mode等值,对可能为空的列设置jdbcType是有必要的
 

Result Maps

         返回值resultType指定返回类型,儿resultMap则返回指定map,其格式
<resultMap id="userResultMap" type="User">
  <id property="id" column="user_id" />
  <result property="username" column="user_name"/>
  <result property="password" column="hashed_password"/>
</resultMap>
通过其id进行引用
<select id="selectUsers" resultMap="userResultMap">
  select user_id, user_name, hashed_password
  from some_table
  where id = #{id}
</select>

高级结果印射

印射语句
<!-- Very Complex Statement -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
  select
       B.id as blog_id,
       B.title as blog_title,
       B.author_id as blog_author_id,
       A.id as author_id,
       A.username as author_username,
       A.password as author_password,
       A.email as author_email,
       A.bio as author_bio,
       A.favourite_section as author_favourite_section,
       P.id as post_id,
       P.blog_id as post_blog_id,
       P.author_id as post_author_id,
       P.created_on as post_created_on,
       P.section as post_section,
       P.subject as post_subject,
       P.draft as draft,
       P.body as post_body,
       C.id as comment_id,
       C.post_id as comment_post_id,
       C.name as comment_name,
       C.comment as comment_text,
       T.id as tag_id,
       T.name as tag_name
  from Blog B
       left outer join Author A on B.author_id = A.id
       left outer join Post P on B.id = P.blog_id
       left outer join Comment C on P.id = C.post_id
       left outer join Post_Tag PT on PT.post_id = P.id
       left outer join Tag T on PT.tag_id = T.id
  where B.id = #{id}
</select>
印射结果集

<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="username" column="author_username"/>
    <result property="password" column="author_password"/>
    <result property="email" column="author_email"/>
    <result property="bio" column="author_bio"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>
ResultMap属性
  • id 唯一标识,用于标识一个result map
  • type类的全限定名
  • autoMapping 如果设置这个属性,MyBatis将会为这个ResultMap开启或者关闭自动映射。这个属性会覆盖全局的属性autoMappingBehavior。默认值为:unset
子集属性

  • constructor - 类在实例化时,用来注入结果到构造方法中
    • idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能
    • arg - 注入到构造方法的一个普通结果
  • id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能
  • result – 注入到字段或 JavaBean 属性的普通结果
  • association – 一个复杂的类型关联;许多结果将包成这种类型
    • 嵌入结果映射 – 结果映射自身的关联,或者参考一个
  • collection – 复杂类型的集
    • 嵌入结果映射 – 结果映射自身的集,或者参考一个
  • discriminator – 使用结果值来决定使用哪个结果映射
    • case – 基于某些值的结果映射
      • 嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。

id or result

  • property java类属性
  • column db列名
  • javaType  java类型
  • jdbcType  db类型
  • typeHandler 类型处理器
支持的jdbc类型

 以下用的少,略

constructor

     子集<arg>基本同result(参数名name,result是property)

association

     关联 ,通过id与result两个标签确定另一个关联类

collection

    作用类型association,但表示多个

discriminator 

     鉴别器类似switch


自动映射

      自动映射是默认开启(setting中设置autoMappingBehavior),指当查询列名与java类属性名一致就会自动映射(resultType就是运用自动),当查询不匹配时,我们就需要手动印射(使用resultMap)

      可以设置一些自动印射的策略,如通过setting设置mapUnderscoreToCamelCase,只是查询列名与驼峰式java属性匹配

      autoMappingBehavior有三种等级

  • NONE - 禁用自动映射。仅设置手动映射属性。
  • PARTIAL - 默认,将自动映射结果除了那些有内部定义内嵌结果映射的(joins).
  • FULL - 自动映射所有。
      对parttal或full 在resultMap中使用autoMapping="false"关闭自动印射(全局默认是开启)

cache

    通过BaseExecutor实现一级缓存,CachingExecutor实现二级缓存

     mybatis除了局部的session缓存,默认是开启二级缓存,但必须xml中使用<cache/>标签使用二级缓存

     一级缓存有session与statement,setting中通过localCacheScope设置

<setting name="localCacheScope" value="SESSION"/>  

  • session 默认,一个session内有效
  • statement 执行完mapper便清楚缓存
    开启二级缓存(默认开启)
<setting name="cacheEnabled" value="true" />
     使用二级缓存
<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>
     或(引用其他mapper的cache,夸mapper命中)
   
<cache-ref namespace="com.someone.application.data.SomeMapper"/>
    cache优先级高,配置cache,相关属性
  • blocking 默认false,查询加锁,-BlockingCache
  • eviction 回收策略 -PerpetualCache(LruCache,FifoCache...)
    • LRU – 默认,最近最少使用的:移除最长时间不被使用的对象。
    • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

  • flushInterval  清空缓存的时间间隔(ms),默认不清除 -ScheduleCache
  • readOnly 默认false ,false每次都获取缓存对象的拷贝(序列化)
  • size 缓存个数,LRU默认1024
  • type 缓存实现类,如LRU默认LruCache,可自定cache
     开启后,具体如何使用(以下均为默认值)
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>
     自定义cache
<cache type="com.domain.something.MyCustomCache">
  <property name="cacheFile" value="/tmp/my-custom-cache.tmp"/>
</cache>
     其中property 相当于set方法
     cache存储在内存中,java代码获取cache
Collection<Cache> caches =session.getConfiguration().getCaches();  
      当然可以使用地方缓存插件,比如 ehcache

动态SQL

      mybatis基于OGNL元素标签简化sql语句的拼写

if + where + choose,when,otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
 SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
    <choose>
    	<when test="title != null">
     	     AND title like #{title}
    	</when>
    	<when test="author != null and author.name != null">
     	      AND author_name like #{author.name}
   	 </when>
   	 <otherwise>
     	      AND featured = 1
          </otherwise>
     </choose>
  </where>
</select>

trim

      trim定义一个语句的开头以及忽略的结尾,以下等价于where,set的trim
#set
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

#where
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>
      prefix前缀, prefixOverrides忽略的后缀

foreach

     循环
<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文
<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

Multi-db vendor support


    一个配置了“_databaseId”变量的 databaseIdProvider 对于动态代码来说是可用的,这样就可以根据不同的数据库厂商构建特定的语句
       
<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>

  Logging

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。 如果一个都未找到,日志功能就会被禁用。

配置

<configuration>
  <settings>
    ...
    <setting name="logImpl" value="LOG4J"/>
    ...
  </settings>
</configuration>
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值