Mybatis总结一(mybatis-config.xml详细配置解析、XML配置和注解配置实现CRUD、Mybatis详细执行流程、日志(STDOUT_LOGGING和LOG4J)、多种分页方法等)

一、Mybatis简介

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

Mybatis官方中文文档:https://mybatis.org/mybatis-3/zh/index.html

Maven仓库:https://mvnrepository.com/artifact/org.mybatis/mybatis

Q:什么是持久化?

A:数据持久化,即将程序的数据在持久状态和瞬时状态转化的过程。

Q:什么是持久层?

A:完成持久化工作的代码块,层的界限是十分明显的。

Q:Mybatis优点?

A:

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql。

二、基础使用流程

  1. 创建父项目

  2. 导入依赖

            <!-- https://mvnrepository.com/artifact/junit/junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13.1</version>
                <scope>test</scope>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.6</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.22</version>
            </dependency>
    
  3. 创建子项目

在这里插入图片描述

  1. 在resources中创建Mybatis配置文件,文件名一般默认为mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url"
                              value="jdbc:mysql://localhost:3306/computer03?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="niushijian"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/ola/dao/AuthorMapper.xml"/>
        </mappers>
    </configuration>
    
  2. 编写工具类MybatisUtils

    package com.ola.utils;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * ClassName:MybatisUtils Package:com.ola.utils
     *
     * @author morningj
     * @date 2021/1/10 15:39
     */
    public class MybatisUtils {
      private static SqlSessionFactory sqlSessionFactory;
    
      static {
        try {
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    
      public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
      }
    }
    
    
  3. 编写代码

    • 实体类

      package com.ola.pojo;
      
      /**
       * ClassName:Author Package:com.ola.pojo
       *
       * @author morningj
       * @date 2021/1/10 15:50
       */
      public class Author {
        private String AuthorID;
        private String Name;
      
        public Author(String authorID, String name) {
          AuthorID = authorID;
          Name = name;
        }
      
        public Author() {}
      
        @Override
        public String toString() {
          return "Author{" + "AuthorID='" + AuthorID + '\'' + ", Name='" + Name + '\'' + '}';
        }
      
        public String getAuthorID() {
          return AuthorID;
        }
      
        public void setAuthorID(String authorID) {
          AuthorID = authorID;
        }
      
        public String getName() {
          return Name;
        }
      
        public void setName(String name) {
          Name = name;
        }
      }
      
    • Dao接口

      package com.ola.dao;
      
      import com.ola.pojo.Author;
      
      import java.util.List;
      
      /**
       * ClassName:AuthorDao Package:com.ola.dao
       *
       * @author morningj
       * @date 2021/1/10 15:52
       */
      public interface AuthorDao {
        List<Author> getAuthorList();
      }
      
    • AuthorMapper.xml(即原来的Dao接口实现类)

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.ola.dao.AuthorDao">
          <select id="getAuthorList" resultType="com.ola.pojo.Author">
              select *
              from computer03.Name
          </select>
      </mapper>
      

      对命名空间的补充

      命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

      命名解析

      ​ 为了减少输入量,MyBatis 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。

      • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
      • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
  4. 测试

    package com.ola.dao;
    
    import com.ola.pojo.Author;
    import com.ola.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    /**
    
     * ClassName:AuthorDaoTest Package:com.ola.dao
       *
    
     * @author morningj
    
     * @date 2021/1/10 16:08
       */
       public class AuthorDaoTest {
         @Test
         public void test() {
       // 获取session对象
       SqlSession sqlSession = MybatisUtils.getSqlSession();
    
       // 方式一
       AuthorDao mapper = sqlSession.getMapper(AuthorDao.class);
       List<Author> authorList = mapper.getAuthorList();
    
       // 方式二(不推荐使用)
       // List<Author> authorsList = sqlSession.selectList("com.ola.dao.AuthorDao.getAuthorList");
       // for (Author author : authorsList) {
       //   System.out.println(author);
       // }
    
       for (Author author : authorList) {
         System.out.println(author);
       }
       sqlSession.close();
         }
       }
    

可能遇到的问题

  1. 配置文件没有注册
  2. 绑定接口错误
  3. 方法名不对
  4. 返回类型不对
  5. url写错
  6. 由于权限问题resources中的配置文件无法导出

对象生命周期和作用域

错误使用会导致非常严重的并发问题

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

三、使用XML配置实现CRUD

  1. namespace
  2. select
    1. id:就是对应的namespace中的方法名
    2. resultType:返回的类型,例如:com.ola.pojo.Author
    3. parameterType:参数类型

INSERT:注意增删改需要提交事务,才能完成增删改操作!!!

    <insert id="addAuthor" parameterType="com.ola.pojo.Author">
        insert into computer03.Name(AuthorID, Name)
        values (#{AuthorID}, #{Name});
    </insert>
@Test
  public void addAuthor() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
    mapper.addAuthor(new Author("12345678-1", "olarian"));
    sqlSession.commit();
    sqlSession.close();
  }

UPDATE:注意增删改需要提交事务,才能完成增删改操作!!!

<update id="updateAuthor" parameterType="com.ola.pojo.Author">
        update computer03.Name
        set AuthorID =#{AuthorID},
            Name=#{Name}
        where AuthorID = #{AuthorID};
    </update>
@Test
  public void updateAuthor() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
    mapper.updateAuthor(new Author("12345678-1", "ola"));
    sqlSession.commit();
    sqlSession.close();
  }

DELETE:注意增删改需要提交事务,才能完成增删改操作!!!

<delete id="deleteAuthor" parameterType="String">
        delete
        from computer03.Name
        where AuthorID = #{id};
    </delete>
@Test
  public void deleteAuthor() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
    mapper.deleteAuthor("12345678-1");
    sqlSession.commit();
    sqlSession.close();
  }

四、配置解析

官方文档:https://mybatis.org/mybatis-3/zh/configuration.html

  1. 核心配置文件(在xml中严格遵守以下顺序)

    • mybatis-config.xml
    • mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
      • properties(属性):这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置.【db.properties】
      • settings(设置):这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
      • typeAliases(类型别名)
      • typeHandlers(类型处理器)
      • objectFactory(对象工厂)
      • plugins(插件)
      • environments(环境配置)
      • environment(环境变量)
      • transactionManager(事务管理器):在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]")
      • dataSource(数据源):有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]")
      • databaseIdProvider(数据库厂商标识)
      • mappers(映射器)
  2. properties(属性):这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置.【db.properties】

    优先级:外部配置文件>内部属性引入

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/computer03?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username=root
    password=niushijian
    

    在核心配置文件中引入:

    <!--注意,在xml文件中,标签是有先后顺序的,放错顺序会报错,properties放在configuration的首位-->
    <properties resource="db.properties"/>
    
    <environment id="test">
                <transactionManager type="JDBC"/>
                <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>
    
  3. typeAliases(类型别名)

    类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

        <select id="getAuthorList" resultType="com.ola.pojo.Author">
            select *
            from computer03.Name
        </select>
    
        <select id="getAuthorById" resultType="com.ola.pojo.Author" parameterType="String">
            select *
            from computer03.Name
            where AuthorID = #{id};
        </select>
    
        <insert id="addAuthor" parameterType="com.ola.pojo.Author">
            insert into computer03.Name(AuthorID, Name)
            values (#{AuthorID}, #{Name});
        </insert>
    
        <update id="updateAuthor" parameterType="com.ola.pojo.Author">
            update computer03.Name
            set AuthorID =#{AuthorID},
                Name=#{Name}
            where AuthorID = #{AuthorID};
        </update>
        <delete id="deleteAuthor" parameterType="String">
            delete
            from computer03.Name
            where AuthorID = #{id};
        </delete>
    

    这里的parameterType和resultType都需要完全限定名,这就产生了冗余,为解决这个问题,使用typeAliases!

    <typeAliases>
        <typeAlias type="com.ola.pojo.Author" alias="Author"/>
    </typeAliases>
    

    也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,例如:

    <typeAliases>
        <package name="com.ola.pojo"/>
    </typeAliases>
    

    每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;若有注解,则别名为其注解值。

    @Alias("author")
    public class Author {
        ...
    }
    
  4. settings(设置):这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

    设置名描述有效值默认值
    cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
    lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
    aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
    multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
    useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
    useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
    autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
    autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARNFAILING: 映射失败 (抛出 SqlSessionException)NONE, WARNING, FAILINGNONE
    defaultExecutorType配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。SIMPLE REUSE BATCHSIMPLE
    defaultStatementTimeout设置超时时间,它决定数据库驱动等待数据库响应的秒数。任意正整数未设置 (null)
    defaultFetchSize为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。任意正整数未设置 (null)
    defaultResultSetType指定语句默认的滚动策略。(新增于 3.5.2)FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置)未设置 (null)
    safeRowBoundsEnabled是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。true | falseFalse
    safeResultHandlerEnabled是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。true | falseTrue
    mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
    localCacheScopeMyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。SESSION | STATEMENTSESSION
    jdbcTypeForNull当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。OTHER
    lazyLoadTriggerMethods指定对象的哪些方法触发一次延迟加载。用逗号分隔的方法列表。equals,clone,hashCode,toString
    defaultScriptingLanguage指定动态 SQL 生成使用的默认脚本语言。一个类型别名或全限定类名。org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
    defaultEnumTypeHandler指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5)一个类型别名或全限定类名。org.apache.ibatis.type.EnumTypeHandler
    callSettersOnNulls指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。true | falsefalse
    returnInstanceForEmptyRow当返回行的所有列都是空时,MyBatis默认返回 null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2)true | falsefalse
    logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
    logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
    proxyFactory指定 Mybatis 创建可延迟加载对象所用到的代理工具。CGLIB | JAVASSISTJAVASSIST (MyBatis 3.3 以上)
    vfsImpl指定 VFS 的实现自定义 VFS 的实现的类全限定名,以逗号分隔。未设置
    useActualParamName允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1)true | falsetrue
    configurationFactory指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3)一个类型别名或完全限定类名。未设置
    shrinkWhitespacesInSql从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5)true | falsefalse
    defaultSqlProviderTypeSpecifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type(or value) attribute on sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.A type alias or fully qualified class nameNot set

    一个配置完整的 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>
    
  5. mappers(映射器)

    • 方式一:使用相对于类路径的资源引用(推荐)

      <mappers>
          <mapper resource="com/ola/dao/AuthorMapper.xml"/>
      </mappers>
      
    • 方式二:使用映射器接口实现类的完全限定类名(不推荐,会出问题,如:不在一个包下;类名和xml名不同)

      <mappers>
        <mapper class="com.ola.dao.AuthorMapper"/>
      </mappers>
      
    • 方式三:将包内的映射器接口实现全部注册为映射器(不推荐,会出问题,如:不在一个包下;类名和xml名不同)

      <mappers>
        <package name="com.ola.dao"/>
      </mappers>
      

五、ResultMap结果集映射:用来解决属性名和字段名不一致的问题

​ ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

    
		<resultMap id="AuthorMap" type="Author">
        <result column="AuthorID" property="id"/>
		</resultMap>

    <select id="getAuthorById"  parameterType="String" resultMap="AuthorMap">
        select *
        from computer03.Name
        where AuthorID = #{id};
    </select>

六、日志

  1. 日志工厂

    如果一个数据库操作出现了异常,我们需要排除错误,就要使用日志!

    设置名描述有效值默认值
    logPrefix指定 MyBatis 增加到日志名称的前缀。任何字符串未设置
    logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
    • SLF4J
    • LOG4J
    • LOG4J2
    • JDK_LOGGING
    • COMMONS_LOGGING
    • STDOUT_LOGGING (标准日志输出)
    • NO_LOGGING

    在Mybatis中具体使用哪个日志需要再settings中设定!

    STDOUT_LOGGING (标准日志输出):

    Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    Opening JDBC Connection
    Created connection 1008315045.
    Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5]
    ==>  Preparing: select * from computer03.Name where AuthorID = ?;
    ==> Parameters: 12345678-1(String)
    <==    Columns: AuthorID, Name
    <==        Row: 12345678-1, olarian
    <==      Total: 1
    Author{AuthorID='12345678-1', Name='olarian'}
    Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5]
    Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3c19aaa5]
    Returned connection 1008315045 to pool.
    

    LOG4J

    1. 导包

              <!-- https://mvnrepository.com/artifact/log4j/log4j -->
              <dependency>
                  <groupId>log4j</groupId>
                  <artifactId>log4j</artifactId>
                  <version>1.2.17</version>
              </dependency>
      
    2. 在resources中创建log4j.properties

      #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
      log4j.rootLogger=DEBUG,console,file
      
      #控制台输出的相关设置
      log4j.appender.console = org.apache.log4j.ConsoleAppender
      log4j.appender.console.Target = System.out
      log4j.appender.console.Threshold=DEBUG
      log4j.appender.console.layout = org.apache.log4j.PatternLayout
      log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
      
      #文件输出的相关设置
      log4j.appender.file = org.apache.log4j.RollingFileAppender
      log4j.appender.file.File=./log/Mybatis_study_ola.log
      log4j.appender.file.MaxFileSize=10mb
      log4j.appender.file.Threshold=DEBUG
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
      
      #日志输出级别
      log4j.logger.org.mybatis=DEBUG
      log4j.logger.java.sql=DEBUG
      log4j.logger.java.sql.Statement=DEBUG
      log4j.logger.java.sql.ResultSet=DEBUG
      log4j.logger.java.sql.PreparedStatement=DEBUG
      
    3. 在mybatis-config.xml中配置settings为LOG4J日志实现

          <settings>
              <setting name="logImpl" value="LOG4J"/>
          </settings>
      
    4. LOG4J的使用

      • 简单使用
      [org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
      [org.apache.ibatis.logging.LogFactory]-Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-PooledDataSource forcefully closed/removed all connections.
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Opening JDBC Connection
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-Created connection 30578394.
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
      [com.ola.dao.AuthorMapper.getAuthorById]-==>  Preparing: select * from computer03.Name where AuthorID = ?;
      [com.ola.dao.AuthorMapper.getAuthorById]-==> Parameters: 12345678-1(String)
      [com.ola.dao.AuthorMapper.getAuthorById]-<==      Total: 1
      Author{AuthorID='12345678-1', Name='olarian'}
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
      [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
      [org.apache.ibatis.datasource.pooled.PooledDataSource]-Returned connection 30578394 to pool.
      
      • 类中使用

        // 注意这里导入的Logger包应该为org.apache.log4j.Logger
        static Logger logger = Logger.getLogger(AuthorMapperTest.class);
        
          @Test
          public void log4jTest() {
            logger.info("---------info:进入了TESTLOG4J方法!!---------");
            logger.debug("---------debug:进入了TESTLOG4J方法!!---------");
            logger.error("---------error:进入了TESTLOG4J方法!!---------");
          }
        
        [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
        [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Opening JDBC Connection
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Created connection 30578394.
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==>  Preparing: select * from computer03.Name where AuthorID = ?;
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Parameters: 12345678-1(String)
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]<==      Total: 1
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Returned connection 30578394 to pool.
        [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
        [DEBUG][21-01-11][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]PooledDataSource forcefully closed/removed all connections.
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Opening JDBC Connection
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Created connection 30578394.
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==>  Preparing: select * from computer03.Name where AuthorID = ?;
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]==> Parameters: 12345678-1(String)
        [DEBUG][21-01-11][com.ola.dao.AuthorMapper.getAuthorById]<==      Total: 1
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][org.apache.ibatis.transaction.jdbc.JdbcTransaction]Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1d296da]
        [DEBUG][21-01-11][org.apache.ibatis.datasource.pooled.PooledDataSource]Returned connection 30578394 to pool.
        [INFO][21-01-11][dao.AuthorMapperTest]---------info:进入了TESTLOG4J方法!!---------
        [DEBUG][21-01-11][dao.AuthorMapperTest]---------debug:进入了TESTLOG4J方法!!---------
        [ERROR][21-01-11][dao.AuthorMapperTest]---------error:进入了TESTLOG4J方法!!---------
        

    七、实现分页

    Q:为什么要分页?

    A:为了减少数据的处理量

    • 使用Limit分页,语法:select * from Table limit startIndex,pageSize;

    • 使用Mybatis实现分页

      1. 接口

          List<Author> getAuthorByLimit(Map<String, Integer> map);
        
      2. Mapper.xml

            <select id="getAuthorByLimit" resultType="Author" parameterType="map">
                select *
                from computer03.Name
                limit #{startIndex},#{pageSize};
            </select>
        
      3. 测试

          @Test
          public void getAuthorByLimit() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
            HashMap<String, Integer> map = new HashMap<>();
            map.put("startIndex", 0);
            map.put("pageSize", 15);
            List<Author> authorByLimit = mapper.getAuthorByLimit(map);
            for (Author author : authorByLimit) {
              System.out.println(author);
            }
            sqlSession.close();
          }
        
    • 使用RowBounds实现分页(不推荐使用)

      1. 接口

          List<Author> getAuthorByRowBounds();
        
      2. Mapper.xml

            <select id="getAuthorByRowBounds" resultType="Author">
                select *
                from computer03.Name
            </select>
        
      3. 测试

          @Test
          public void getAuthorByRowBounds() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            RowBounds rowBounds = new RowBounds(0, 3);
            List<Author> authorList =
                sqlSession.selectList("com.ola.dao.AuthorMapper.getAuthorByRowBounds", null, rowBounds);
            for (Author author : authorList) {
              System.out.println(author);
            }
            sqlSession.close();
          }
        
    • 使用分页插件 Mybatis PageHelper

      1. 引入Jar包

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
        </dependency>
        
      2. 配置拦截器插件

        <!--
            plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
            properties?, settings?,
            typeAliases?, typeHandlers?,
            objectFactory?,objectWrapperFactory?,
            plugins?,
            environments?, databaseIdProvider?, mappers?
        -->
        <plugins>
            <!-- com.github.pagehelper为PageHelper类所在包名 -->
            <plugin interceptor="com.github.pagehelper.PageInterceptor">
                <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
                <property name="param1" value="value1"/>
        	</plugin>
        </plugins>
        
      3. 分页插件参数介绍

八、使用注解开发

底层实现机制:反射(动态代理)

  1. 增加接口

    public interface AuthorMapper {
      @Select("select * from computer03.Name limit 0,15")
      List<Author> getAuthors();
    }
    
  2. 绑定接口

        <mappers>
            <mapper class="com.ola.dao.AuthorMapper"/>
        </mappers>
    
  3. 测试

    package com.ola.dao;
    
    import com.ola.pojo.Author;
    import com.ola.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    /**
     * ClassName:authorTest Package:com.ola.dao
     *
     * @author morningj
     * @date 2021/1/11 12:34
     */
    public class authorTest {
      @Test
      public void getAuthors() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
        List<Author> authors = mapper.getAuthors();
        for (Author author : authors) {
          System.out.println(author);
        }
        sqlSession.close();
      }
    }
    

Attention: 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

九、Mybatis详细执行流程

在这里插入图片描述

十、使用注解实现增删改查CRUD

  • SELECT:

      @Select("select * from computer03.Name where AuthorID = #{id}")
      Author getAuthorById(@Param("id") String id);
    
      @Test
      public void getAuthorById() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
        Author authorById = mapper.getAuthorById("12345678-1");
        System.out.println(authorById);
        sqlSession.close();
      }
    
  • INSERT:

    • 法一
      @Insert("insert into computer03.Name(AuthorID,Name) values(#{id},#{name})")
      void addAuthor(@Param("id") String authorID, @Param("name") String name);
    
      @Test
      public void addAuthor() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
        mapper.addAuthor("12345678-2", "niushijian");
        sqlSession.close();
      }
    
    • 法二

        @Insert("insert into computer03.Name(AuthorID,Name) values(#{AuthorID},#{Name})")
        void addAuthor02(Author author);
      
        @Test
        public void addAuthor() {
          SqlSession sqlSession = MybatisUtils.getSqlSession();
          AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
          mapper.addAuthor02(new Author("12345678-3", "olarional"));
          sqlSession.close();
        }
      
  • UPDATE:

      @Update("update computer03.Name set AuthorID=#{AuthorID},Name=#{Name} where AuthorID=#{AuthorID}")
      void updateAuthor(Author author);
    
      @Test
      public void updateAuthor() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
        mapper.updateAuthor(new Author("12345678-3", "o"));
        sqlSession.close();
      }
    
  • DELETE:

      @Delete("delete from computer03.Name where AuthorID=#{deleteId}")
      void deleteAuthor(@Param("deleteId") String id);
    
      @Test
      public void deleteAuthor() {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        AuthorMapper mapper = sqlSession.getMapper(AuthorMapper.class);
        mapper.deleteAuthor("12345678-4");
        sqlSession.close();
      }
    

    关于@Param()注解

    • 基本类型的参数或者String类型的参数,需要加上
    • 引用类型不需要加
    • 如果只有一个基本类型的话,可以忽略,但是还是建议加上
    • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名

    关于==#{}${}==的区别

    #是预编译的,相当于PreparedStatement!一般会使用#{}来防止SQL注入问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值