• Mybatis【全面学习 一篇就够】


    在这里插入图片描述

    Mybatis学习笔记

    一、Mybatis框架

    1.概述

    1. mybatis是什么?有什么特点?

      它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它和数据库无关性较低。

    1. 什么是ORM?

    Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指得是数据库中的关系模型,对象关系映射,指的就是Java对象和数据库的关系模型之间建立一种对应关系。比如:用一个Java的Student类,去对应数据库中的一张student表,一个Student对象就对应student表中的一行数据,类中的属性和表中的列一一对应。

    1. 为什么Mybatis是半自动的ORM框架?

    用Mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。用hibernate开发,只需要定义好ORM映射,就可以直接进行CRUD操作了。由于Mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialet),所以Mybatis的数据库无关性比较低。虽然Mybatis需要手写SQL,但相比JDBC,他提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发效率。

    2.原理示意图

    img

    1. Mybatis配置

      SQLMapConfig.xml,此文件作为Mybatis的全局配置文件,配置了Mybatis的运行环境等信息,此后会有详细介绍。mapper.xml文件即SQL映射文件,文件中配置了操作数据库的SQL语句。此文件需要在SQLMapConfig.xml中加载。

    2. 通过Mybatis环境等配置信息构造SqlSessionFactory,即会话工厂

    3. 有会话工厂(SqlSessionFactory)创建sqlSession即会话,操作数据库需要通过sqlSession进行。

    4. Mybatis底层自定义了Executor执行器接口来操作数据库,Executor接口有两个实现,一个是基本执行器,一个是缓存执行器

    5. Mybatis底层自定义了Executor执行器接口来操作数据库,Executor接口有两个实现,一个是基本执行器,一个是缓存执行器

    6. Mapped Statement也是Mybatis一个底层封装对象,它包含了Mybatis配置信息以及SQL映射信息等。mapper.xml文件中一个SQL对应一个Maped Statement对象,SQL的id即是Mapped Statement的id。

    7. Mapped Statement对SQL输入参数进行定义,包含HashMap、基本数据类型、POJO等,Executor通过Mapped Statement在执行SQL前,将输入的java对象映射到SQL中,输入参数映射就是在JDBC编程中对PreparedStatement设置参数。

    8. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo等,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果集的解析处理过程

    二、入门程序

    1.原生开发

    1.在jdbc数据库中,创建一张tbl_employee表(d_id字段暂时用不到)和tbl_dept表(本阶段暂时用不到此表)

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

    2.打开IDEA,创建一个maven项目

    3.导入依赖jar包

    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <groupId>com.wangsuhanggroupId>
        <artifactId>MyBatis3artifactId>
        <version>1.0-SNAPSHOTversion>
        <packaging>warpackaging>
        <properties>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <maven.compiler.source>1.8maven.compiler.source>
            <maven.compiler.target>1.8maven.compiler.target>
        properties>
        <dependencies>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.12version>
            dependency>
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.9version>
            dependency>
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.4.1version>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.16version>
            dependency>
            <dependency>
                <groupId>commons-logginggroupId>
                <artifactId>commons-loggingartifactId>
                <version>1.1.1version>
            dependency>
        dependencies>
        
        <build>
            <resources>
                <resource>
                    <directory>src/main/javadirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>falsefiltering>
                resource>
                <resource>
                    <directory>src/main/resourcesdirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>falsefiltering>
                resource>
            resources>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-pluginartifactId>
                    <version>3.1version>
                    <configuration>
                        <source>1.8source>
                        <target>1.8target>
                    configuration>
                plugin>
            plugins>
        build>
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    4.创建一个pojo类(一个映射类)

    package com.wangsuhang.mybatis_01_helloworld.pojo;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    /**
     * @author suahng
     * @date 2021-07-06 9:56
     * @dec
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Employee {
        private Integer id;
        private String lastName;
        private String email;
        private String gender;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5.编写mapper.xml文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
            
    <mapper namespace="com.wangsuhang.mybatis_01_helloworld">
    <select id="getEmpById" resultType="com.wangsuhang.mybatis_01_helloworld.pojo.Employee">
            select id,last_name lastName,email,gender from tbl_employee where id = #{id}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.编写全局配置文件SQLMapConfig.xml( mybatis-config.xml)

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        
        <settings>
            
            <setting name="logImpl" value="STDOUT_LOGGING"/>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/jdbc"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                dataSource>
            environment>
        environments>
        
        <mappers>
        	
            <mapper resource="EmployeeMapper.xml" />
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    7.测试代码和运行结果

    package com.wangsuhang.mybatis_01_helloworld.test;
    import com.wangsuhang.mybatis_01_helloworld.mapper.EmployeeMapper;
    import com.wangsuhang.mybatis_01_helloworld.pojo.Employee;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    public class MyBatisTest {
        /**
         * 1.根据xml配置文件(全局配置文件 mybatis-config.xml )创建一个 SqlSessionFactory 对象
         *      有数据源的一些信息
         * 2.sql映射文件(EmployeeMapper2.xml):配置了每一个sql,以及 sql 的封装规则
         * 3.将 sql 映射文件注册在全局配置文件中
         * 4.在测试类中写具体的代码:
         *       1)根据全局配置文件得到 SQLSessionFactory
         *       2)使用 SQLSession工厂,获取 sqlSession 对象,使用他来执行增删改查
         *           一个 sqlSession 就是代表和数据库的一个会话,用完关闭
         *       3)使用 sql 的唯一标识来告诉 MyBatis执行哪个SQL。 sql都是保存在sql映射文件中
         */
        @Test
        public void testMyBatis() throws IOException {
            //1.获取sqlSessionFactory对象
            String config = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(config);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            System.out.println(sqlSessionFactory);
            //2.获取 sqlSession 实例,能直接执行已经映射的 sql 语句
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //sql的唯一标识:statement- Unique identifier matching the statement to use.
            //即mapper.xml文件中的namespace + SQL语句的id
            //执行SQL要用的参数:parameter- A parameter object to pass to the statement.
            Employee employee = sqlSession.selectOne("com.wangsuhang.mybatis_01_helloworld.getEmpById", 1);
            System.out.println(employee);
            //关闭资源
            sqlSession.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    运行结果

    com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 com.wangsuhang.mybatis_01_helloworld.test.MyBatisTest,testMyBatis
    Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@f6c48ac
    Opening JDBC Connection
    Created connection 81009902.
    Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4d41cee]
    ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? 
    ==> Parameters: 1(Integer)
    <==    Columns: id, lastName, email, gender
    <==        Row: 1, admin, jerry@qq.com, 女
    <==      Total: 1
    Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
    Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4d41cee]
    Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4d41cee]
    Returned connection 81009902 to pool.
    Process finished with exit code 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.Mapper动态代理方式开发DAO

    1.实现原理

    Mapper接口开发放肆只需要程序员编写Mapper接口(相当于DAO接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同DAO接口的实现类方法。

    Mapper接口开发需要遵循以下规范:

    • mapper.xml文件中namespace与mapper的全类名相同。
    • Mapper接口方法名和mapper.xml中定义的每个statement(即具体的SQL语句)的id相同。
    • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同。
    • Mapper接口方法的输出类型参数类型和mapper.xml中定义的每个resultType的类型相同。

    2.改写mapper.xml文件

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
            
    <mapper namespace="com.wangsuhang.mybatis_01_helloworld.mapper.EmployeeMapper">
    	<select id="getEmpById" resultType="com.wangsuhang.mybatis_01_helloworld.pojo.Employee">
            select id,last_name lastName,email,gender from tbl_employee where id = #{id}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.编写XxxMapper.java(接口文件)

    package com.wangsuhang.mybatis_01_helloworld.mapper;
    import com.wangsuhang.mybatis_01_helloworld.pojo.Employee;
    /**
     * @author suahng
     * @date 2021-07-06 14:18
     * @dec
     */
    public interface EmployeeMapper {
        public Employee getEmpById(Integer id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.测试代码和运行结果

    package com.wangsuhang.mybatis_01_helloworld.test;
    import com.wangsuhang.mybatis_01_helloworld.mapper.EmployeeMapper;
    import com.wangsuhang.mybatis_01_helloworld.pojo.Employee;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    /**
     * @author suahng
     * @date 2021-07-06 10:49
     * @dec
     *
     * 1.接口式编程
     *   原生:       Dao     ====>    DaoImpl
     *   mybatis:   Mapper  ====>    xxMapper.xml
     * 2.SqlSession:代表和数据库的一次会话,用完必须关闭
     * 3.SqlSession和Connection 一样它都是非线程安全。每次使用都应该获取新的对象
     * 4.mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象
     *      (将接口和xml进行绑定)
     *   EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
     * 5.两个重要的配置文件:
     *      mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息的那个...系统运行环境信息
     *      sql映射文件:保存了每一个sql语句的映射信息,将sql抽取了出来了
     */
    public class MyBatisTest {
        public SqlSessionFactory getSqlSessionFactory() throws IOException {
            String config = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(config);
            return new SqlSessionFactoryBuilder().build(is);
        }
        /**
         * 1.获取sqlSessionFactory对象
         *      解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSessionFactory
         *      注意:MappedStatement:代表一个增删改查的详细信息
         * 2.获取SQLSession对象
         *      返回一个DefaultSqlSession对象,包含Executor和Configuration
         *      这一步会创建Executor对象;
         * 3.获取接口的代理对象(MapperProxy)
         *      getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
         *      代理对象里面包含了,DefaultSqlSession(Executor)
         *
         * 4.执行增删改操作
         *
         *
         * 总结:
         * 1.根据配置文件(全局,sql映射)初试化出Configuration对象
         * 2.创建一个DefaultSqlSession对象,
         *      他里面包含Configuration以及
         *      Executor(根据全局配置文件的defaultExecutorType创建出对应的Executor)
         * 3.DefaultSqlSession.getMapper(),拿到Mapper接口对应的MapperProxy
         * 4.MapperProxy里面有(DefaultSqlSession);
         * 5.执行增删改查方法:
         *      1)调用DefaultSession的增删改查(Executor);
         *      2)会创建一个StatementHandler对象;(同时也会创建出ParameterHandler和ResultSetHandler)
         *      3)调用StatementHandler预编译参数以及设置参数值;
         *          使用ParameterHandler来给sql设置参数
         *      4)调用StatementHandler的增删改查方法;
         *      5)ResultSetHandler封装结果
         * 注意:
         *  四大对象(Executor,ParameterHandler,ResultSetHandler,StatementHandler)
         *  每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler)
         *
         * @throws IOException
         */
        @Test
        public void test01() throws IOException {
            //1.获取sqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
            //2.获取SQLSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            try {
                //3.获取接口的实现类对象
                //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
                EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                System.out.println(mapper.getClass());
                Employee emp = mapper.getEmpById(1);
                System.out.println(mapper.getClass());
                System.out.println(emp);
            }finally {
                //4.关闭资源
                sqlSession.close();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87

    运行结果

    com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 com.wangsuhang.mybatis_01_helloworld.test.MyBatisTest,test01
    Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    PooledDataSource forcefully closed/removed all connections.
    class com.sun.proxy.$Proxy4
    Opening JDBC Connection
    Created connection 1039949752.
    Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3dfc5fb8]
    ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? 
    ==> Parameters: 1(Integer)
    <==    Columns: id, lastName, email, gender
    <==        Row: 1, admin, jerry@qq.com, 女
    <==      Total: 1
    class com.sun.proxy.$Proxy4
    Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
    Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3dfc5fb8]
    Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3dfc5fb8]
    Returned connection 1039949752 to pool.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Process finished with exit code 0

    三、全局配置文件

    1.配置文件内容

    全局配置文件中,各个标签要按照如下的顺序进行配置,因为Mybatis加载配置文件的原码中是按照这个顺序进行解析的。

    <configuration>
    	
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    各个标签说明如下:

    • properties(属性)

    • settings(全局配置参数)

    • typeAliases(类型别名)

    • typeHandlers(类型处理器)

    • objectFactory(对象工厂)

    • plugins(插件)

    • environments(环境集合属性对象)

      • environment(环境子属性对象)
        • transactionManager(事务管理器)
        • dataSource(数据源)
    • databaseIdProvider(数据库厂商标识)

    • mappers(映射器)

    1.1properties(属性)

    这些属性可以在外部进行配置,并可以进行动态替换。

    classpath下定义dbconfig.properties文件

    jdbc.username=root
    jdbc.password=root
    jdbc.url=jdbc:mysql://localhost:3306/jdbc?rewriteBatchedStatements=true
    jdbc.driver=com.mysql.jdbc.Driver
    
    • 1
    • 2
    • 3
    • 4

    全局配置文件中引用如下:

    	<properties resource="dbconfig.properties"/>
        
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                dataSource>
            environment>
        environments>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    • 首先读取在 properties 元素体内指定的属性。
    • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
    • 最后读取作为==方法参数即(parameterType)==传递的属性,并覆盖之前读取过的同名属性。

    因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

    1.2settings(全局配置参数)

    这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

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

    一个配置完整的 settings 元素的示例如下:

    <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="multipleResultSetsEnabled" value="true"/>
      <setting name="useColumnLabel" value="true"/>
      <setting name="useGeneratedKeys" value="false"/>
      <setting name="autoMappingBehavior" value="PARTIAL"/>
      <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
      <setting name="defaultExecutorType" value="SIMPLE"/>
      <setting name="defaultStatementTimeout" value="25"/>
      <setting name="defaultFetchSize" value="100"/>
      <setting name="safeRowBoundsEnabled" value="false"/>
      <setting name="mapUnderscoreToCamelCase" value="false"/>
      <setting name="localCacheScope" value="SESSION"/>
      <setting name="jdbcTypeForNull" value="OTHER"/>
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    本例中使用的settings元素有:

        
        <settings>
            
            <setting name="logImpl" value="STDOUT_LOGGING"/>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.3 typeAliases(类型别名)

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

    <typeAliases>
      <typeAlias alias="Author" type="domain.blog.Author"/>
      <typeAlias alias="Blog" type="domain.blog.Blog"/>
      <typeAlias alias="Comment" type="domain.blog.Comment"/>
      <typeAlias alias="Post" type="domain.blog.Post"/>
      <typeAlias alias="Section" type="domain.blog.Section"/>
      <typeAlias alias="Tag" type="domain.blog.Tag"/>
    typeAliases>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

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

    <typeAliases>
      <package name="domain.blog"/>
    typeAliases>
    
    • 1
    • 2
    • 3

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

    @Alias("author")
    public class Author {
        ...
    }
    
    • 1
    • 2
    • 3
    • 4

    下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

    别名映射的类型
    _bytebyte
    _longlong
    _shortshort
    _intint
    _integerint
    _doubledouble
    _floatfloat
    _booleanboolean
    stringString
    byteByte
    longLong
    shortShort
    intInteger
    integerInteger
    doubleDouble
    floatFloat
    booleanBoolean
    dateDate
    decimalBigDecimal
    bigdecimalBigDecimal
    objectObject
    mapMap
    hashmapHashMap
    listList
    arraylistArrayList
    collectionCollection
    iteratorIterator

    所以,我们在别名的时候,不要占用上面已有的别名,它们都是大小写不敏感的。

    1.4typeHandlers(类型处理器)

    MyBatis 在设置预处理语句(PreparedStatement)中的参数,或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

    理解:用于处理Java类型和Jdbc类型之间的转换,mybatis有许多内置的TypeHandler

        <select id="getEmpById" parameterType="int" resultType="com.wangsuhang.mybatis_01_helloworld.pojo.Employee">
            select id,last_name lastName,email,gender from tbl_employee where id = #{id}
        select>
    
    • 1
    • 2
    • 3

    1.5objectFactory(对象工厂)

    mybatis会根据resultTyperesultMap的属性来将查询得到的结果封装成对应的Java类,它有一个默认的DefaultObjectFactory,用于创建对象实例,这个标签用的也不多

    1.6plugins(插件)

    可以用来配置mybatis的插件,比如在开发中经常需要对查询结果进行分页,就需要用到pageHelper分页插件,这些插件就是通过这个标签进行配置的。

    
    <plugins>
      <plugin interceptor="com.github.pagehelper.PageInterceptor">
         <property name="helperDialect" value="mysql"/>
      plugin>
    plugins>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.7environments(环境配置)

    MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置。

    不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境

    所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:

    • 每个数据库对应一个 SqlSessionFactory 实例

    为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);
    
    • 1
    • 2

    如果忽略了环境参数,那么将会加载默认环境,如下所示:

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);
    
    • 1
    • 2

    environments 元素定义了如何配置环境。

    environment:指定据具环境

    • id:指定当前环境的唯一标识
    • transactionManager:事务管理器
    • dataSource:数据源
    <environments default="development">
      <environment id="development">
        <transactionManager type="JDBC">
          <property name="..." value="..."/>
        transactionManager>
        <dataSource type="POOLED">
          <property name="driver" value="${driver}"/>
          <property name="url" value="${url}"/>
          <property name="username" value="${username}"/>
          <property name="password" value="${password}"/>
        dataSource>
      environment>
    environments>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意一些关键点:

    • 默认使用的环境 ID(比如:default=“development”)。
    • 每个 environment 元素定义的环境 ID(比如:id=“development”)。
    • 事务管理器的配置(比如:type=“JDBC”)。
    • 数据源的配置(比如:type=“POOLED”)。

    默认环境和环境 ID 顾名思义, 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

    本例中使用如下:

        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/jdbc"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                dataSource>
            environment>
        environments>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.8databaseIdProvider(数据库厂商标识)

    MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:

        <databaseIdProvider type="DB_VENDOR">
            
            <property name="MySQL" value="mysql1"/>
            <property name="Oracle" value="oracle"/>
        databaseIdProvider>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在mapper.xml中使用:

        <select id="getEmpById" resultType="com.wangsuhang.mybatis_02_config.pojo.Employee"
            databaseId="mysql1">
            select id,last_name lastName,email,gender from tbl_employee where id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 4

    Mybatis匹配规则如下:

    • 如果没有配置databaseIdProvider标签,那么databaseId=null;
    • 如果配置了databaseIdProvider标签,使用标签配置的name去匹配数据库信息,匹配上,则设置databaseId=配置指定的值,否则,依旧为null;
    • Mybatis会加载不带databaseId属性和带有匹配当前数据库databaseId属性的所有语句。如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被舍弃。

    1.9mappers(映射器)

    mapper配置的几种方法:

    • 使用相对于类路径的资源引用

          <mappers>
              <mapper resource="EmployeeMapper3.xml" />
              <mapper resource="EmployeeMapperPlus.xml" />
              <mapper resource="DepartmentMapper.xml"/>
          mappers> 
      • 1
      • 2
      • 3
      • 4
    • 使用完全限定资源定位符(UEL)

      <mapper url="file:///F:\code\MyBatis3\src\main\resources\EmployeeMapper2.xml" /> 
      • 使用映射器接口实现类的完全限定类名

        注意:

        1.有sql映射文件,映射文件名必须和接口同名,并且与接口统一目录下;

        2.没有sql映射 文件,所有的sql都是利用注解写在接口上

            <mappers>
                <mapper resource="EmployeeMapper2.xml" />
                <mapper class="com.wangsuhang.mybatis_02_config.mapper.EmployeeMapperAnnotation"/>
            mappers>
        
        • 1
        • 2
        • 3
        • 4

      本例中使用的是第二种方式:

      package com.wangsuhang.mybatis_02_config.mapper;
      import com.wangsuhang.mybatis_01_helloworld.pojo.Employee;
      import org.apache.ibatis.annotations.Select;
      /**
       * @author suahng
       * @date 2021-07-06 20:23
       * @dec
       */
      public interface EmployeeMapperAnnotation {
          @Select("select * from tbl_employee where id = #{id}")
          public Employee getEmpById(Integer id);
      }
       
        • 将包内的映射器接口实现全部注册为映射器

          注意:

          此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中

          <mappers>
            <package name="org.mybatis.builder"/>
          mappers> 
          • 1
          • 2
        • 四、参数传递

          1.输入参数

          1.1单个参数

          可以接收基本类型,对象类型,集合类型的值。这种情况下Mybatis可以直接使用这个参数,不需要经过任何处理。

          dao接口:

          package com.wangsuhang.mybatis_03_mapper.mapper;
          import com.wangsuhang.mybatis_03_mapper.pojo.Employee;
          /**
           * @author suahng
           * @date 2021-07-06 14:18
           * @dec
           */
          public interface EmployeeMapper {
              public Employee getEmpById(Integer id);
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

        mapper.xml文件中对应的sql语句:

        	<select id="getEmpById" resultType="com.wangsuhang.mybatis_03_mapper.pojo.Employee">
                select id,last_name lastName,email,gender from tbl_employee where id = #{id}
            select>
        
        • 1
        • 2
        • 3

        测试程序及结果

            @Test
            public void test() throws IOException {
                SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
                //1.获取到的SQLSession不会自动提交数据
                SqlSession sqlSession = sqlSessionFactory.openSession();
                try {
                    EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                    Employee emp = mapper.getEmpById(1);
                    System.out.println(emp);
                    sqlSession.commit();
                }finally {
                    sqlSession.close();
                }
            }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? 
        ==> Parameters: 1(Integer)
        <==    Columns: id, lastName, email, gender
        <==        Row: 1, admin, jerry@qq.com, 女
        <==      Total: 1
        Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        

        1.2.多个参数

        1.2.1多个参数-按位置

        任意多个参数,都会被Mybatis重新包装成一个Map传入。Map的key是param1,param2… 或arg0,arg1…;value就是参数的值;

        dao接口:

        List<Employee> getEmpByIdOrLastName(Integer id,String lastName);
        
        

        mapper.xml文件中对应的sql语句:

            
            <select id="getEmpByIdOrLastName" resultType="com.wangsuhang.mybatis_03_mapper.pojo.Employee">
                select id,last_name lastName,email,gender from tbl_employee where id = #{param1} or last_name = #{arg1}
            select>
        
        

        测试程序及结果:

        	EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
            List<Employee> emps = mapper.getEmpByIdOrLastName(1, "admin");
            emps.forEach(System.out::println);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 36333492.
        Returned connection 36333492 to pool.
        Opening JDBC Connection
        Checked out connection 36333492 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@22a67b4]
        ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? or last_name = ? 
        ==> Parameters: 1(Integer), admin(String)
        <==    Columns: id, lastName, email, gender
        <==        Row: 1, admin, jerry@qq.com, 女
        <==      Total: 1
        Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@22a67b4]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@22a67b4]
        Returned connection 36333492 to pool.
        
        
        1.2.2多个参数-使用@Param

        为参数使用@param起一个名字,Mybatis就会将这些参数封装进map中,key就是我们自己指定的名字。

        即在方法中形参前面加入@param(“自定义参数”),mapper.xml文件中使用#{自定义参数名}

        dao接口:

        	public Employee getEmpByIdAndLastName(@Param("id") Integer id, @Param("lastName") String lastName);
        
        

        mapper.xml文件中对应的sql语句:

            <select id="getEmpByIdAndLastName" resultType="com.wangsuhang.mybatis_03_mapper.pojo.Employee">
                select id,last_name lastName,email,gender from tbl_employee where id = #{id} and last_name = #{lastName}
            select>
        
        

        测试程序及结果:

             EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
             Employee emp = mapper.getEmpByIdAndLastName(1, "admin");
             System.out.println(emp);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? and last_name = ? 
        ==> Parameters: 1(Integer), admin(String)
        <==    Columns: id, lastName, email, gender
        <==        Row: 1, admin, jerry@qq.com, 女
        <==      Total: 1
        Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        Process finished with exit code 0
        
        
        1.2.3多个参数-使用对象(POJO)

        当这些参数属于我们业务在中的POJO时,我们直接传递POJO。

        使用java对象传递参数,java的属性值就是SQL语句需要的参数值。每个属性就是一个参数。

        语法格式:#{property,javaType=java中数据类型名,jdbcType=数据库中数据类型名};javaType,jdbcType的类型Mybatis可以检测出来,一般不需要设置,常用格式为#{property};

        dao接口:

        	public Employee getEmpbyPojo(Employee employee);
        
        

        mapper.xml文件中对应的sql语句:

            <select id="getEmpbyPojo" parameterType="com.wangsuhang.mybatis_03_mapper.pojo.Employee"
                    resultType="com.wangsuhang.mybatis_03_mapper.pojo.Employee">
                select id,last_name lastName,email,gender from tbl_employee where id = #{id} or last_name = #{lastName}
            select>
        
        

        测试程序及结果:

                    EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                    Employee employee = new Employee();
                    employee.setId(1);
                    employee.setLastName("admin");
                    Employee emp = mapper.getEmpbyPojo(employee);
                    System.out.println(emp);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? or last_name = ? 
        ==> Parameters: 1(Integer), admin(String)
        <==    Columns: id, lastName, email, gender
        <==        Row: 1, admin, jerry@qq.com, 女
        <==      Total: 1
        Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        Process finished with exit code 0
        
        

        异常测试:

        SQL语句中字段名输入错误后测试,将lastName改为lastname:

        org.apache.ibatis.exceptions.PersistenceException: 
        ### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'lastname' in 'class com.wangsuhang.mybatis_03_mapper.pojo.Employee'
        ### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'lastname' in 'class com.wangsuhang.mybatis_03_mapper.pojo.Employee'
        Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'lastname' in 'class com.wangsuhang.mybatis_03_mapper.pojo.Employee'
        Process finished with exit code -1
        
        
        1.2.4多个参数-使用map

        也可将多个参数封装为map,直接传递,mapper.xml文件使用#{key}引用参数值。

        dao接口:

        	public Employee getEmpByMap(Map<String,Object> map);
        
        

        mapper.xml文件中对应的sql语句:

            <select id="getEmpByMap" resultType="com.wangsuhang.mybatis_03_mapper.pojo.Employee">
                select id,last_name lastName,email,gender from tbl_employee where id = #{id} and last_name = #{lastName}
            select>
        
        

        测试程序及结果:

                    EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                    HashMap<String, Object> map = new HashMap<>();
                    map.put("id",1);
                    map.put("lastName","admin");
                    Employee emp = mapper.getEmpByMap(map);
                    System.out.println(emp);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select id,last_name lastName,email,gender from tbl_employee where id = ? and last_name = ? 
        ==> Parameters: 1(Integer), admin(String)
        <==    Columns: id, lastName, email, gender
        <==        Row: 1, admin, jerry@qq.com, 女
        <==      Total: 1
        Employee(id=1, lastName=admin, email=jerry@qq.com, gender=女)
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        Process finished with exit code 0
        
        

        2.输出参数

        2.1使用resultType

        resultType:执行SQL得到ResultSet转换的类型,使用类型的完全限定名或别名。注意,如果返回的是集合,那应该设置为集合包含的类型,而不是结合本身。

        resultType和resultMap,不能同时使用。

        2.1.1简单类型

        简单类型:8种java原始类型+String

        dao接口:

        public int getEmpCount();
        
        

        mapper.xml文件中对应的sql语句:

            <select id="getEmpCount" resultType="int">
                select count(*) from tbl_employee
            select>
        
        

        测试程序及结果:

                    EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                    int count = mapper.getEmpCount();
                    System.out.println(count);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select count(*) from tbl_employee 
        ==> Parameters: 
        <==    Columns: count(*)
        <==        Row: 30013
        <==      Total: 1
        30013
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        Process finished with exit code 0
        
        
        2.1.2对象类型(POJO)

        前面几个例子,一直在用这个,就不再另外举例了。

        2.1.3map

        SQL的查询结果作为Map 中的key和value;

        dao接口:

            // 返回一条记录的map:key是列名,值就是对于的值
            public Map<String,Object> getEmpByIdReturnMap(Integer id);
        
        

        mapper.xml文件中对应的sql语句:

            <select id="getEmpByIdReturnMap" resultType="java.util.Map">
                select * from tbl_employee where id = #{id}
            select>
        
        

        测试程序及结果:

                    EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
                    Map<String, Object> emp = mapper.getEmpByIdReturnMap(1);
                    System.out.println(emp);
        
        
        Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        PooledDataSource forcefully closed/removed all connections.
        Created connection 1333592072.
        Returned connection 1333592072 to pool.
        Opening JDBC Connection
        Checked out connection 1333592072 from pool.
        Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        ==>  Preparing: select * from tbl_employee where id = ? 
        ==> Parameters: 1(Integer)
        <==    Columns: id, last_name, email, gender, d_id
        <==        Row: 1, admin, jerry@qq.com, 女, 1
        <==      Total: 1
        {gender=女, d_id=1, last_name=admin, id=1, email=jerry@qq.com}
        Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@4f7d0008]
        Returned connection 1333592072 to pool.
        
        Process finished with exit code 0
        
        

        2.2使用resultMap

        resultMap可以自定义SQL的结果和java对象属性的映射关系。更灵活的把列值赋值给指定的属性。

        使用方式:

        1. 先定义resultMap,指定列名和属性的对应关系