Mybatis学习笔记

Mybatis

环境:

  • JDK 1.8
  • Maven 3.6.1
  • mysql 5.7
  • IDEA

学习必备前置

  • Java基础
  • mysql基础
  • JDBC ——还未系统学过
  • Maven——还未系统学过
  • JUnit——还未系统学过

说明💃学习技术框架的最好的方式:看官方文档(很多官方文档都有中文版)

1、Mybatis简介

1.1 什么是Mybatis

image-20211217154202313

  • MyBatis 是一款优秀的持久层框架

  • 它支持自定义sql、存储过程以及高级映射——暂未理解

  • 几乎免除了所有的JDBC代码以及设置参数和获取结果集的工作

  • Mybatis可以通过简单的XML或注解来配置和映射【原始类型、接口、Java POJO】为数据库中的记录

1.1.1 历史

历史:MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis 。2013年11月迁移到Github

iBATIS一词来源于“internet”和“abatis”(释义:有刺铁丝网,可结合“持久”这个概念进行联想)的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

1.1.2 特点

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

1.1.3 Mybatis获取方式

Maven仓库配置:

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>

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

mybatis源码中文注释: https://github.com/tuguangquan/mybatis

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

1.2 持久化

什么是持久化?

  • 持久化是将程序数据在持久状态到瞬时状态间转换的机制;通俗讲就是讲瞬时数据(比如内存的数据,不能永久保存,断电即失)持久化为持久数据(比如持久化到数据库中,可永久保存)
  • 生活中的例子:冰箱冷藏、罐头

为什么需要持久化?

  • 因为内存是断电即失,而有些对象需要进行长期保存,不希望断点即失
  • 内存的价格通常为外存的2~3个数量级(一般说的数量级都是以10为底数(10的多少次幂)),可见内存价格非常昂贵

什么是持久层?

类似Controller层、Dao层、Service层,持久层是一个完成持久化工作的代码块

1.3 为什么需要mybatis

  • 简单易学、使用的人多
  • 让程序员从复杂的JDBC操作中解放出来【简化、自动化】
  • 实现sql与程序代码的解耦、分离

2、第一个Mybatis程序

思路:搭建环境–》导入Mybatis(jar包)–》编写代码 --》测试

2.1 搭建环境

搭建数据库

// 创建数据库
CREATE DATABASE 'mybatis';
// 使用数据库
USER 'mybatis';
// 创建user表
DROP TABLE IF EXISTS user;
CREATE TABLE user(idint(20) NOT NULL,namechar(30) DEFAULT NULL,pwdchar(30) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
// 插入数据
INSERT INTOuserVALUES ('1', '狂神', '123456');
INSERT INTOuserVALUES ('2', '张三', '123456');
INSERT INTOuserVALUES ('3', '李四', '123456');

新建项目

  1. 新建一个普通的Maven项目

  2. 删掉src

  3. 导入依赖

    <!--导入依赖-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
        <!--Junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    

2.2 创建模块

1、创建新模块mybati-01 …n

2、在 Resources下新建mybatis核心配置文件mybatis-config.xml

XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)

下面只是最关键的一些配置,还有很多其他可加的配置项。

关键配置解读

  • XML 头部的声明,它用来验证 XML 文档的正确性
  • environment 元素体中包含了事务管理和连接池的配置
  • mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息
<?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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicodetrue&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
</configuration>

**每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。**SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件(Resources)进行配置。 MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易

通过SqlSessionFactory获得sqlSession,sqlSession完全包含了面向数据库执行SQL语句的所有方法

3、编写Mybatis工具类

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    /**
     * 1.使用Mybatis的第一步:获取SqlSessionFactory
     */
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 2.从 SqlSessionFactory 中获取 SqlSession, 可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
     */
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

2.3 编写代码

  • 实体

    package com.panwj.pojo;
    
    import lombok.Data;
    
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    
  • dao接口:写方法签名(获取sql数据的方法)

userMapper.java

package com.panwj.dao;

import com.panwj.pojo.User;

import java.util.List;

public interface userMapper {
    List<User> listUser();
}
  • 实现dao接口:userMapper.xml 设计sql查询语句

userMapper.xml

<?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.panwj.dao.userMapper">
    <select id="listUser" resultType="com.panwj.pojo.User">
        select * from user
    </select>
</mapper>

还有另一种方法来完成语句映射,它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。比如,上面的 XML 示例可以被替换成如下的配置:

package com.panwj.dao;

import com.panwj.pojo.User;
import java.util.List;

public interface userMapper {
    @Select("select * from user")
    List<User> listUser();
}

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

2.4 测试代码

编写测试代码

package com.panwj.dao;

import com.panwj.pojo.User;
import com.panwj.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserMapperTest {
    @Test
    public void test(){
        // 获取sqlSession实例
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        // 方式一执行sql:获取Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.listUser();

        for (User user : userList){
            System.out.println(user.getName());
        }
    }
}

2.5 问题记录

1. 问题:说明,在进行模块化开发打jar包时,maven会将非java文件过滤掉,xml,properties配置文件等,但是这些文件又是必需的,使用此配置可以在打包时将不会过滤这些必需的配置文件。

解决:在父工程或者每个子模块的pom.xml配置文件中添加以下配置

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

2. 报错:Type interface com.panwj.dao.UserMapper is not known to the MapperRegistry.

原因:每一个mapper.xml文件都需要在核心配置文件中去注册(mybatis-config.xml)

<mappers>
        <mapper resource="com/panwj/dao/UserMapper.xml"/>
 </mappers>

完整:

<?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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicodetrue&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/panwj/dao/UserMapper.xml"/>
    </mappers>
</configuration>

2.6 作用域(Scope)和生命周期

理解不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。


对象生命周期和依赖注入框架

依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器,并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。


SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。


SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中。如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中,换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。


映射器实例

映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。 也就是说,映射器实例应该在调用它们的方法中被获取,使用完毕之后即可丢弃。 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,在这个作用域上管理太多像 SqlSession 的资源会让你忙不过来。 因此,最好将映射器放在方法作用域内。就像下面的例子一样:

// 获取sqlSession实例
SqlSession sqlSession = MybatisUtils.getSqlSession();

// 执行sql:获取Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

3、Mybatis增删改查

增删改需要提交事务:sqlSession.commit() 这样对数据库数据的操作才能成功

1、insert

mapper编写sql

<insert id="addUser" parameterType="com.panwj.pojo.User">
    insert into user (id, name, pwd) values (#{id}, #{name}, #{pwd})
</insert>

​ 测试

public void addUser(){
    User user = new User();
    user.setId(4);
    user.setName("王五");
    user.setPwd("123456");
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    int res = userMapper.addUser(user);
    if (res > 0){
        System.out.println("用户插入成功");
    }
    // 提交事务
    sqlSession.commit();
    sqlSession.close();
}

2、select

<select id="listUser" resultType="com.panwj.pojo.User">
    select * from user
</select>

3、delete

<delete id="deleteUserById" parameterType="int">
    delete from user  where id = #{id}
</delete>

4、update

<update id="updateUserById" parameterType="int">
    update user set {id, name, pwd} values (#{id}, #{name}, #{pwd})
</update>

5、resultMap和resultType的区别

  • resultType:期望从这条语句中返回结果的类全限定名或别名,例如:String、int、Map、List( 大小写不敏感),还可以pojo对象以及定义好的resultMap结果集

  • resultMap:在xml中定义好的结果集形式,id命名,然后xml中的resultType赋值为id值就可以用自定义的结果集了,例如:

    
    <resultMap id="baseResultMap" type="com.panwj.pojo.User">
        <result property="id" column="userId"/>
        <result property="name" column="userName"/>
        <result property="pwd" column="password"/>
    </resultMap>
    
    <select id="getUser" resultMap="baseResultMap">
            select * from user where id = #{id}
    </select>
    

注意:type这里如果类全限定名太长的话,类型别名是你的好帮手,使用它们,你就可以不用输入类的全限定名了。具体做法是在mybatis核心配置文件中进行配置

<typeAliases>
    <typeAlias type="com.panwj.pojo.User" alias="User"/>
</typeAliases>

然后上面的resultMap就可以这么写

<resultMap id="baseResultMap" type="User">
    <result property="id" column="userId"/>
    <result property="name" column="userName"/>
    <result property="pwd" column="password"/>
</resultMap>

resultMap 元素有很多子元素和一个值得深入探讨的结构。 下面是resultMap 元素的概念视图。

高级结果映射(resultMap)——待学习
  • constructor 用于在实例化类时,注入结果到构造方法中

    • idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
    • arg - 将被注入到构造方法的一个普通结果
  • id 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能

  • result 注入到字段或 JavaBean 属性的普通结果

  • associatio一个复杂类型的关联;许多结果将包装成这种类型

    • 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
  • collection 一个复杂类型的集合

    • 嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用
  • discriminato 使用结果值来决定使用哪个resultMap

    • case 基于某些值的结果映射
      • 嵌套结果映射 – case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射

最佳实践 最好逐步建立结果映射。单元测试可以在这个过程中起到很大帮助。 如果你尝试一次性创建像上面示例那么巨大的结果映射,不仅容易出错,难度也会直线上升。 所以,从最简单的形态开始,逐步迭代。而且别忘了单元测试! 有时候,框架的行为像是一个黑盒子(无论是否开源)。因此,为了确保实现的行为与你的期望相一致,最好编写单元测试。 并且单元测试在提交 bug 时也能起到很大的作用。

待学习——具体每个元素的使用案例说明

4、属性配置

1、核心配置文件

mybatis核心配置文件mybatis-config.xml包含了会深深影响mybatis行为的设置和属性信息

2、环境配置(environments)

environments(环境配置): environments 元素定义了如何配置环境

  • environment(环境变量) : id有开发development、测试test、生产release等不同的环境配置,根据需要进行配置;用哪个就设置defalut为哪个就好 例如

``

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value=""/>
        </dataSource>
    </environment>
    <environment id="test">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis-test?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value=""/>
        </dataSource>
    </environment>
    <environment id="release">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis-release?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value=""/>
        </dataSource>
    </environment>
</environments>
  • transactionManager(事务管理器) 一般都使用type=“JDBC” ,这个配置使用了JDBC的回滚和提交设施,它依赖从数据源获得的连接来管理事务作用域;

    提示: 如果使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

  • dataSource(数据源)连接数据库

    dataSource元素使用标准的JDBC数据源接口来配置JDBC连接对象的资源

    如:

    ``

    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </dataSource>
    

其中type=“POOLED”: POOLED– 这种数据源的实现利用**“池”的概念将 JDBC 连接对象组织起来**,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

datasource可配置的属性有很多,以下是最常见的基本设置

  • driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。

作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:

  • driver.encoding=UTF8

这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8encoding 属性给数据库驱动

  • url – 这是数据库的 JDBC URL 地址。
  • username – 登录数据库的用户名。
  • password – 登录数据库的密码。

还有更多属性用来配置 POOLED 的数据源:

  • defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
  • defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文档以获取更多信息。

作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如:

  • driver.encoding=UTF8
  • poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
  • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。
  • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
  • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
  • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnectionspoolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)
  • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。
  • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
  • poolPingConnectionsNotUsedFor – 配置 poolPingQuery 的频率。可以被设置为和数据库连接超时时间一样,来避免不必要的侦测,默认值:0(即所有连接每一时刻都被侦测 — 当然仅当 poolPingEnabled 为 true 时适用)。

连接数据库的

3、属性(properties)

我们可以通过properties元素来引入外部配置文件的东西,这样就不用在xml中把数据写死了

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,然后在xml中引入,例如我们常用的db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8
username=root
password

也可以在 properties 元素的子元素中设置。

<properties resource="db.properties"> -------引入外部配置文件
        <property name="username" value="root"/>  ------在 properties 元素的子元素中设置
        <property name="password" value=""/>
</properties>

注意:xml中规定了标签的存放顺序,顺序不对会报错
在这里插入图片描述

如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

属性读取优先级 : properties 元素中指定的属性 > resource/url 指定的配置文件 > 方法参数传递的属性

属性使用优先级 : 方法参数传递的属性 > resource/url 指定的配置文件 > properties 元素中指定的属性

4、类型别名(typeAliases)

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

好处:当这样配置时,User 可以用在任何使用 com.panwj.pojo.User 的地方。当实体类较少的时候推荐使用

<!--可以给实体类起别名-->
<typeAliases>
        <typeAlias type="com.panwj.pojo.User" alias="User"/>
</typeAliases>

<!--使用注解给实体类起别名-->
@Alias("VipUser")
public class User (){
	...
}

也可以指定一个包,这样Mybatis就会搜索这个包下要用到的Java Bean, 当实体类比较多的时候推荐使用

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

5、设置(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(deprecated since 3.5.9) | 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
nullableOnForEachSpecifies the default value of ‘nullable’ attribute on ‘foreach’ tag. (Since 3.5.9)true | falsefalse

一个配置完整的 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>

6、映射器(mappers)

mappers配置会告诉 MyBatis 去哪里找映射文件

<mappers>
    <!--第一种:使用相对类路径的资源引用-->
    <mapper resource="com/panwj/dao/UserMapper.xml"/>
    <!--第二种:使用完全限定资源定位符-->
    <mapper url="D:\practice\mybatis-study\mybatis-02\src\main\java\com\panwj\dao\UserMapper.xml"/>
    <!--第三种:使用映射器接口实现类的完全限定类名,要保证接口和mapper实现类同名且同包-->
    <mapper class="com.panwj.dao.UserMapper"/>
    <!--第四种:将包内的映射接口实现全部注册为为映射器,要保证接口和mapper实现类同名且同包-->
    <package name="com.panwj.dao"/>
</mappers>

5、面试题目

  1. 什么是mybatis?
    mybatis是一款基于Java的持久层框架,支持自定义SQL、存储过程和高级映射。它几乎免除了所有的JDBC代码以及设置和获取结果集的工作;可以通过xml或注解的方式来配置和映射 原始类型、接口和Java POJO为数据库中的记录。

  2. mybatis的优缺点?

    • 优点

      1. 相对于传统的JDBC,mybatis减少了50%以上的代码量,消除了JDBC大量的冗余代码,不需要手动开关连接
      2. 基于SQL语句编程,不会对应用程序或数据库的现有设计产生任何影响;sql语句写在xml文件中,解除了sql与程序代码的耦合,便于统一管理
      3. 提供xml标签,支持编写动态sql
      4. 提供映射标签,支持Java对象和数据库ORM字段关系映射
      5. 提供对象关系映射。
      6. mybatis兼容jdbc支持的所有数据库
    • 缺点

      1. sql编写工作了较大,当关联表多,字段多的时候,对sql语句的功底有一定要求
      2. sql依赖数据库,导致数据库移植性较差
  3. #{}和${}的区别是什么?

  • #{}是预处理; mybatismybatis处理sql时,会对sql进行预处理,将#{}转换成? ,然后调用PreparedStatement的set方法来赋值;使用#{}接收参数可以有效防止sql注入,提高系统安全性
  • 是 字 符 串 替 换 , m y b a t i s 处 理 s q l 时 , 直 接 把 {}是字符串替换,mybatis处理sql时,直接把 mybatissql{}替换成参数的值
  1. Mybatis中 Dao接口和XML文件的SQL如何建立关联?

  2. 通常一个mapper.xml文件,都会对应一个Dao接口,这个Dao接口的工作原理是什么?
    mapper接口的工作原理是JDK动态代理,mybatis运行时会使用JDK动态代理为mapper接口生成一个代理对象MapperProxy,代理对象会拦截接口方法,根据类的全限定名+方法名,唯一定位到xml文件中的一个mapperStatement并调用代理对象的执行器invoke()执行对应的sql语句,最终将sql执行结果返回;

  3. Dao接口里的方法,参数不同时,方法能重载吗?
    不能,因为mapper接口采用的是 类的全限定名+方法名 的唯一查找策略

    Dao接口即Mapper接口。接口的全限名,就是映射文件中的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;接口方法内的参数,就是传递给sql的参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值