zoukankan      html  css  js  c++  java
  • 入门级myBatis

    1章 MyBatis简介

    1.1 MyBatis历史

      1MyBatisApache的一个开源项目iBatis, 20106月这个项目由Apache Software Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下,iBatis3.x正式更名为MyBatis ,代码于201311月迁移到Github

      2iBatis一词来源于“internet”“abatis”的组合,是一个基于Java的持久层框架。iBatis提供的持久层框架包括SQL MapsData Access ObjectsDAO

    1.2 MyBatis简介

      1 MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架

      2MyBatis 避免了几乎所有的JDBC 代码和手动设置参数以及获取结果集

      3MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和JavaPOJOPlain Old Java Objects,普通的Java对象)映射成数据库中的记录

      4半自动ORMObject Relation Mapping`)框架

     

    1.为什么要使用MyBatis – 现有持久化技术的对比

    1    JDBC

           SQL夹在Java代码块里,耦合度高导致硬编码内伤

           维护不易且实际开发需求中sql是有变化,频繁修改的情况多见

    2    HibernateJPA

           难复杂SQL,对于Hibernate而言处理也不容易

           内部自动生产的SQL,不容易做特殊优化

           基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。导致数据库性能下降

     

    3    MyBatis

           对开发人员而言,核心sql还是需要自己优化

           sqljava编码分开,功能边界清晰,一个专注业务、一个专注数据

     

    1.如何下载MyBatis

    中文官网:https://mybatis.org/mybatis-3/zh/getting-started.html

    1    下载网址

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

     

     

    2章 MyBatis HelloWorld

    2.1 开发环境的准备

    1)        导入MyBatis框架的jar包、Mysql驱动包、log4jjar

     

    myBatis-3.4.1.jar
    
    mysql-connector-java-5.1.37-bin.jar
    
    log4j.jar

     

    2)        导入log4j 的配置文件

    <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
            <param name="Encoding" value="UTF-8"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) 
    "/>
            </layout>
        </appender>
        <logger name="java.sql">
            <level value="debug"/>
        </logger>
        <logger name="org.apache.ibatis">
            <level value="info"/>
        </logger>
        <root>
            <level value="debug"/>
            <appender-ref ref="STDOUT"/>
        </root>
    </log4j:configuration>

    2.2 创建测试表


    --
    创建库 CREATE DATABASE test_mybatis; -- 使用库 USE test_mybatis; -- 创建表 CREATE TABLE tbl_employee( id INT(11) PRIMARY KEY AUTO_INCREMENT, last_name VARCHAR(50), email VARCHAR(50), gender CHAR(1) );

    2.3 创建javaBean

    public class Employee {
        private Integer id ;
        private String lastName;
        private String email ;
        private String gender ;
        //生成set 和 get 方法...
    }

    2.4 创建MyBatis的全局配置文件

    1)        参考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>
        <!-- 数据库连接环境的配置 -->
        <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_1129"/>
                    <property name="username" value="root"/>
                    <property name="password" value="1234"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 引入SQL映射文件,Mapper映射文件     -->
        <mappers>
            <mapper resource="EmployeeMapper.xml"/>
        </mappers>
    </configuration>

     

    2.5 创建Mybatissql映射文件 

    1)        参考MyBatis的官方手册

     

        <select id = "selectEmployee" resultType="com.tuniu.data.helloWorld.Employee">
            select id ,last_name lastName ,email ,gender from tbl_employee where id = #{id}
            <!-- select * from tbl_employee  where id = #{id} -->
        </select>

     

    2.6 测试 

    1)        参考MyBatis的官方手册

        @Test
        public void test() throws Exception {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            System.out.println(sqlSessionFactory);
            SqlSession session = sqlSessionFactory.openSession();
            try {
                Employee employee = session.selectOne("suibian.selectEmployee", 1001);
                System.out.println(employee);
            } finally {
                session.close();
            }
        } 

    2.7 Mapper接口开发HelloWorld 

    1)        编写Mapper接口

    publicinterface EmployeeMapper {
        public Employee getEmployeeById(Integer id );
    }


    2)
            完成两个绑定 

           Mapper接口与Mapper映射文件的绑定

    Mppper映射文件中的<mapper>标签中的namespace中必须指定Mapper接口

    的全类名

           Mapper映射文件中的增删改查标签id必须指定成Mapper接口中的方法名.

    3)        获取Mapper接口的代理实现类对象

        @Test
        publicvoidtest() throws Exception {
    
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
            SqlSession session = sqlSessionFactory.openSession();
            try {
                //Mapper接口:获取Mapper接口的代理实现类对象
                EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
                Employee employee = mapper.getEmployeeById(1006);
                System.out.println(employee);
            } finally {
                session.close();
            }
        }

    3章 MyBatis全局配置文件 

    3.1 MyBatis全局配置文件简介

    1)        The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves.

    MyBatis 的配置文件包含了影响MyBatis 行为甚深的设置(settings)和属性(properties)信息。

    2)        文件结构如下:

    configuration 配置

    properties 属性

    settings 设置

    typeAliases 类型命名

    typeHandlers 类型处理器

    objectFactory 对象工厂

    plugins 插件

    environments 环境

    environment 环境变量

    transactionManager 事务管理器

    dataSource 数据源

    databaseIdProvider 数据库厂商标识

    mappers 映射器

    3.2 properties属性

    1)       可外部配置且可动态替换的,既可以在典型的Java 属性文件中配置,亦可通过properties 元素的子元素来配置

    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis" />
        <property name="username" value="root" />
        <property name="password" value="1234" />
    </properties>

     

    2)       然而properties的作用并不单单是这样,你可以创建一个资源文件,名为jdbc.properties的文件,将四个连接字符串的数据在资源文件中通过键值(key=value)的方式放置,不要任何符号,一条占一行  

    jdbc.driver=com.mysql.jdbc.Driver
    
    jdbc.url=jdbc:mysql://localhost:3306/mybatis_1129
    
    jdbc.username=root
    
    jdbc.password=1234
      

     

    <!--
    
    properties: 引入外部的属性文件
    
    resource: 从类路径下引入属性文件
    
    url:  引入网络路径或者是磁盘路径下的属性文件
    
    -->
    
    <properties resource="db.properties"></properties> 

     

    3)environment元素的dataSource元素中为其动态设置

        <environments default="oracle">
            <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>

    3.3 settings设置 

    1)        这是MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为。

    2)        包含如下的setting设置:

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

    完整的setting的属性配置:

     

    设置名描述有效值默认值
    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' 的日志等级必须设置为 WARN
    • FAILING: 映射失败 (抛出 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 是否允许在嵌套语句中使用结果处理器(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

     

     

     

    3.4 typeAliases 别名处理

     

    1)        类型别名是为Java 类型设置一个短的名字,可以方便我们引用某个类。

    <typeAliases>
    
        <typeAliastype="com.atguigu.mybatis.beans.Employee" alias="emp"/>
    
    </typeAliases>

      

    2)        类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简单类名小写

     

    <typeAliases>
    
        <packagename="com.atguigu.mybatis.beans"/>
    
    </typeAliases> 

     

    3)        MyBatis已经取好的别名

     

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

     

    别名映射的类型
    _byte byte
    _long long
    _short short
    _int int
    _integer int
    _double double
    _float float
    _boolean boolean
    string String
    byte Byte
    long Long
    short Short
    int Integer
    integer Integer
    double Double
    float Float
    boolean Boolean
    date Date
    decimal BigDecimal
    bigdecimal BigDecimal
    object Object
    map Map
    hashmap HashMap
    list List
    arraylist ArrayList
    collection Collection
    iterator Iterator

    3.environments 环境配置 

    1)        MyBatis可以配置多种环境,比如开发、测试和生产环境需要有不同的配置

    2)        每种环境使用一个environment标签进行配置并指定唯一标识符

    3)        可以通过environments标签中的default属性指定一个环境的标识符来快速的切换环境

    4)        environment-指定具体环境

    id:指定当前环境的唯一标识

    transactionManager、和dataSource都必须有

     

    <environments default="oracle">
            <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>
            <environment id="oracle">
                <transactionManager type="JDBC"/>    
                <dataSource type="POOLED">
                    <property name="driver" value="${orcl.driver}" />
                    <property name="url" value="${orcl.url}" />
                    <property name="username" value="${orcl.username}" />
                    <property name="password" value="${orcl.password}" />
                </dataSource>
            </environment>     
    </environments>

     

    5)        transactionManager:

     

    type:

     JDBC | MANAGED | 自定义

    JDBC:

    使用了JDBC 的提交和回滚设置,依赖于从数据源得到的连接来管理事务范围。JdbcTransactionFactory

    MANAGED:

    不提交或回滚一个连接、让容器来管理事务的整个生命周期(比如JEE应用服务器的上下文)。ManagedTransactionFactory

    自定义:

    实现TransactionFactory接口,type=全类名/别名

     6)        dataSource :

     

    Type

     UNPOOLED | POOLED | JNDI | 自定义

    UNPOOLED

    不使用连接池,UnpooledDataSourceFactory

    POOLED

    使用连接池,PooledDataSourceFactory

    JNDI

    EJB 或应用服务器这类容器中查找指定的数据源

    自定义

    实现DataSourceFactory接口,定义数据源的获取方式。

     

    7)        实际开发中我们使用Spring管理数据源,并进行事务控制的配置来覆盖上述配置

    3.mappers 映射器

    1)        用来在mybatis初始化的时候,告诉mybatis需要引入哪些Mapper映射文件

    2)        mapper逐个注册SQL映射文件

    resource : 引入类路径下的文件

    url :      引入网络路径或者是磁盘路径下的文件

         class :    引入Mapper接口.

    SQL映射文件, 要求Mapper接口与SQL映射文件同名同位置.

    没有SQL映射文件, 使用注解在接口的方法上写SQL语句.

     

    <mappers>
        <mapper resource="EmployeeMapper.xml" />
        <mapper class="com.atguigu.mybatis.dao.EmployeeMapper"/>
        <package name="com.atguigu.mybatis.dao"/>
    </mappers>

    3)   使用批量注册,这种方式要求SQL映射文件名必须和接口名相同并且在同一目录下

     

    <mappers>
        <package name="com.atguigu.mybatis.dao"/>
    </mappers>

     

    4章 MyBatis 映射文件 

    4.1 Mybatis映射文件简介

    1)        MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的XML 文件就显得相对简单。如果拿它跟具有相同功能的JDBC 代码进行对比,你会立即发现省掉了将近95% 的代码。MyBatis 就是针对SQL 构建的,并且比普通的方法做的更好。

    2)        SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

     

     

    cache

    给定命名空间的缓存配置

    cache-ref

    其他命名空间缓存配置的引用。

    resultMap

    是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

    parameterMap

    已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。

    sql

    可被其他语句引用的可重用语句块。

    insert

    映射插入语句

    update

    映射更新语句

    delete

    映射删除语句

    select

    映射查询语



    4.2 Mybatis使用insert|update|delete|select完成CRUD

    4.2.1 select

    1)        Mapper接口方法

     

    public Employee getEmployeeById(Integer id );

    2)        Mapper映射文件 

    <select id="getEmployeeById" 
              resultType="com.atguigu.mybatis.beans.Employee" 
              databaseId="mysql">
             select * from tbl_employee where id = ${_parameter}
    </select>

    4.2.2 insert

    1)        Mapper接口方法

     

    publicInteger  insertEmployee(Employee employee);

     

    2)        Mapper映射文件 

     

    <insert id="insertEmployee" parameterType="com.atguigu.mybatis.beans.Employee"  databaseId="mysql">
          insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    </insert>

     

    4.2.3  update 

    1)        Mapper接口方法

     

    publicBoolean  updateEmployee(Employee employee);

     

    2)        Mapper映射文件 

     

    <update id="updateEmployee" >
            update tbl_employee set last_name = #{lastName},
                                    email = #{email},
                                    gender = #{gender}
                                    where id = #{id}
    </update>

     

    4.2.4  delete 

    1)        Mapper接口方法

    publicvoid  deleteEmployeeById(Integer id );


     
    2)
            Mapper映射文件

    <deleteid="deleteEmployeeById">
    
        delete from tbl_employee where id = #{id}
    
    </delete>    

     

    4.3  主键生成方式、获取主键值 

    4.3.1 主键生成方式

    1)        支持主键自增,例如MySQL数据库

    2)        不支持主键自增,例如Oracle数据库

    4.3.2 获取主键值

    1)        若数据库支持自动生成主键的字段(比如MySQL SQL Server),则可以设置useGeneratedKeys=true”,然后再把keyProperty 设置到目标属性上。

    <insert id="insertEmployee"     parameterType="com.atguigu.mybatis.beans.Employee"  
                databaseId="mysql"
                useGeneratedKeys="true"
                keyProperty="id">
            insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    </insert>

       2)    升级到Mybatis版本到3.3.1。官方在这个版本中加入了批量新增返回主键id的功能

    4.4 参数传递 

    4.4.1 参数传递的方式

    1)        单个普通(基本/包装+String)参数

        这种情况MyBatis可直接使用这个参数,不需要经过任何处理。

        取值:#{随便写}

     

    2)        多个参数

      任意多个参数,都会被MyBatis重新包装成一个Map传入。Mapkeyparam1param2,或者01…,值就是参数的值

      取值:#{0 1 2 …N / param1  param2  ….. paramN}

     

    3)        命名参数

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

      取值: #{自己指定的名字/  param1  param2 … paramN}

     

    4)        POJO

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

      取值: #{POJO的属性名}

     

    5)        Map

      我们也可以封装多个参数为map,直接传递

      取值: #{使用封装Map时自己指定的key}

     

    6)        Collection/Array

      会被MyBatis封装成一个map传入, Collection对应的keycollection,Array对应的keyarray. 如果确定是List集合,key还可以是list.

    取值: 

    Array: 

    #{array}
    Collection(List/Set):  #{collection}
    List :  #{collection / list}

     

    4.4.2 参数传递源码分析

    1)        以命名参数为例:

    public Employee getEmployeeByIdAndLastName
    
    (@Param("id")Integerid, @Param("lastName")String lastName);

     2)        源码: 

        前提:  args=[1024,苍老师]    names={0=id ,1=lastName}

    public Object getNamedParams(Object[] args) {
        final int paramCount = names.size();
        if (args == null || paramCount == 0) {
          return null;
        } else if (!hasParamAnnotation && paramCount == 1) {
          return args[names.firstKey()];
        } else {
          final Map<String, Object> param = new ParamMap<Object>();
          int i = 0;
          for (Map.Entry<Integer, String> entry : names.entrySet()) {
            param.put(entry.getValue(), args[entry.getKey()]);
            // add generic param names (param1, param2, ...)
            final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
            // ensure not to overwrite parameter named with @Param
            if (!names.containsValue(genericParamName)) {
              param.put(genericParamName, args[entry.getKey()]);
            }
            i++;
          }
          return param;
        }
      }

    4.4.3 参数处理

    1)        参数位置支持的属性:

    javaTypejdbcTypemodenumericScaleresultMaptypeHandlerjdbcTypeNameexpression

    2)        实际上通常被设置的是:可能为空的列名指定jdbcType ,例如:

     

    insert into orcl_employee(id,last_name,email,gender) values(employee_seq.nextval,#{lastName, ,jdbcType=NULL },#{email},#{gender})    --Oracle

     

    4.4.4 参数的获取方式

    1)        #{key}可取单个普通类型、POJO类型、多个参数集合类型

           获取参数的值,预编译到SQL中。安全。PreparedStatement

    2)        ${key}可取单个普通类型、POJO类型、多个参数、集合类型.

        注意:取单个普通类型的参数,${}中不能随便写,必须使用_parameter

                  _parameter Mybatis的内置参数.

            获取参数的值,拼接到SQL中。有SQL注入问题。Statement

    原则:能用#{}取值就优先使用#{},#{}解决不了的可以使用${}.

      例如:原生的JDBC支持占位符的地方,就可以使用${}

      Select  column1 ,column2… from where 条件group by   组标识having  条件order by 排序字段 desc/asc  limit  x, x

    4.select查询的几种情况

    1)        查询单行数据返回单个对象

    public Employee getEmployeeById(Integer id );

     

    2)        查询多行数据返回对象的集合 

    public List<Employee> getAllEmps();

     

    3)        查询单行数据返回Map集合 

    public Map<String,Object> getEmployeeByIdReturnMap(Integer id );

      

    4)        查询多行数据返回Map集合 

    @MapKey("id") // 指定使用对象的哪个属性来充当map的key
    
    public Map<Integer,Employee>  getAllEmpsReturnMap();

     

    4.6 resultType自动映射 

     

    1)        autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是列名和javaBean属性名一致

    2)        如果autoMappingBehavior设置为null则会取消自动映射

    3)        数据库字段命名规范,POJO属性符合驼峰命名法,如A_COLUMNaColumn

        我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true

        注意:如果要使用 resultType 来接受和传递参数,那么一定要开启该属性,否者会出现实体类中的数据无法映射的问题

    4.7 resultMap自定义映射

    自定义resultMap,实现高级结果集映射

    1)        id :用于完成主键值的映射

    2)        result :用于完成普通列的映射

    3)        association :一个复杂的类型关联;许多结果将包成这种类型

    4)        collection 复杂类型的集

    4.7.1  id&result

    <select id="getEmployeeById" resultMap="myEmp">
            select id, last_name,email, gender from tbl_employee where id =#{id}
    </select>
    
    <resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmp">
            <id column="id"  property="id" />
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
    </resultMap>

    4.7.2 association

    1)        POJO中的属性可能会是一个对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用association标签定义对象的封装规则

     

    publicclass Department {
    
      private Integer id ;
    
      private String departmentName ;
    
    //  省略get/set方法
    
    }

     

    publicclass Employee {
    
        private Integer id ;
    
        private String lastName;
    
        private String email ;
    
        private String gender ;
    
        private Department dept ;
    
        // 省略get/set方法
    
    }

     

    2)        使用级联的方式:

    <select id="getEmployeeAndDept" resultMap="myEmpAndDept" >
            SELECT e.id eid, e.last_name, e.email,e.gender ,d.id did, d.dept_name FROM tbl_employee e , tbl_dept d   WHERE e.d_id = d.id  AND e.id = #{id}
    </select>
        
    <resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDept">
            <id column="eid" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
            <!-- 级联的方式 -->
            <result column="did" property="dept.id"/>
        <result column="dept_name" property="dept.departmentName"/>
    </resultMap>

     

    3)        Association

    <resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDept">
            <id column="eid" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
            <association property="dept" javaType="com.atguigu.mybatis.beans.Department">
                <id column="did" property="id"/>
                <result column="dept_name" property="departmentName"/>
            </association>
    </resultMap>

     

    4.7.3 association 分步查询

    1)        实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层,因此

    对于查询员工信息并且将对应的部门信息也查询出来的需求,就可以通过分步的方式

    完成查询。

           先通过员工的id查询员工信息

           再通过查询出来的员工信息中的外键(部门id)查询对应的部门信息.

     

    <select id="getEmployeeAndDeptStep" resultMap="myEmpAndDeptStep">
             select id, last_name, email,gender,d_id  from tbl_employee where id =#{id}
    </select>
        
    <resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDeptStep">
            <id column="id"  property="id" />
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
            <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id" fetchType="eager">
            </association>
    </resultMap>

    4.7.4 association 分步查询使用延迟加载

    1)        在分步查询的基础上,可以使用延迟加载来提升查询的效率,只需要在全局的Settings中进行如下的配置: 

    <!-- 开启延迟加载 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 设置加载的数据是按需还是全部 -->
    <setting name="aggressiveLazyLoading" value="false"/>

    4.7.5 collection

    1)        POJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用collection标签定义对象的封装规则

    public class Department {
        private Integer id ; 
        private String departmentName ;
        private List<Employee> emps ;
    }

      

    2)        Collection

    <select id="getDeptAndEmpsById" resultMap="myDeptAndEmps">
      SELECT 
        d.id did, d.dept_name ,e.id eid ,e.last_name ,e.email,e.gender   FROM tbl_dept d
      LEFT OUTER JOIN tbl_employee e ON d.id = e.d_id   WHERE d.id = #{id}
    </select> <resultMap type="com.atguigu.mybatis.beans.Department" id="myDeptAndEmps"> <id column="did" property="id"/> <result column="dept_name" property="departmentName"/> <!-- property: 关联的属性名 ofType: 集合中元素的类型 --> <collection property="emps" ofType="com.atguigu.mybatis.beans.Employee"> <id column="eid" property="id"/> <result column="last_name" property="lastName"/> <result column="email" property="email"/> <result column="gender" property="gender"/> </collection> </resultMap>

    4.7.6 collection 分步查询

    1)       实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层,因此

    对于查询部门信息并且将对应的所有的员工信息也查询出来的需求,就可以通过分步的方式完成查询。

           先通过部门的id查询部门信息

           通过部门id作为员工的外键查询对应的部门信息.

     

    <select id="getDeptAndEmpsByIdStep" resultMap="myDeptAndEmpsStep">
             select id ,dept_name  from tbl_dept where id = #{id}
    </select>
    <resultMap type="com.atguigu.mybatis.beans.Department" id="myDeptAndEmpsStep">
             <id column="id" property="id"/>
             <result column="dept_name" property="departmentName"/>
             <collection property="emps" 
                     select="com.atguigu.mybatis.dao.EmployeeMapper.getEmpsByDid"
                     column="id">
             </collection>
     </resultMap> 

    4.7.7 collection 分步查询使用延迟加载

    4.7.8 扩展: 分步查询多列值的传递

    1)        如果分步查询时,需要传递给调用的查询中多个参数,则需要将多个参数封装成

    Map来进行传递,语法如下: {k1=v1, k2=v2....}

    2)        在所调用的查询方,取值时就要参考Map的取值方式,需要严格的按照封装map

    时所用的key来取值.

    4.7.9 扩展: association collectionfetchType属性

    1)        <association> <collection>标签中都可以设置fetchType,指定本次查询是否要使用延迟加载。默认为fetchType=lazy” ,如果本次的查询不想使用延迟加载,则可设置为

    fetchType=”eager”.

    2)        fetchType可以灵活的设置查询是否需要使用延迟加载,而不需要因为某个查询不想使用延迟加载将全局的延迟加载设置关闭.

    5章 MyBatis 动态SQL

    5.1 MyBatis动态SQL简介

    1)        动态SQLMyBatis强大特性之一。极大的简化我们拼装SQL的操作

    2)        动态SQL 元素和使用JSTL 或其他类似基于XML 的文本处理器相似

    3)        MyBatis 采用功能强大的基于OGNL 的表达式来简化操作

    if

    choose (when, otherwise)

    trim (where, set)

    foreach

    4)        OGNLObject Graph Navigation Language )对象图导航语言,这是一种强大的

    表达式语言,通过它可以非常方便的来操作对象属性。类似于我们的ELSpEL

     

    访问对象属性

    person.name
    调用方法 person.getName()
    调用静态属性/方法

    @java.lang.Math@PI

    @java.util.UUID@randomUUID()

    调用构造方法 new com.atguigu.bean.Person(‘admin’).name
    运算符  +,-*,/,%
    逻辑运算符

    in,not in,>,>=,<,<=,==,!=

    注意:xml中特殊符号如”,>,<等这些都需要使用转义字符

     

     

     

     

     

     

     

     

     

     

     

          

         

                         

           

                

     

            

     

     

    5.if where

    1)        If用于完成简单的判断.

    2)        Where用于解决SQL语句中where关键字以及条件中第一个and或者or的问题

     

    <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.beans.Employee">
            select id , last_name ,email  , gender  
            from tbl_employee 
            <where>
                <if test="id!=null">
                    and id = #{id}
                </if>
                <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                    and last_name = #{lastName}
                </if>
                <if test="email!=null and email.trim()!=''">
                    and email = #{email}
                </if>
                <if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
                    and gender = #{gender}
                </if>
            </where>
    </select>

     

    5.trim

    1)        Trim 可以在条件判断完的SQL语句前后添加或者去掉指定的字符

    prefix: 添加前缀

    prefixOverrides: 去掉前缀

    suffix: 添加后缀

    suffixOverrides: 去掉后缀

     

    <select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.beans.Employee">
            select id , last_name ,email  , gender  
            from tbl_employee 
            <trim prefix="where"  suffixOverrides="and">
                <if test="id!=null">
                     id = #{id} and
                </if>
                <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                     last_name = #{lastName} and
                </if>
                <if test="email!=null and email.trim()!=''">
                     email = #{email} and
                </if>
                <if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
                    gender = #{gender}
                </if>
            </trim>
    </select>

     

    5.set

    1)        set 主要是用于解决修改操作中SQL语句中可能多出逗号的问题

     

    <update id="updateEmpByConditionSet">
            update  tbl_employee  
            <set>
                <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                     last_name = #{lastName},
                </if>
                <if test="email!=null and email.trim()!=''">
                     email = #{email} ,
                </if>
                <if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
                    gender = #{gender} 
                </if>
            </set>
             where id =#{id}
        </update>

     

    5.choose(whenotherwise)

    1)        choose 主要是用于分支判断,类似于java中的switch case,只会满足所有分支中的一个

     

    <select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.beans.Employee">
        select id ,last_name, email,gender from tbl_employee
            <where>
                <choose>
                    <when test="id!=null">
                        id = #{id}
                    </when>
                    <when test="lastName!=null">
                        last_name = #{lastName}
                    </when>
                    <when test="email!=null">
                        email = #{email}
                    </when>
                    <otherwise>
                         gender = 'm'
                    </otherwise>
                </choose>
            </where>
    </select>

     

    5.foreach

    1)        foreach 主要用户循环迭代

    collection 要迭代的集合
    item 当前从集合中迭代出的元素
    open 开始字符
    close 结束字符
    separator

    元素与元素之间的分隔符

    index

    迭代的是List集合: index表示的当前元素的下标

    迭代的Map集合:  index表示的当前元素的key

     


           

     

      

     

     

     

     

     

      

              

     

    <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.beans.Employee">
             select id , last_name, email ,gender from tbl_employee where  id in 
             <foreach collection="ids" item="curr_id" open="(" close=")" separator="," >
                     #{curr_id}
             </foreach>
    </select>

     

    5.sql

    1)        sql 标签是用于抽取可重用的sql片段,将相同的,使用频繁的SQL片段抽取出来,单独定义,方便多次引用.

    2)        抽取SQL:

     

    <sqlid="selectSQL">
    
      select id , last_name, email ,gender from tbl_employee
    
    </sql>

     

    3)        引用SQL:

    <includerefid="selectSQL"></include>

     

  • 相关阅读:
    Objective-C写出Json文件(可作配置文件)
    关于快速排序的部分内容
    关于折半查找排序的部分内容
    异步下载网络图片
    pytest(5):setup/teardown框架结构
    pytest(4):用例参数化
    pytest(3):pytest运行参数介绍
    pytest(2):使用pycharm运行pytest
    pytest(1):pytest的安装与使用
    pytest文档4-Allure报告清除上一次数据
  • 原文地址:https://www.cnblogs.com/lzghyh/p/14252723.html
Copyright © 2011-2022 走看看