1.Mybatis

MyBatis 本来是apache的一个开源软件iBatis,2010年这一工程由Apache Software Foundation转移到Google Code,而且更名为MyBatis,2013年11月转移到GitHub。它是一款出色的持久层架构,它支撑自定 SQL、sql语句及其高級投射(ORM),适用XML或是注释来配制和投射原生态种类、插口和java的POJO(Plain Old Java Objects,一般传统的Java目标)数据库查询中的纪录。。

2.免费下载MyBatis

2.1.github

https://github.com/mybatis/mybatis-3/releases

image-20210816153745328

2.2Maven库房

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

3.新手入门

3.1推动与依靠

选用mavenhttps://search.maven.org/ 查看有关的推动。

image-20210816171241868

<dependencies>
    <!--dependency>
      <groupId>org.wyl</groupId>
      <artifactId>[the artifact id of the block to be mounted]</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency-->
    <!-- mysql推动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.18</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.5</version>
    </dependency>
    <!-- 融合log4j -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.4</version>
    </dependency>
      <!-- 检测junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

右键pom.xml->meave 重新加载新项目。包免费下载完就可以。

将 mybatis-x.x.x.jar 文档放置 classpath 中就可以。

3.2.MyBatis的作用构架

3.2.1.构架

img

API插口层:给予给外界应用的插口API,开发者根据这种当地API来操作数据库查询。插口层一接受到启用要求便会启用数据处理方法层来进行主要的数据处理方法。
数据处理方法层:承担主要的SQL搜索、SQL分析、SQL实行和运行結果投射解决等。它具体的效果是依据启用的要求进行一次数据库操作。

  • 主要参数投射(主要参数分析和主要参数关联):获得并解析映射文档中的 Statement标识以及特性(parameterType)。也就是分析SQL句子并为 SQL句子提前准备必须完成关联的主要参数
  • SQL分析:对 Statement【 <select><update><delete><insert>】标识中的具体内容开展分析、拼凑、封裝,最终获得一个完全的含有占位符的 SQL句子。也就是 JDBC中的提前准备 SQL句子的全过程
  • 結果投射(結果集分析和結果集解决):获得环境变量中的結果集种类,并开展数据转换,将ResultSet开展結果投射。也就是 JDBC中事件处理集的流程。

基本支撑点层:承担最根本的作用支撑点,包含联接管理方法、事务处理、配备载入和缓存文件解决,这种全是公用的物品,将她们提取出去做为最根本的部件。为顶层的数据处理方法层给予最根本的支撑点。

  • 管理方法 Mybatis与数据库系统的接口方式

  • 管理方法 Mybatis的事务管理

  • 载入 环境变量

  • Mybatis 查看缓存文件

3.2.2.全局性环境变量 mybatis-config

<?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标识 => 申明MyBatis关键配备 -->
<configuration>
    <!-- environments标识 => 设定MyBatis采用的条件信息内容 -->
    <environments default="development">
        <environment >
            <!-- transactionManager标签 => 事务处理 -->
            <transactionManager type="JDBC"/>         <!-- dataSource标识 => 配备数据库特性 -->
            <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>
    <!--将mapper投射文档申请注册到全局性环境变量中-->
    <mappers>
        <mapper resource="org/mybatis/example/WylMapper.xml"/>
    </mappers>
</configuration>
<?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标识 => 申明MyBatis关键配备 -->
<configuration>
    <!-- environments标识 => 设定MyBatis采用的条件信息内容 -->
    <environments default="development">
        <environment >
            <!-- transactionManager标签 => 事务处理 -->
            <transactionManager type="JDBC"/>
            <!-- dataSource标识 => 配备数据库特性 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/wyl?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=CST"/>
                <property name="username" value="nps"/>
                <property name="password" value="123.nps@zst"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mappers/userMapper.xml"/>
    </mappers>

</configuration>

3.2.3.SqlSessionFactory 对话加工厂

  • 根据Mybatis的配备信息内容,应用 SqlSessionFactoryBuilder搭建器,来搭建对话加工厂目标

  • SqlSessionFactory 建立了 Configuration目标,应用 Configuration目标来搭建SqlSession对话加工厂

  • SqlSessionFactoryBuilder搭建器应用了 Builder搭建者策略模式

  • SqlSessionFactory 对话加工厂,应用了加工厂策略模式

    public class MyBatisUtils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                // 界定XML关键环境变量途径信息内容
                String resource = "mybatis-config.xml";
                // 载入XML关键环境变量途径信息内容
                InputStream inputStream = Resources.getResourceAsStream(resource);
                // 得到创建对象SQLSessionFactory
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    	//启用SqlSessionFactory.openSession()方式 ,回到SqlSession目标
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    

3.2.4.SqlSession插口方式

程序流程根据SqlSession来使用数据库查询

  • SqlSession对外开放供应了一整套的增删的api,根据api来使用数据库查询
  • SqlSession还可以获得动态性的Mapper插口
  • SqlSession的修饰符是方式 等级的,也就是以建立到消毁务必确保在方式 内进行,留意一定要在方式 內部消毁sqlSession,千万别忘掉
  • sqlSession在采用完后一定要立即关掉,尤其是在Service层,会在一个方式 中一起应用好几个sqlSession,每一个sqlSession在用完后尽量在下一行编码就关掉,防止危害别的sqlSession。
//从 SqlSessionFactory 中获得 SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
List<Users> usersInfo = mapper.getUsersInfo();

还可以

try (SqlSession session = sqlSessionFactory.openSession()) {
  User user = (User) session.selectOne("org.mybatis.example.WylMapper.getUsersById",12);
  }

3.2.5.pojo层

相匹配的数据库表的dao层

package com.wyl.mybatis.pojo;

/**
 * @创建者 王延领
 * @建立時间 2021/8/16
 * 叙述
 **/
public class Users {
    private int id;
    private String username;
    private String password;
    private String email;
    private int gender;

    public Users() {
    }

    public Users(int id, String username, String password, String email, int gender) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Users{"  
                ", username='"   username   '\''  
                ", password='"   password   '\''  
                ", email='"   email   '\''  
                ", gender="   gender  
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }
}

迅速转化成构造方法get set 等的方式 ,空白右键转化成就可以

image-20210823153814340

3.2.6. dao层

与数据库系统互动有关编码,相匹配Mybatis的mapper插口

package com.wyl.mybatis.dao;
import com.wyl.mybatis.pojo.Users;
import java.util.List;
import java.util.Map;
/**
 * @创建者 王延领
 * @建立時间 2021/8/18
 * 叙述
 **/
public interface UserDao {
    // 【select】全部客户信息
    List<Users> getUsersInfo();

    // 【select】特定客户信息
    Users getUserInfoById(int id);

    // 【update】特定客户信息
    int updateUseInfoById(Users user);

    // 【insert】特定客户信息
    int insertUser(Users user);

    // 【delete】特定客户信息
    int deleteUserById(int id);

    // 【insert】 大批量客户信息
    int insertManyUseList(List<Users> users);

    // 【select】 模糊搜索
    List<Users> getUsersInfoByPhantomSelect(String username);
}

3.2.7.mapper

image-20210823155011994

userMapper.xml配备相应的数据库操作投射,在mybatis-config开展申请注册。

<!--如下图所示配备-->
<mappers>
    <mapper resource="mappers/usersMapper.xml"/>
</mappers>

mapper以下。

<?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】: 特定dao层,关联Dao -->
<mapper namespace="com.wyl.mybatis.dao.UserDao">
    <!-- select sql: 关联getUsersInfo方式 ,回到全部客户信息【id】: 关联Dao中的方式 名
				【resultType】: 特定相匹配【类的方式】回到結果集的种类 -->
    <select  resultType="com.wyl.mybatis.pojo.Users">
        select * from users
    </select>
  </mapper>

检测:

 @Test
    public void getUsersInfo() {
        // 启用MyBatisUtils.getSqlSession()方式 ,获得SqlSession目标
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        // 启用获得到的SQLSession目标中的getMapper目标
        // 反射面Dao插口,动态代理Dao插口中的方式 ,并将这种方式 存有目标【mapper】中
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        // 启用mapper中相匹配方式 ,并设定相应的目标来接受其回到結果
        // 下列为测试标准getUsersInfo() => 获得全部Users表格中信息内容,并且用相匹配类接受
        List<Users> usersInfo = mapper.getUsersInfo();
        // for循环解析xml輸出List结合
        for (Users users : usersInfo) {
            System.out.println(users);
        }
        // 关掉sqlSession
        sqlSession.close();
    }

3.3.修饰符与生命期

image-20210823173846319

3.3.1.SqlSessionFactoryBuilder

这一类能够 被创建对象、应用和丢掉,一旦建立了 SqlSessionFactory,就不会必须它了。 因而 SqlSessionFactoryBuilder 案例的最好修饰符是方式 修饰符(也就是部分方式 自变量)。 你能器重 SqlSessionFactoryBuilder 来建立好几个 SqlSessionFactory 案例,但尽量還是不必一直保存着它,以确保任何的 XML 分析資源能够被施放给更主要的事儿。

3.3.2.SqlSessionFactory

SqlSessionFactory 一旦被建立就应当在使用的运作期内一直存有,沒有任何借口丢掉它或再次建立另一个案例。类似数据库查询数据库连接池。 应用 SqlSessionFactory 的最佳实践是在运用运作期内不必反复建立数次,数次复建 SqlSessionFactory 被视作一种编码“不良习惯”。因而 SqlSessionFactory 的最好修饰符是运用修饰符。 有很多方式 能够保证,非常简单的也是应用单例设计模式或是静态数据单例设计模式

3.3.3.SqlSession

每一个进程都需要有它自身的 SqlSession 案例。SqlSession 的案例并不是线程安全的,因而是不可以被共享资源的,因此 它的最合适的修饰符是要求方式 修饰符。 肯定无法将 SqlSession 案例的引入放到一个类的静态数据域,乃至一个类的实例变量也不好。 也决不能将 SqlSession 案例的引入放到一切种类的代管修饰符中,例如 Servlet 架构中的 HttpSession。 假如现在已经应用一种 Web 架构,考虑到将 SqlSession 放到一个和 HTTP 要求类似的修饰符中。 也就是说,每一次接到 HTTP 要求,就可以开启一个 SqlSession回到一个回应后,就关掉它。 这一关掉实际操作很重要,为了更好地保证每一次都能实行关掉实际操作,你应该把这个关掉实际操作放进 finally 块中。

3.3.4.Mapper

是一种建立的用以关联投射句子的插口,Mapper 插口的例子是用 SqlSession 来得到的。一样,在技术上而言,最普遍的 Mapper 案例修饰符像 SqlSession 一样,应用要求修饰符。准确地说,在方式 被启用的过程中启用 Mapper 案例,随后应用后,就全自动消毁掉不用应用确立的销户。当一个要求实行恰当准确的情况下,像 SqlSession 一样,你能毫不费力地操纵这一切。维持简易性,维持 Mapper 在方式 体修饰符内。

4.xml 配备分析

MyBatis 的环境变量包括了会深深地危害 MyBatis 个人行为的安装和特性信息内容。 配备文本文档的高层构造以下:

<?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>
    <!-- 特性:界定配备外在化 -->
    <properties></properties>
    <!-- 设定:界定mybatis的一些全面性设定 -->
    <settings>
       <!-- 实际的主要参数名和变量值 -->
       <setting name="" value=""/> 
    </settings>
    <!-- 种类名字:为一些类界定别称 -->
    <typeAliases></typeAliases>
    <!-- 种类CPU:界定Java类型与数据表中的基本数据类型中间的转化关联 -->
    <typeHandlers></typeHandlers>
    <!-- 目标加工厂 -->
    <objectFactory type=""></objectFactory>
    <!-- 软件:mybatis的软件,软件能够 改动mybatis的內部运作标准 -->
    <plugins>
       <plugin interceptor=""></plugin>
    </plugins>
    <!-- 自然环境:配备mybatis的自然环境 -->
    <environments default="">
       <!-- 系统变量:能够 配备好几个系统变量,例如应用多数据库时,就必须配备好几个系统变量 -->
       <environment >
          <!-- 事务管理管理工具 -->
          <transactionManager type=""></transactionManager>
          <!-- 数据库 -->
          <dataSource type=""></dataSource>
       </environment> 
    </environments>
    <!-- 数据库查询生产商标志 -->
    <databaseIdProvider type=""></databaseIdProvider>
    <!-- 映射器:特定投射文档或是投射类 -->
    <mappers></mappers>
</configuration>

image-20210823161021441

​ 照片来源于官方网站

4.1.特性(properties)

这种特性能够在外界开展配备,并能够实现动态性更换。你既能够在常见的 Java 特性文档中配备这种特性,还可以在 properties 原素的子原素中设定.

例如第三章的环境变量我们可以以下书写

<!-- properties标识 => 载入外界properties文件 -->
    <properties resource="dataSource.properties">
        <property name="username" value="root"/>
        <property name="password" value="123"/>
    </properties>
<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

这一事例中的username和password可能由properties元素中设定的相对应值来更换。driver和url特性可能由dataSource.properties文件中相对应的值来更换。那样就为配备给予了众多灵便挑选。

image-20210823162924181

特性还可以被传送到SqlSessionBuilder.build()方式 中。

SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);
// ... or ...
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);

可是,这也就涉及到到优先的难题,假如特性不只在一个地区配备,那麼mybatis可能依照接下来的次序来载入:
1.在properties元素身体特定的特性最先被载入。

  1. 随后依据properties元素中的resource特性载入类途径下特性文档或依据url特性特定的途径载入特性文档,并遮盖已载入的同名的特性。
  2. 最终载入做为方式 参数传递的特性,并遮盖已载入的同名的特性。

根据方式 参数传递的特性具备最大优先,resource/url 特性中规定的环境变量其次,最低优先级队列的则是 properties 原素中规定的特性

从 MyBatis 3.4.2 逐渐,你能为占位符特定一个初始值。比如:

<dataSource type="POOLED">
  <!-- ... -->
  <property name="username" value="${username:ut_user}"/> <!-- 假如特性 'username' 沒有被配备,'username' 特性的值将为 'ut_user' -->
</dataSource>

这一特点默认设置 是关掉的。要开启这一特点,必须加上一个特殊的特性来打开这一特点。比如:

<properties resource="org/mybatis/example/config.properties">
  <!-- ... -->
  <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- 开启初始值特点 -->
</properties>

4.2.设定(settings)

一个配备详细的 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>

这也是 MyBatis 中极其重要的更改设定,他们会更改 MyBatis 的运作时个人行为。 下表叙述了设定中各类设定的含意、初始值等。

设定名 叙述 有效值 初始值
cacheEnabled 全面性地打开或关上全部映射器环境变量中已配制的一切缓存文件。 true | false true
lazyLoadingEnabled 延迟时间载入的全局性电源开关。当打开时,全部关系目标都是会延迟时间载入。 特殊关联性中可根据设定 fetchType 特性来遮盖此项的按钮情况。 true | false false
aggressiveLazyLoading 打开时,任一方式 的启用都是会载入该目标的全部延迟时间载入特性。 不然,每一个延迟时间载入特性会按需载入(参照 lazyLoadTriggerMethods)。 true | false false (在 3.4.1 及以前的新版本中默认设置 为 true)
multipleResultSetsEnabled 是不是容许单独句子回到多結果集(必须数据库查询推动适用)。 true | false true
useColumnLabel 应用列标识替代字段名。具体主要表现取决于数据库查询推动,实际可参照数据库查询推动的有关文本文档,或根据比照检测来观察。 true | false true
useGeneratedKeys 容许 JDBC 适用自动生成外键约束,必须数据库查询推动适用。假如设定为 true,将强制性应用自动生成外键约束。虽然一些数据库查询推动不兼容此特点,但仍可一切正常工作中(如 Derby)。 true | false False
autoMappingBehavior 特定 MyBatis 应怎样全自动投射列到字段名或特性。 NONE 表明关掉全自动投射;PARTIAL 只能全自动投射沒有界定嵌入結果投射的字段名。 FULL 会全自动投射一切繁杂的結果集(不管是不是嵌入)。 NONE, PARTIAL, FULL PARTIAL
autoMappingUnknownColumnBehavior 特定发觉全自动投射总体目标不明列(或不明特性种类)的个人行为。NONE: 不做一切反映WARNING: 輸出警示日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志级别务必设定为 WARNFAILING: 投射不成功 (抛出去 SqlSessionException) NONE, WARNING, FAILING NONE
defaultExecutorType 配备默认设置 的电动执行机构。SIMPLE 便是一般的电动执行机构;REUSE 电动执行机构会器重预备处理句子(PreparedStatement); BATCH 电动执行机构不但器重句子还会继续实行批量更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 设定请求超时時间,它决策数据库查询推动等候数据库查询回应的分秒。 随意整数 未设定 (null)
defaultFetchSize 为推动的結果集获得总数(fetchSize)设定一个提议值。此参数只能够在查看设定中被遮盖。 随意整数 未设定 (null)
defaultResultSetType 特定句子默认设置 的翻转对策。(增加于 3.5.2) FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(相当于未设定) 未设定 (null)
safeRowBoundsEnabled 是不是可以在嵌入句子中应用分页查询(RowBounds)。假如容许应用则设定为 false。 true | false False
safeResultHandlerEnabled 是不是可以在嵌入句子中应用結果CPU(ResultHandler)。假如容许应用则设定为 false。 true | false True
mapUnderscoreToCamelCase 是不是打开驼峰命名全自动投射,即从經典数据库查询字段名 A_COLUMN 投射到經典 Java 特性名 aColumn。 true | false False
localCacheScope MyBatis 运用当地缓存文件体制(Local Cache)避免循环引用和加快反复的嵌入查看。 初始值为 SESSION,会缓存文件一个对话中实行的任何查看。 若设定数值 STATEMENT,当地缓存文件将仅用以实行句子,对同样 SqlSession 的不一样查看将不容易开展缓存文件。 SESSION | STATEMENT SESSION
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 | false false
returnInstanceForEmptyRow 当回到行的全部列全是空时,MyBatis默认设置 回到 null。 当打开这一设定时,MyBatis会回到一个空案例。 一定要注意,它也适用嵌入的結果集(如结合或关系)。(增加于 3.4.2) true | false false
logPrefix 特定 MyBatis 提升到日志名字的作为前缀。 一切字符串数组 未设定
logImpl 特定 MyBatis 常用日志的主要完成,未找到时将全自动搜索。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设定
proxyFactory 特定 Mybatis 建立可延迟时间载入目标常用到的代理工具。 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 之上)
vfsImpl 特定 VFS 的完成 自定 VFS 的完成的类全限制名,以分号隔开。 未设定
useActualParamName 容许操作方法签字中的名字做为句子主要参数名字。 为了更好地应用该特点,你的工程项目务必选用 Java 8 编译程序,而且再加上 -parameters 选择项。(增加于 3.4.1) true | false true
configurationFactory 特定一个给予 Configuration 案例的类。 这一被回到的 Configuration 案例用于载入被反序列化目标的延时载入特性值。 这一类务必包括一个签字为static Configuration getConfiguration() 的方式 。(增加于 3.2.3) 一个种类别称或彻底限制类名。 未设定
shrinkWhitespacesInSql 从SQL中删掉不必要的空格字符。一定要注意,这也会危害SQL中的文本字符串数组。 (增加于 3.5.5) true | false false
defaultSqlProviderType Specifies 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 name Not set

4.3.种类别称(typeAliases)

种类别称能为 Java 种类设定一个简称名称。 它仅用以 XML 配备,借以减少沉余的全限制类名撰写。

 <typeAlias alias="user" type="com.wyl.mybatis.pojo.Users"></typeAlias>

​ 当那样配备时,user 可以用在任意应用 com.wyl.mybatis.pojo.Users 的地区。

在应用注释的情况下还可以特定一个包名,再应用其类的情况下立即小写字母类名就可以。.例如:

<!--除非是应用注释,不然不兼容自定别称-->
<package name="com.wyl.mybatis.dao"/>

4.4.映射器(mappers)

界定SQL投射句子,特定MyBatis找寻SQL句子。

    1. 应用相对性于类途径的資源引入 【强烈推荐】:

      <mappers>
         <mapper resource="mappers/userMapper.xml"/>
      </mappers>
      
    2. 应用映射器插口完成类的彻底限制类名

      <mappers>
        <mapper class="com.wyl.mybatis.dao.UsersDao"/>
      </mappers>
      
    3. 将包内的映射器插口完成所有申请注册为映射器(留意相对位置)

      <mappers>
        <package name="com.wyl.mybatis.dao"/>
      </mappers>
      
    4. 应用彻底限制資源精准定位符(URL) 【不建议应用】

      <mappers>
        <mapper url="file:///var/mappers/usersMapper.xml"/>
      </mappers>
      

4.5.自然环境配备(environments)

MyBatis 能够 配制成融入各种自然环境,这类体制有利于将 SQL 投射运用于多种多样数据库查询当中, 现实状况下有多种多样原因必须如此做。比如,开发设计、检测和工作环境必须有不一样的配备;或是想在有着同样 Schema 的好几个生产制造数据库查询中运用一样的 SQL 投射。也有很多相似的应用情景。

但是要记牢:虽然能够 配备好几个自然环境,但每一个 SqlSessionFactory 案例只有挑选一种自然环境。

因此 ,假如想要联接2个数据库查询,就必须建立2个 SqlSessionFactory 案例,每一个数据库查询相匹配一个。

 <environments default="oracle">
        <environment >
         <!--mysql 配备-->
        </environment>
        <environment >
             <!--oracle 配备-->
        </environment>
    </environments>

4.6.事务管理管理工具(transactionManager)

在 MyBatis 中有这两种类别的事务管理管理工具(也就是 type="[JDBC|MANAGED]"):

在 MyBatis 中有这两种类别的事务管理管理工具(也就是 type="[JDBC|MANAGED]"):

  • JDBC – 这一配备立即采用了 JDBC 的递交和回退设备,它依靠从数据库得到的接入来管理方法事务管理修饰符。

  • MANAGED – 这一配备基本上没干什么。它从来不递交或回退一个联接,只是让器皿来管理方法业务的全部生命期(例如 JEE 网站服务器的前后文)。 默认设置 状况下它会关掉联接。殊不知一些器皿并不期待联接被关掉,因而必须将 closeConnection 特性设定为 false 来阻拦默认设置 的关掉个人行为。比如:

    <transactionManager type="MANAGED">
      <property name="closeConnection" value="false"/>
    </transactionManager>
    

提醒 假如你已经应用 Spring MyBatis,则沒有必需配备事务管理管理工具,由于 Spring 控制模块会应用内置的管理工具来遮盖之前的配备。

这二种事务管理管理工具种类都不用安装一切特性。他们实际上是种类别称,也就是说,你能用 TransactionFactory 插口完成类的全限制名或种类别称替代他们。

public interface TransactionFactory {
  default void setProperties(Properties props) { // 从 3.5.2 逐渐,该办法为默认设置 方式 
    // 空完成
  }
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}

在事务管理管理工具创建对象后,全部在 XML 中配备的特性可能被传送给 setProperties() 方式 。你的建立还必须建立一个 Transaction 插口的建立类,这一插口也非常简单:

public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
  Integer getTimeout() throws SQLException;
}

应用这两个插口,你能彻底自定 MyBatis 对业务的解决。

4.7.数据库(dataSource)

  • 【官方网申明】:dataSource 原素应用规范的 JDBC 数据库插口来配备 JDBC 联接的对象的資源。

  • 【官方网申明】:大部分 MyBatis 应用软件会按实例中的事例来配备数据库。尽管数据库配备是可选择的,但假如要开启延迟时间载入特点,就需要配备数据库。

  • 【官方网申明】:有三种內建的数据库种类(也就是 type="[UNPOOLED|POOLED|JNDI]")

    • UNPOOLED– 这一数据库的建立会每一次要求时开启和关掉联接。尽管有点儿慢,但对这些连接数据库易用性规定不太高的简易应用软件而言,是一个非常好的挑选。 特性主要表现则取决于应用的数据库查询,对一些数据库查询而言,应用数据库连接池并不重要,这一配备就很适用这类情况。
    • POOLED– 这类数据库的完成运用“池”的定义将 JDBC 联接目标机构起來,防止了建立新的联接案例时需需要的复位和验证時间。 这类处理方法很时兴,能使高并发 Web 运用快速响应要求。
    • JNDI – 这一数据库完成是因为能在如 EJB 或网站服务器这类器皿中应用,器皿能够 集中化或在外界配备数据库,随后置放一个 JNDI 前后文的数据库引入。
  • MyBatis默认设置 数据库种类 => 【POOLED】

  • 数据库种类: dbcp c3p0 druid hikari

4.8.目标加工厂(objectFactory)

MyBatis 每一次建立結果目标的新案例时,它都是会应用一个目标加工厂(ObjectFactory)案例来进行。 默认设置 的目标加工厂必须做的只是是创建对象总体目标类,要不根据默认设置 构造函数,要不在主要参数投射存有的情况下根据主要参数构造函数来创建对象。 假如想遮盖目标加工厂的默认设置 个人行为,则还可以利用建立自身的目标加工厂来完成.
自定目标加工厂
ObjectFactory是个接口类,其默认设置 完成类是DefaultObjectFactory。在 MyBatis 中,默认设置 的DefaultObjectFactory要做的便是创建对象查看結果相对应的总体目标类,有俩种方法能够 将查找结果显示的值镜像到相匹配的总体目标类:一种是根据总体目标类的默认设置 构造函数,此外一种便是根据总体目标类的有参构造函数。

4.8.1.自定目标加工厂

MyBatis容许申请注册自定的ObjectFactory,只须要完成插口 org.apache.ibatis.reflection.factory.ObjectFactory就可以。可是在绝大多数的情形下,大家都不用自定ObjectFactory目标加工厂,只必须承继系统软件早已完成好的 DefaultObjectFactory ,根据一定的改变来结束大家所须要的工作中。

有时在新创建一个新目标(构造函数或是有参构造函数),在获得目标以前必须解决一些逻辑性,或是在实行此类的有参构造函数时,在传到主要参数以前,要对主要参数开展一些解决,这时候就可以建立自身的 ObjectFactory 来载入该种类的目标。以下所显示,提升了日志打印出作用:

public class MyObjectFactory extends DefaultObjectFactory
{
    private static final long serialVersionUID = 1L;
    Logger log = Logger.getLogger(MyObjectFactory.class);
    private Object temp = null;
    @Override
    public void setProperties(Properties properties)
    {
        super.setProperties(properties);
    }
    @Override
    public <T> T create(Class<T> type)
    {
        T result = super.create(type);
        log.info("创建对象:"   result.toString());
        return result;
    }
    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)
    {
        T result = super.create(type, constructorArgTypes, constructorArgs);
        log.info("创建对象:"   result.toString());
        return result;
    }
    @Override
    public <T> boolean isCollection(Class<T> type)
    {
        return super.isCollection(type);
    }

随后,必须 在 SqlMapConfig.xml 全局性环境变量中配备该自定目标加工厂就可以,编码以下:

<objectFactory type="cn.mybatis.mydemo.MyObjectFactory">
    <property name="key" value="value" />
</objectFactory>

那样 MyBatis 便会选用配备的 MyObjectFactory 来转化成結果集目标,选用下边的源代码开展检测。

public class MyBatisDemo
{
    public static void main(String[] args) throws IOException
    {
        Logger log = Logger.getLogger(MyBatisDemo.class);
        InputStream config = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config);
        SqlSession session = factory .openSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.getUser(1L);  
    }
}

4.9.软件

4.9.1.软件的归类

第一类:软件是系统的一种填补,比如在分布式架构中,能够应用软件的方法,完成运行内存软件、硬盘软件、线性网络软件、Paxos软件等。该类软件相当于部件。

第二类:软件是系统对默认设置 作用的定制改动,比如mybatis里边自定软件,它完成的拦截器的作用。该类软件相当于拦截器。

4.9.2.MyBatis拦截器软件

MyBatis容许客户在已投射句子实行流程中的某一点开展阻拦启用。MyBatis应用软件来阻拦的方式启用,因此MyBatis软件一般 称之为:Mybatis拦截器。默认设置 状况下,MyBatis容许应用软件来阻拦的目标包含接下来的四大金刚:

  • Executor:MyBatis的电动执行机构,用以实行增删实际操作
  • ParameterHandler:解决SQL的主要参数目标
  • ResultSetHandler:解决SQL的回到結果集
  • StatementHandler:数据库查询的解决目标,用以实行SQL句子

在Java里边,大家想阻拦某一目标,只须要把这个目标包裝一下,用编码行语而言,便是再次转化成一个代理商目标。

4.9.2.注释案例

@Intercepts({
    @Signature(
            type=Executor.class,
            method="query",
            args={MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
    )
})
public class MyInterceptor implements Interceptor {
    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
    }
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }
    public void setProperties(Properties arg0) {}

@Intercepts 拦截器注释,此注释申明该类是一个软件类。在其中能够 申明好几个 @Signature 签字信息内容注释,type 为阻拦的方式 隶属的接口方式,method 为阻拦的方式 名字,args 是基本参数。

intercept 方式 是一个对总体目标方式 开展阻拦的抽象方法,而 plugin 方式 的效果是将拦截器插进总体目标目标。

setProperties 方式 的效果是将全局性环境变量中的主要参数引入软件类中。

MyBatis 全局性环境变量中配备该软件就可以

<plugins>
    <plugin interceptor="com.wyl.mybatis.unit.MyInterceptor"></plugin>
</plugins>

4.10.typeHandlers(种类CPU)

在JDBC中,必须 在PreparedStatement目标中设定这些早已预编译过的SQlL句子的主要参数。实行SQL后,会根据ResultSet目标获得获得数据库查询的数据信息,而那些在Mybatis是依据信息的种类根据typeHandler来完成的。

在typeHandler中,分成jdbcType和javatype,在其中jdbcType用以界定数据库类型,而javaType用以界定Java类型,那麼typeHandler的效果便是担负jdbcTypr和javaType中间的互相变换。

image-20210824103050041

和别称一样,在 MyBatis 中存有系统软件界定 typeHandler 和自定 typeHandler。MyBatis 会依据 javaType 和数据表的 jdbcType 来取决于选用哪一个 typeHandler 解决这种转换方法。系统软件给予的 typeHandler 能遮盖绝大多数情景的规定,可是很多状况下是远远不够的,例如大家有独特的转换方法,枚举类就这样。

4.10.1.系统软件界定的typeHandler

image

image-20210824104028080

这种便是MyBatis 系统软件早已构建好的typeHandler。在绝大多数的情形下不必显式地申明jdbcType 和javaType ,或是用typeHandler 去特定相应的typeHandler 来完成数据信息数据转换,由于MyBatis 系统软件会自身检测。有时必须改动一些转换方法,例如枚举类通常须要自身去撰写标准。

public interface TypeHandler<T> {
  // 应用typeHandler根据PreparedStatement目标开展设定SQL主要参数的过程中采用的具体做法。在其中:ps是PreparedStatement目标;i是主要参数在SQL句子中的字符;jdbcType是数据库类型
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  //JDBC結果集中化读取数据开展变换,应用字段名(columnName)或字符(columeIdex)获得数据库查询的数据信息
  T getResult(ResultSet rs, String columnName) throws SQLException;
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
   //sql语句专用型
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

4.10.2.自定TypeHandler

从系统软件界定的typeHandler中能够 了解,要完成typeHandler就必须去完成插口Typehandler,或是承继BaseTypeHandler(事实上,BaseTypehandler完成了typeHandler插口)

完成TypeHandler

public class MyTypeHandler implements TypeHandler<String>{
	//界定一个日志
	Logger log = Logger.getLogger(MyTypeHandler.class);

	@Override
	public String getResult(ResultSet rs, String columnName) throws SQLException {
		String result = rs.getString(columnName);
		log.info("载入string主要参数1【" result "】");
		return result;
	}

	@Override
	public String getResult(ResultSet rs, int columnIdex) throws SQLException {
		String result = rs.getString(columnIdex);
		log.info("载入string主要参数2【" result "】");
		return result;
	}

	@Override
	public String getResult(CallableStatement cs, int columnIdex) throws SQLException {
		String result = cs.getString(columnIdex);
		log.info("载入string主要参数3【" result "】");
		return result;
	}

	@Override
	public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
		log.info("设定string主要参数【" parameter "】");
		ps.setString(i, parameter);
	}
}

在源代码中应用自定typeHandler

<!-- 种类转化器 -->
	<typeHandlers>
		<typeHandler handler="com.wyl.mybatis.utils.MyTypeHandler" jdbcType="VARCHAR" javaType="string"/>
	</typeHandlers>

or

<resultMap  type="role">
    <result property="id" column="id"/>
    <result property="roleName" column="role_name" jdbcType="VARCHAR" javaType="string"/>
    <result property="note" column="note" typeHandler="com.wyl.mybatis.utils.MyTypeHandler"/>
</resultMap>

<select  parameterType="long" resultMap="roleMapper">
    select id,role_name,note from t_role where id = #{id}
</select>

有时配备的typeHandler过多,还可以应用包扫描仪的方法

<typeHandlers>      
    <package name="com.wyl.mybatis.unit.typeHandler"/>
</typeHandlers>
@MappedJdbcTypes(JdbcType.VARCHAR)   // 表明把数据库查询中的varchar种类转为java的String种类时应用该转化器
@MappedTypes(String.class)
public class MyTypeHandler implements TypeHandler<String>{
    Logger logger = Logger.getLogger(MyTypeHandler.class);
    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        String result = rs.getString(columnName);
        logger.info("载入string主要参数1【"   result  "】");
        return result;
    }
    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        String result = rs.getString(columnIndex);
        logger.info("载入string主要参数2【"   result  "】");
        return result;
    }
    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String result = cs.getString(columnIndex);
        logger.info("载入string主要参数3【"   result  "】");
        return result;
    }
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        logger.info("设定string主要参数【"   parameter   "】");
        ps.setString(i, parameter);
    }
}

4.10.3.枚举类型TypeHandler

在大部分状况下,typeHandler 由于枚举类型而应用,MyBatis 早已界定了2个类做为枚举类型的适用,这两个类分别是:

  • EnumOrdinalTypeHandler。应用整数金额字符做为参数传递的(枚举类型的默认设置 变换类)

        <resultMap  type="user">
            <result property="id" column="id" />
            <result property="userName" column="user_name" />
            <result property="password" column="passsword" />
            <result property="sex" column="sex"
                typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
        </resultMap>
        <select  resultMap="userMapper" parameterType="long">
            select id,user_name,password,sex,mobile,tel,email,note from myUser
            where id=#{id}
        </select>
    
    
  • EnumTypeHandler。应用枚举类型字符串数组名字做为参数传递的

    <resultMap  type="com.mybatis.po.User">
            <result property="id" column="id" />
            <result property="userName" column="user_name" />
            <result property="password" column="passsword" />
            <result property="sex" column="sex"
                typeHandler="org.apache.ibatis.type.EnumTypeHandler" />
        </resultMap>
        <select  resultMap="userMapper" parameterType="long">
            select id,user_name,password,sex,mobile,tel,email,note from myUser
            where id=#{id}
        </select>
    

4.10.4.BlobTypeHandler载入Blob字段名

MyBatis 对数据库查询的 Blob 字段名也开展了适用,它给予了一个 BlobTypeHandler,为了更好地应付越来越多的情景,它还带来了 ByteArrayTypeHandler,仅仅它不太常见.

create table file(
    id int(12) not null auto_increment,
    content blob not null,
    primary key(id)
);
//pojo
public class TestFile{
    long id;
    byte[] content;
    /** setter and getter **/
}
 <resultMap type="com.ssm.chapter5.pojo.TestFile" >
        <id column="id" property="id"/>
        <id column="content" property="content" typeHandler="org.apache.ibatis.type.BlobTypeHandler"/>
    </resultMap>

4.11.数据库查询生产商标志(databaseIdProvider)

MyBatis 能够 按照不一样的数据库查询生产商实行不一样的句子,这类多生产商的适用是根据投射句子中的 databaseId 特性。 MyBatis 会载入含有配对当今数据库查询 databaseId 特性和全部没有 databaseId 特性的句子。 假如与此同时寻找含有 databaseId 和没有 databaseId 的同样句子,则后面一种会被放弃。 为适用多生产商特点,只需像下边那样在 mybatis-config.xml 文档中添加 databaseIdProvider 就可以:

<databaseIdProvider type="DB_VENDOR" />

databaseIdProvider 相匹配的 DB_VENDOR 完成会将 databaseId 设定为 DatabaseMetaData#getDatabaseProductName() 回到的字符串数组。 因为一般状况下这种字符串数组都特别长,并且同样设备的不一样版本号会回到不一样的值,你也许想根据设定特性别称来使其减短:

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

在保证了特性别称时,databaseIdProvider 的 DB_VENDOR 完成会将 databaseId 设定为数据库查询产品名字与特性中的名字第一个相符合的值,要是没有配对的特性,可能设定为 “null”。 在这个示例中,假如 getDatabaseProductName() 回到“Oracle (DataDirect)”,databaseId 将被设定为“oracle”。

你能根据完成插口 org.apache.ibatis.mapping.DatabaseIdProvider 并在 mybatis-config.xml 中申请注册来搭建自身的 DatabaseIdProvider:

public interface DatabaseIdProvider {
  default void setProperties(Properties p) { // 从 3.5.2 逐渐,该办法为默认设置 方式 
    // 空完成
  }
  String getDatabaseId(DataSource dataSource) throws SQLException;
}

5.映射器

5.1.Select

撰写插口dao
User getUserById(int id);

撰写相应的mapper中的sql语句,留意要写在相应的mapper下

<!--
id:相匹配的dao插口
resultType:sql语句实行的传参
parameterType : 主要参数种类
User:为别称
-->
<select  parameterType="int" resultType="user">
        select * from mybatis.user where id=#{id}
</select>
@Test
    public void getUserInfoById(){
        // 启用MyBatisUtils.getSqlSession()方式 ,获得SqlSession目标
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        // 启用获得到的SQLSession目标中的getMapper目标
        // 反射面Dao插口,动态代理Dao插口中的方式 ,并将这种方式 存有目标【mapper】中
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);
        Users user = mapper.getUserInfoById(2);
        System.out.println(user);
        // 关掉sqlSession
        sqlSession.close();
    }

查看全部

 // 【select】全部客户信息
    List<Users> getUsersInfo();
<!-- select sql: 关联getUsersInfo方式 ,回到全部客户信息 -->
    <select  resultType="com.camemax.com.camemax.pojo.Users">
        select * from school.users
    </select>
 @Test
    public void getUsersInfo(){

        // 启用MyBatisUtils.getSqlSession()方式 ,获得SqlSession目标
        SqlSession sqlSession = MyBatisUtils.getSqlSession();

        // 启用获得到的SQLSession目标中的getMapper目标
        // 反射面Dao插口,动态代理Dao插口中的方式 ,并将这种方式 存有目标【mapper】中
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);

        // 启用mapper中相匹配方式 ,并设定相应的目标来接受其回到結果
        // 下列为测试标准getUsersInfo() => 获得全部Users表格中信息内容,并且用相匹配类接受
        List<Users> usersInfo = mapper.getUsersInfo();
        // for循环解析xml輸出List结合
        for (Users users : usersInfo) {
            System.out.println(users);
        }
        // 关掉sqlSession
        sqlSession.close();

    }

5.2.insert

插进一条细致

  // 【insert】特定客户信息
    int insertUser(Users user);
 <!-- insert sql: 关联insertUser方法,插进单独客户信息-->
    <insert  parameterType="user" >
        insert into users
        values (#{id},#{username},#{password},#{email},#{gender})
    </insert>
 @Test
    public void insertUsers(){
        // 启用MyBatisUtils.getSqlSession()方式 ,获得SqlSession目标
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        // 启用获得到的SQLSession目标中的getMapper目标
        // 反射面Dao插口,动态代理Dao插口中的方式 ,并将这种方式 存有目标【mapper】中
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);
        int i = mapper.insertUser(
                new Users(2, "wyl", "123456", "171@qq.com", 0)         
        );
        //递交事务管理
        sqlSession.commit();
        if ( i > 0 ){
            System.out.println("Insert 取得成功!");
        }
        // 关掉sqlSession
        sqlSession.close();
    }

插进好几条数据信息

    // 【insert】 大批量客户信息
    int insertManyUseList(List<Users> users);
<!-- insert sql: 关联insertManyUseMap,批量插入 -->
    <insert  >
        insert into users values
        /* foreach 标识:
            -【item】特性: 表明结合中每一个原素开展迭代更新时的别称
            - 【collection】特性: 主要参数种类是一个List的情况下,collection特性数值list
            - 【separator】特性: 表明在每一次开展迭代更新中间以什么符号做为分节符。
        */
        <foreach  item="user" collection="list" separator=",">
            (#{user.id},#{user.username},#{user.password},#{user.email},#{user.gender})
        </foreach>
    </insert>
 @Test
    public void insertManyUseList(){

        List<Users> users = new ArrayList<Users>();
        users.add(new Users(2, "wyl", "123", "123@qq.com", 20));
        users.add(new Users(3, "wjm", "123456", "123456@qq.com", 30));
        users.add(new Users(4, "王延领", "1123456", "wjm@qq.com", 41));
        users.add(new Users(5, "王经墨", "223", "wjm@qq.com", 51));
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);
        int i = mapper.insertManyUseList(users);
        if ( i > 0 ){
            System.out.println("插进取得成功过!");
        }
        sqlSession.commit();

        sqlSession.close();
    }

5.3.1.外键约束回填土

假如你的数据库系统适用自动生成外键约束的字段名(例如 MySQL 和 SQL Server),那麼可以设定 useGeneratedKeys=”true”,随后再把 keyProperty 设定为总体目标特性就 OK 了

 <insert  useGeneratedKeys="true"  keyProperty="id">
        insert into users
        values (#{id},#{username},#{password},#{email},#{gender})
    </insert>

假如你的数据库查询还适用几行插进, 你还可以传到一个 Author 二维数组或结合,并回到自动生成的外键约束。

5.3.2.自定外键约束

最先会运作 selectKey 原素中的句子,并设定 Users的 id,随后才会启用插入语句。那样就保持了数据库查询自动生成外键约束相近的个人行为,与此同时保证了 Java 编码的简约。

<insert  useGeneratedKeys="true"  keyProperty="id">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
    select if(max(id)==null,1,max(id) 2) from users
  </selectKey>
        insert into users
        values (#{id},#{username},#{password},#{email},#{gender})
    </insert>

5.3.update

// 【update】特定客户信息
    int updateUseInfoById(Users user);
 <!-- update sql: 关联updateUser方法,升级特定客户信息 -->
    <update  parameterType="users">
        update users
        set username = #{username},
            password = #{password},
            email = #{email},
            gender = #{gender}
        where id = #{id}
    </update>
@Test
    public void updateUseInfoById(){

        SqlSession session = MyBatisUtils.getSqlSession();
        UsersDao mapper = session.getMapper(UsersDao.class);
        int i = mapper.updateUseInfoById(new Users(1, "王延领", "123456", "171@qq.com", 1));
        if ( i > 0 ){
            System.out.println(mapper.getUserInfoById(1).getUsername()   " 改动变成!");
        }
        session.commit();
        session.close();
    }

5.4.delete

// 【delete】特定客户信息
    int deleteUserById(int id);
 <!-- delete sql: 关联deleteUserById方式 ,删掉特定客户信息 -->
    <delete  parameterType="int">
        delete from users
        where id = #{id}
    </delete>
@Test
    public void deleteUserInfoById(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);
        String willDeleteUsername = mapper.getUserInfoById(2).getUsername();
        int i = mapper.deleteUserById(2);

        if (i > 0){
            System.out.println(willDeleteUsername   " 已删除!");
        }
        sqlSession.commit();
        sqlSession.close();
    }

5.5.模糊搜索like

// 【select】 模糊搜索
    List<Users> getUsersInfoByPhantomSelect(String username);
<!-- select sql: 关联getUsersInfoByPhantomSelect,模糊搜索 -->
    <select  resultType="Users">
        select * from users where username like #{username}
    </select>
 @Test
    public void getUsersInfoByPhantomSelect(){
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UsersDao mapper = sqlSession.getMapper(UsersDao.class);
        List<Users> users = mapper.getUsersInfoByPhantomSelect("%e%");
        for (Users user : users) {
            System.out.println(user);
        }
        sqlSession.close();
    }

5.6.sql

这一原素能够 用于界定可提拔的 SQL 编码精彩片段,便于在其他句子中应用。

<sql id='userCols'> user_name,pwd</sql>
 <select  resultType="Users">
        select <include refid='userCols' from school.users where username like #{username}
    </select>

5.7.投射結果(resultMap)

resultMap 原素是 MyBatis 中最重要最强有力的原素。它能够 让人从 90% 的 JDBC ResultSets 数据信息获取编码中解放出来,并在一些情况下容许你开展一些 JDBC 不兼容的实际操作。事实上,在为一些例如联接的繁杂句子撰写投射编码的情况下,一份 resultMap 可以替代完成同样作用的千余行编码。ResultMap的制定观念是,对简洁的句子保证零配备,针对繁杂一点的句子,只必须叙述句子中间的关联就可以了。

5.7.1构造

<!--原素的 type 特性表明必须的 POJO,id 特性是 resultMap 的唯一标志-->
<resultMap  type="">
    <constructor><!-- 类再创建对象时用于引入結果到构造函数 -->
        <idArg/><!-- ID主要参数,結果为ID -->
        <arg/><!-- 引入到构造函数的一个一般結果 -->  
    </constructor>
    <id/><!-- 用以表明哪一个列是外键约束 -->
    <result/><!-- 引入到字段名或JavaBean特性的一般結果 -->
    <association property=""/><!-- 用以一对一关系 -->
    <collection property=""/><!-- 用以一对多、多对多关系 -->
    <discriminator javaType=""><!-- 应用結果值来决策采用哪一个結果投射 -->
        <case value=""/><!-- 根据一些值的結果投射 -->
    </discriminator>
</resultMap>

5.7.2.应用 Map 储存結果集

一切 select 句子都能够应用 Map 储存結果,实例编码以下:

<!-- 查看全部客户信息存进Map中 -->
<select  resultType="map">
    select * from user
</select>
@Test
// 查看全部客户信息存进Map中
List<Map<String, Object>> lmp = userDao.selectAllUserMap();
for (Map<String, Object> map : lmp) {
    System.out.println(map);
}

以上 Map 的 key 是 select 句子查看的列名(务必彻底一样),而 Map 的 value 是查看回到結果中字段名相匹配的值

5.7.3.应用POJO储存結果集

Map 用起來很便捷,但易读性稍弱,有的开发人员不太喜爱应用 Map,大量情况下喜爱应用 POJO 的方法。

package com.wyl.mybatis.pojo;
public class User {
    private Integer m_uid;
    private String m_uname;
    private String m_usex;
    // 此处省略setter和getter方法
    @Override
    public String toString() {
        return "User[u,uname="   m_uname   ",usex="   m_usex
                  "]";
    }
}
 <!-- 查看特定客户信息 -->
    <resultMap  type="users">
        <!-- 类特性【userId】投射为数据库查询中的【id】字段名 -->
        <id property="userId" column="id"/>
        <!-- 类特性【userName】投射为数据库查询中的【name】字段名 -->
        <result property="userName" column="name" />
        <!-- 类特性【userPasswd】投射为数据库查询中的【password】字段名 -->
        <result property="userPasswd" column="password" />
    </resultMap>

 <!-- 【resultMap】特性偏向<resultMap>标识 -->
    <select  resultType="MyBatisAliasUsers" >
        select * from users
    </select>
@Test
// 应用resultMap投射結果集
List<User> listResultMap = userDao.selectResultMap();
for (User myUser : listResultMap) {
    System.out.println(myUser);
}

5.8.分页查询

5.8.1.应用limit分页查询

//分页查询
List<User> getUserByLimit(Map<String,Integer> map);
<!--分页查询
英语的语法:
SELECT * from user limit startIndex,pageSize;
SELECT * from user limit 3;  #[0,3)
-->
<select  parameterType="map" resultMap="User">
    select * from user limit #{startIndex},#{pageSize}
 </select>
//分页查询
@Test
public void getUserByLimit(){
    SqlSession sqlSession=MybatisUtils.getsqlSession();
    UserMapper mapper =sqlSession.getMapper(UserMapper.class);
    Map<String,Integer> map=new HashMap<String, Integer>();
    map.put("startIndex",0);
    map.put("pageSize",2);
    List<User> userList=mapper.getUserByLimit(map);
    for (User user: userList) {
        System.out.println(user);
     }
    sqlSession.close();
}

5.8.2.RowBounds分页查询

//分页查询2
List<User> getUserByRowBounds();
<select  resultMap="User">
    select * from user
</select>
//分页查询2
@Test
public void getUserByRowBounds(){
    SqlSession sqlSession=MybatisUtils.getsqlSession();
    //RowBounds
    RowBounds rowBounds = new RowBounds(1, 2);
    List<User> userList = sqlSession.selectList("com.wyl.mybatis.dao.UserMapper.getUserByRowBounds",null,rowBounds);
    for (User user: userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

5.8.3.应用分页插件

官方网站详细地址:https://pagehelper.github.io/

image-20210824093737129

5.9.联级查看

联级关联是一个数据库查询实体线的定义,有 3 种联级关联,分别是一对一联级、一对多联级及其多对多联级

5.9.1.一对一关联查询

在 MyBatis 中,根据 原素的子原素 解决这类一对一联级关联。

在 原素中一般 应用下列特性。

  • property:特定投射到dao层的目标特性。
  • column:特定表格中相对应的字段名(即查看回到的字段名)。
  • javaType:特定投射到实体线目标特性的种类。
  • select:特定引进嵌入查看的子 SQL 句子,该特性用以关系投射中的嵌入查看。
public class Teacher {
    private int tid;
    private String tname;
    private Classes classes;
    public int getTid() {
        return tid;
    }
    public void setTid(int tid) {
        this.tid = tid;
    }
    public String getTname() {
        return tname;
    }
    public void setTname(String tname) {
        this.tname = tname;
    }
    public Classes getClasses() {
        return classes;
    }
    public void setClasses(Classes classes) {
        this.classes = classes;
    }
    @Override
    public String toString() {
        return "Teacher [t, tname="   tname   ", classes="   classes   "]";
    }
}
public class Classes {
    private int cid;
    private String cname;
    private Teacher teacher;
    public int getCid() {
        return cid;
    }
    public void setCid(int cid) {
        this.cid = cid;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
    @Override
    public String toString() {
        return "Classes [c, cname="   cname   ", teacher="   teacher   "]";
    }
<?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="one.to.one.classesMapper">
    <!--
         方法一:嵌入結果:应用嵌入結果投射来解决反复的协同結果的非空子集
                 封裝联表查看的数据信息(除去相同的数据信息)
         select * from classes c, teacher t where c.tid=t.tid and c.tid=#{tid}
     -->
    <select  resultMap="getClassesMap" parameterType="int">
        select * from classes c ,teacher t
            where c.tid=t.tid and c.tid=#{tid}
    </select>
    <resultMap type="one.to.one.Classes" >
        <id column="cid" property="cid"/>
        <result column="cname" property="cname"/>
        <association property="teacher" javaType="one.to.one.Teacher">
            <id column="tid" property="tid"></id>
            <result column="tname" property="tname"/>
        </association>
    </resultMap>
    <!--
         方法一:嵌入結果:应用嵌入結果投射来解决反复的协同結果的非空子集
                 封裝联表查看的数据信息(除去相同的数据信息)
         select * from teacher t,classes c where t.cid = c.cid and t.cid=#{cid}
     -->
    <select  resultMap="getTeacherMap" parameterType="int">
        select * from teacher t,classes c
            where t.cid = c.cid and t.cid=#{cid}
    </select>
    <resultMap type="one.to.one.Teacher" >
        <id column="tid" property="tid"/>
        <result column="tname" property="tname"/>
        <association property="classes" javaType="one.to.one.Classes">
            <id column="cid" property="cid"/>
            <result column="cname" property="cname"/>
        </association>
    </resultMap>
    <!--
         方法二:嵌入查看:根据实行此外一个SQL投射句子来回到预估的复杂性种类
         SELECT * FROM classes WHERE cid=1;
         SELECT * FROM teacher WHERE tid=1   //1 是上一个查看获得的tid的值
         property:别称(特性名)    column:字段名 -->
          <!-- 把teacher的字段名设定进来 -->
    <select  resultMap="getClassesMap2">
        select * from classes c where c.cid = #{cid}
    </select>
    <resultMap type="one.to.one.Classes" >
        <id column="cid" property="cid"/>
        <result column="cname" property="cname"/>
        <collection property="teacher" column="tid" select="getTeacherCollection">
        </collection>
    </resultMap>
    <select  resultType="one.to.one.Teacher">
        select tid tid,tname tname from teacher where tid=#{tid}
    </select>
</mapper>

大家这儿一对一的关系实际操作,有俩种方法:

    1、应用嵌入結果投射来解决反复的协同結果的非空子集

    2、根据实行此外一个SQL投射句子来回到预估的复杂性种类

 //一对一嵌入結果方法:依据老师id查询班集体信息内容
    @Test
    public void testGetClasses(){
        String statement = "one.to.one.classesMapper.getClasses";
        Classes c = session.selectOne(statement, 1);
        System.out.println(c);
    }
    //一对一嵌入結果方法:依据班集体id查询老师信息内容
    @Test
    public void testGetTeacher(){
        String statement = "one.to.one.classesMapper.getTeacher";
        Teacher t = session.selectOne(statement, 1);
        System.out.println(t);
    }
    //一对一嵌入查看方法:依据老师id查询班集体信息内容
    @Test
    public void testGetClasses2(){
        String statement = "one.to.one.classesMapper.getClasses2";
        Classes c = session.selectOne(statement, 1);
        System.out.println(c);
    }

5.9.2. 多对一查看

  • SQL回到的值必须应用到类时的处理方法

  • 仿真模拟检测:好几个学员相匹配一个教师

    1. MySQL检测表【Teachers】、【Students】
    2. 检测dao层【Teachers】、【Students】
    3. dao层【TeachersMapper】、【StudentsMapper】
    4. XML投射文档【teachersMapper.xml】、【studentsMapper.xml】
    5. 关键环境变量=>【mybatis-config.xml】关联dao插口、申请注册XML投射文档
    6. 輸出检测
  • 总体文件目录构造

    image-20200829123326705

5.9.2.1 自然环境构建

MySQL建立数据测试

use school;

#老师表
DROP TABLE IF exists teachers;
create table teachers(
	`tid` int(10),
	`tname` varchar(20) DEFAULT NULL,
	PRIMARY KEY (`tid`)
	)ENGINE=INNODB DEFAULT CHARSET=utf8;

#学员表
DROP TABLE IF exists students;
create table students(
	`id` int(10) ,
	`name` varchar(20) DEFAULT NULL,
	`tid` int(10) DEFAULT NULL,
	PRIMARY KEY (`id`),
	CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teachers` (`tid`)	
	)ENGINE=INNODB DEFAULT CHARSET=utf8;
	insert into teachers (`tid`,`tname`) values (1,'卡梅克斯');
	insert into students (`id`,`name`,`tid`) values (1,'小红书',1);
	insert into students (`id`,`name`,`tid`) values (2,'小绿',1);
	insert into students (`id`,`name`,`tid`) values (3,'小白',1);
	insert into students (`id`,`name`,`tid`) values (4,'新手',1);
	insert into students (`id`,`name`,`tid`) values (5,'小紫',1);

5.9.2.2 dao层与插口

  • 学员有关

    • 【Students】dao层

      package com.camemax.pojo;
      import org.apache.ibatis.type.Alias;
      
      @Alias("students")
      public class Students {
          private int sid;
          private String sname;
          // 加上【Teachers】类特性
          private Teachers teacher;
      
          public Students() {};
      
          public Students(int sid, String sname, Teachers teacher) {
              this.sid = sid;
              this.sname = sname;
              this.teacher = teacher;
          }
      
          public int getSid() {
              return sid;
          }
      
          public void setSid(int sid) {
              this.sid = sid;
          }
      
          public String getSname() {
              return sname;
          }
      
          public void setSname(String sname) {
              this.sname = sname;
          }
      
          public Teachers getTeacher() {
              return teacher;
          }
      
          public void setTeacher(Teachers teacher) {
              this.teacher = teacher;
          }
      
          @Override
          public String toString() {
              return "Students{"  
                      "s, sname='"   sname   '\''  
                      ", teacher="   teacher  
                      '}';
          }
      }
      
    • 【StudentsMapper】插口

      package com.camemax.dao;
      
      import com.camemax.pojo.Students;
      import java.util.List;
      
      public interface StudentsMapper {
      	//查看全部学生电子档案,与此同时輸出老师信息内容
          List<Students> getStudentsInfo();
      }
      
      
  • 老师有关

    • 【Teachers】dao层

      package com.camemax.pojo;
      
      import org.apache.ibatis.type.Alias;
      
      @Alias("teachers")
      public class Teachers {
          private int tid;
          private String tname;
      
          public Teachers() {};
      
          public Teachers(int tid, String tname) {
              this.tid = tid;
              this.tname = tname;
          }
      
          public int getTid() {
              return tid;
          }
      
          public void setTid(int tid) {
              this.tid = tid;
          }
      
          public String getTname() {
              return tname;
          }
      
          public void setTname(String tname) {
              this.tname = tname;
          }
      
          @Override
          public String toString() {
              return "Teachers{"  
                      "t, tname='"   tname   '\''  
                      '}';
          }
      }
      
    • 【TeachersMapper】插口

      package com.camemax.dao;
      
      public interface TeachersMapper {
      }
      

5.9.2.3 Mapper映射器

  • mybatis-config.xml

    <configuration>
        <properties resource="db.properties"/>
    
        <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    
        <typeAliases>
            <package name="com.camemax.pojo"/>
        </typeAliases>
    
        <environments default="development">
            <environment >
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${propDriver}"/>
                    <property name="url" value="${propUrl}"/>
                    <property name="username" value="${propUsername}"/>
                    <property name="password" value="${propPassword}"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 申请注册Mapper-->
        <mappers>
            <mapper resource="mapper/studentsMapper.xml"/>
            <mapper resource="mapper/teachersMapper.xml"/>
        </mappers>
    </configuration>
    

5.9.2.4. 按查看嵌入解决【子查询】

  • studentsMapper.xml

     <!-- 按查看嵌入解决 -->
    <select resultMap="StudentsInfoMapBySelect" >
        select * from school.students
    </select>
    <resultMap  type="students">
        <id property="sid" column="id"/>
        <result property="sname" column="name"/>
    
        <!-- 繁杂种类: Teachers类
                【association】: 目标
                    - 【property】: 设定获得到的結果集字段 => private Teachers teacher
                    - 【column】: 设定投射相匹配的数据库查询字段名 => tid
                    - 【javaType】: 设定回到种类 => Teachers
                    - 【select】: 子查询关联。根据别的<select>标识中的值,偏向别的select句子 => <select >
                【collection】: 结合
            -->
        <association property="teacher" column="tid" javaType="Teachers" select="TeachersInfo"/>
    </resultMap>
    
    <!-- 查看特定老师信息内容 -->
    <select  resultType="teachers">
        select * from school.teachers where tid = #{tid}
    </select>
    
    
    
  • teachersMapper.xml

    <mapper namespace="com.wyl.mybatis.dao.TeachersMapper">
    </mapper>
    

5.9.2.5 按結果嵌入解决【关系】

  • studentsMapper.xml

    <!-- 按結果嵌入解决 -->
    <select  resultMap="getStudentsInfoByResult">
        select s.id studentId,
        s.name studentName,
        t.tname teacherName
        from students s,teachers t
        where s.tid = t.tid;
    </select>
    <resultMap  type="students">
        <id property="sid" column="studentId"/>
        <result property="sname" column="studentName"/>
        <association property="teacher" javaType="Teachers">
            <result property="tname" column="teacherName"/>
        </association>
    </resultMap>
    
  • teachersMapper.xml

    <mapper namespace="com.wyl.mybatis.dao.TeachersMapper">
    </mapper>
    

5.9.3. 一对多查看

  • 仿真模拟检测:一名教师有多位学员 => 【朝向老师】
  • 实质:应用<collection>标识进行一对多的輸出

5.9.3.1. 根据[12.1自然环境构建](#12.1 自然环境构建)作出的改动

  1. dao层 => 【TeachersDao】

    package com.camemax.dao;
    
    import com.camemax.pojo.Students;
    import com.camemax.pojo.Teachers;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface TeachersMapper {
    	// 传到特定老师序号,回到其下学生电子档案
        List<Students> getTeacherByIdHasStudents(@Param("tid") int tid);
    }
    
    
  2. 完成类 => 【Teachers】

    package com.camemax.pojo;
    
    import org.apache.ibatis.type.Alias;
    
    import java.util.List;
    
    @Alias("teachers")
    public class Teachers {
        private int tid;
        private String tname;
        // 增加特性 : 老师有着的学员
        private List<Students> teacherHasStudents;
    
        public List<Students> getTeacherHasStudents() {
            return teacherHasStudents;
        }
    
        public void setTeacherHasStudents(List<Students> teacherHasStudents) {
            this.teacherHasStudents = teacherHasStudents;
        }
    
        public Teachers(int tid, String tname, List<Students> teacherHasStudents) {
            this.tid = tid;
            this.tname = tname;
            this.teacherHasStudents = teacherHasStudents;
        }
    
        public Teachers() {};
    
        public int getTid() {
            return tid;
        }
    
        public void setTid(int tid) {
            this.tid = tid;
        }
    
        public String getTname() {
            return tname;
        }
    
        public void setTname(String tname) {
            this.tname = tname;
        }
    
        @Override
        public String toString() {
            return "Teachers{"  
                    "t, tname='"   tname   '\''  
                    ", teacherHasStudents="   teacherHasStudents  
                    '}';
        }
    }
    
  3. dao层 => 【Students】

    package com.camemax.pojo;
    
    import org.apache.ibatis.type.Alias;
    
    @Alias("students")
    public class Students {
        private int sid;
        private String sname;
        private int tid;
    
        public Students(){};
        public Students(int sid, String sname, int tid) {
            this.sid = sid;
            this.sname = sname;
            this.tid = tid;
        }
    
        @Override
        public String toString() {
            return "Students{"  
                    "s, sname='"   sname   '\''  
                    ", tlanguage-java">@Test
    public void getStudentsByTid(){
        MyBatisUtils mybatis = new MyBatisUtils();
        SqlSession sqlSession = mybatis.getSqlSession();
        TeachersMapper mapper = sqlSession.getMapper(TeachersDao.class);
        System.out.println(mapper.getStudentsByTid(1));
      	sqlSession.close();
    }
    

5.9.3.2. 按查看嵌入解决 【子查询】

  1. XML投射文档 => teachersMapper.xml

    <select  resultMap="getStudentsByTidMapUseSelect">
        select * from school.teachers where tid = #{tid}
    </select>
    
    <!-- 建立【getStudentsByTidMapUseSelect】投射結果集,完成一对多結果回到。	留意:Teachers类 应用了 @Alias("teachers") 
    -->
    <resultMap  type="teachers">
        <id property="tid" column="tid" />
        <result property="tname" column="name" />
        <!-- Teachers类中增加List<Students> teacherHasStudents属性字段名 
    			javaType: 特定在java中的字段名种类特性
    			ofType: 特定种类隶属类
    			select: 使resultMap关联特定<select>标识
    			column: 使resultMap传送特定的特性字段名
    	-->
        <collection property="teacherHasStudents" javaType="ArrayList" ofType="students" select="getStudentsByTid" column="tid"/> 
    </resultMap>
    
    <!-- 子查询:学生电子档案 -->
    <select  resultMap="studentsMap">
    	select * from school.students where tid = #{tid}
    </select>
    
    <!-- 建立【studentsMap】,投射Students类中,与Teachers表字段不一致的特性字段名 -->
    <resultMap  type="students">
        <id property="sid" column="id" />
        <result property="sname" column="name"/>
     	<!-- 不用会造成 字段名【tid】結果为0 -->   
        <result property="tid" column="tid" />
    </resultMap>
    
  2. 輸出結果

    // 按查看嵌入解决 => 子查询 結果:
    [Teachers{tid=1, tname='卡梅克斯', teacherHasStudents=[Students{sid=1, sname='小红书', tid=1}, Students{sid=2, sname='小绿', tid=1}, Students{sid=3, sname='小白', tid=1}, Students{sid=4, sname='新手', tid=1}, Students{sid=5, sname='小紫', tid=1}]}]
    

5.9.3.3. 按結果嵌入解决 【关联查询】

  1. XML投射文档 => teachersMapper.xml

    <select  resultMap="teacherGetStudentsByResult">
        select s.id studentId,s.name studentName,s.tid,t.tname teacherName,t.tid
        from students s,teachers t
        where s.tid = t.tid
        and t.tid = #{tid}
    </select>
    <resultMap  type="teachers">
        <id property="tid" column="tid"/>
        <result property="tname" column="teacherName"/>
        <collection property="teacherHasStudents" ofType="students">
            <id property="sid" column="studentId"/>
            <result property="sname" column="studentName"/>
            <result property="tid" column="tid" />
        </collection>
    </resultMap>
    
  2. 检测結果

    // 按結果嵌入解决 => 关联查询 結果:
    [Teachers{tid=1, tname='卡梅克斯', teacherHasStudents=[Students{sid=1, sname='小红书', tid=1}, Students{sid=2, sname='小绿', tid=1}, Students{sid=3, sname='小白', tid=1}, Students{sid=4, sname='新手', tid=1}, Students{sid=5, sname='小紫', tid=1}]}]
    

5.10.缓存文件

假如每一次查看都数据库连接 ,耗資源!一次查看的結果,给他们暂存有一个能够 立即得到的地区!–> 运行内存 : 缓存文件
大家再度查看同样数据信息的情况下,立即走缓存文件,就无需走数据库查询了

因此 常常查看又很久没更改的信息能够 应用缓存文件,降低和数据表的互动频次,降低系统软件花销,提升系统软件高效率.

  • MyBatis包括一个十分强有力的查看缓存文件特点,它能够十分便捷地订制和配备缓存文件。缓存文件能够 很大程度的提高查看高效率。

  • MyBatis系统中默认设置 界定了二级缓存文件:一级缓存文件二级缓存.

    • 默认设置 状况下,仅有一级缓存文件打开。(SqlSession等级的缓存文件,也称之为当地缓存文件)

    • 二级缓存必须手动式开始和配备,他是根据namespace级其他缓存文件。

    • 为了更好地提升扩展性,MyBatis界定了缓存文件插口Cache。我们可以根据完成Cache插口来源于界定二级缓存

5.10.1.一级缓存文件

也叫当地缓存文件: SqlSession.

  1. 一级缓存文件默认设置 是打开的,只在一次SqlSession中合理,也就是取得联接到关掉联接这一区段段!

  2. 一级缓存文件便是一个Map

  3. 在同一个 SqlSession 中, Mybatis 会把实行的办法和主要参数根据优化算法转化成缓存文件的键值, 将键值和結果储放在一个 Map 中, 假如事后的键值一样, 则同时从 Map 中读取数据;

  4. 不一样的 SqlSession 中间的缓存文件是互相防护的;

  5. 用一个 SqlSession, 能够 根据配备促使在查看前清除缓存文件;

  6. 一切的 UPDATE, INSERT, DELETE 句子都是会清除缓存文件。

5.10.2.二级缓存

  1. 级缓存文件也叫全局性缓存文件,一级缓存文件修饰符太低了,因此 产生了二级缓存
  2. 根据namespace级其他缓存文件,一个名字室内空间,相匹配一个二级缓存;
  3. 工作方案
    3.1.一个对话查看一条数据信息,这一数据信息便会被放到当今对话的一级缓存文件中;
    3.2.假如当今对话关掉了,这一对话相匹配的一级缓存文件就没有了;可是大家需要的是,对话关掉了,一级缓存文件中的信息被保留到二级缓存中;
    3.3.新的对话查看信息内容,就可以从二级缓存中获得內容;
    3.4.不一样的mapper查出来的信息会放到自身相应的缓存文件(map)中;

流程:

打开全局性缓存文件

<!--表明的打开全局性缓存文件-->
<setting name="cacheEnabled" value="true"/>

在要应用二级缓存的Mapper中打开

<!--在当今Mapper.xml中应用二级缓存-->
<cache/>

还可以自定主要参数

<!--在当今Mapper.xml中应用二级缓存-->
<cache  eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

总结:

  • 只需开始了二级缓存,在同一个Mapper下就合理
  • 全部的信息都是会先放到一级缓存文件中;
  • 仅有当对话递交,或是关上的情况下,才会递交到二级缓存中

6.动态sql

动态性 SQL 是 MyBatis 的强悍特点之一。

MyBatis 3 更换了以前的大多数原素,大大的简化了元素种类,如今要學習的元素种类比原先的一半还需要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

6.1.if

应用动态性 SQL 最普遍场景是依据标准包括 where 子句的一部分。

<select 
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

6.2.choose、when、otherwise

<select 
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <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>
</select>

6.3.trim、where、set

<select 
     resultType="Blog">
  SELECT * FROM BLOG
  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>
</select>

6.3.foreach

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

6.4.script

 @Update({"<script>",
      "update Author",
      "  <set>",
      "    <if test='username != null'>username=#{username},</if>",
      "    <if test='password != null'>password=#{password},</if>",
      "    <if test='email != null'>email=#{email},</if>",
      "    <if test='bio != null'>bio=#{bio}</if>",
      "  </set>",
      "where id=#{id}",
      "</script>"})
    void updateAuthorValues(Author author);

6.5.bind

<select  resultType="Blog">
  <bind name="pattern" value="'%'   _parameter.getTitle()   '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

6.6.trim

<select  parameterType="blogs">
	select * from test.blog
    <trim prefix="WHERE" prefixOverride="AND |OR ">
        <if test="titleMap != null"> AND title = #{titleMap}</if>
        <if test="authorMap != null"> OR author = #{authorMap}</if>
    </trim>
</select>
<update  parameterType="map">
	update test.blog
    <trim prefix="SET" suffixOverride=",">
        <if test="titleMap != null"> title = #{titleMap},</if>
        <if test="authorMap != null"> author = #{authorMap},</if>
    </trim>
    where id = #{idMap}
</update>

6.7.多数据库查询适用

假如配备了 databaseIdProvider,你也就能够 在动态性编码中应用名叫 “_databaseId” 的变数来为不一样的数据库查询搭建相应的句子。例如接下来的事例:

<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>

6.8.动态性 SQL 中的插进开发语言

MyBatis 从 3.2 版本号进行适用插进开发语言,这容许你插进一种语言表达推动,并根据这类语言表达来撰写动态性 SQL 查看句子。

能够 根据完成下列插口来插进一种语言表达:

public interface LanguageDriver {
  ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
  SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
  SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}

完成自定语言表达推动后,你也就能够 在 mybatis-config.xml 文档里将它设定为默认设置 语言表达:

<typeAliases>
  <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
</typeAliases>
<settings>
  <setting name="defaultScriptingLanguage" value="myLanguage"/>
</settings>

或是,你还可以应用 lang 特性为特殊的句子特定语言表达:

<select  lang="myLanguage">
  SELECT * FROM BLOG
</select>

或是,在你的 mapper 插口上加上 @Lang 注释:

public interface Mapper {
  @Lang(MyLanguageDriver.class)
  @Select("SELECT * FROM BLOG")
  List<Blog> selectBlog();
}

7.注释

image-20210824160741551

优点和缺点:

  • 优势:省掉繁杂的mapper映射器中的sql编码有关配备
  • 缺陷:没法实行繁杂的SQL,比如:存有字段名出现异常不搭配时,应用注释实行SQL非常容易发生找不着值的状况(查看結果为'null')
 @Select("select * from school.users where id = #{userId}")
    Users getUserInfoById(@Param("userId") int id);

    @Insert("insert into school.users value(#{id},#{username},#{password},#{email},#{gender})")
    int insertUserInfo(@Param("userId") int id
            ,@Param("userName") String username
            ,@Param("userPassword") String password
            ,@Param("userEmail") String email
            ,@Param("userGender") int gender
    );

    @Delete("delete from school.users where id = #{userId}")
    int deleteUserInfoById(@Param("userId") int id);

    @Update("update school.users set username = #{userName} , password = #{userPassword} , email = #{userEmail} , gender = #{userGender} where id = #{userId}")
    int updateUserInfoById(
            @Param("userId") int id
            ,@Param("userName") String username
            ,@Param("userPassword") String password
            ,@Param("userEmail") String email
            ,@Param("userGender") int gender
    );

8.日志

Mybatis 根据应用自带的日志加工厂给予日志作用。内嵌日志加工厂可能把日志工作中委派给接下来的完成之一:

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

在mybatis-config.xml中人们早已设定了日志的默认设置为STDOUT_LOGGING规范日志輸出

 <!--配日志-SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

检测輸出

image-20210824182641931

8.1.Log4J

  • Log4j是Apache的一个开源软件,根据应用Log4j,能够 操纵日志信息内容运输的终点是控制面板、文档、GUI组件,乃至是套插口网络服务器、NT的事情监控软件、UNIX Syslogxinetd等;
  • 操纵每一条日志的輸出文件格式;根据界定每一条日志信息内容的等级,可以更为仔细地操纵日志的产生全过程。
  • 根据一个环境变量来灵敏地开展配备,而不用改动运用的编码。
  1. 导进Maven依靠

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  2. 映射器打开日志作用

    <configuration>
      <settings>
        ...
        <setting name="logImpl" value="LOG4J"/>
        ...
      </settings>
    </configuration>
    
  3. 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.txt
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

8.2.日志类应用

导进Apache-Log4J包

import org.apache.log4j.Logger;

应用反射面当今目标来建立当今Logger目标

// 建立静态变量Logger目标 => logger
// 应用当今类.class反射面建立logger目标
static Logger logger = logger.getLogger(UsersDaoTest.class)
@Test
public void log4jTest(){
    logger.info("info: 日志輸出级别【Info】");
    logger.debug("debug: 日志輸出级别【DEBUG】");
    logger.error("error: 日志輸出级别【ERROR】");
}

image-20210824183517453

评论(0条)

刀客源码 游客评论