• 第01篇_MyBatis基础应用

    第01章_MyBatis概述

    第一节 MyBatis简介

    1. 什么是MyBatis?

    MyBatis 是一个开源的、基于 Java 的持久层框架,它简化了数据库操作的复杂性,同时又提供了灵活的 SQL 映射机制。

     

    2. MyBatis入门案例

    1) 前置准备

    数据库中有一张 User 表,下面将使用 MyBatis 对其进行查询操作:

    该表对应的实体类DAO 接口如下:

    如果使用传统的 JDBC 或 JdbcTemplate ,那么下一步应该实现 DAO 接口,编写具体的 CURD 方法。

    但是,使用 MyBatis 后,你无需自己手写这些繁琐的实现类,这些 MyBatis 都会使用动态代理技术帮你生成。

     

    2) 依赖导入

    引入 MyBatis 相关的依赖如下:

    如果你使用的是Oracle或SqlServer数据库,应该切换如下驱动:

     

    3) 核心配置

    在类路径下新建src\main\resources\mybatis-config.xml配置文件,用来配置 MyBatis 的相关属性和行为:

    如果你使用的是Oracle或SqlServer数据库,JDBC连接四要素应修改如下:

     

    4) 映射配置

    在类路径下新建src\main\resources\org\example\dao\UserDao.xml配置文件,用于配置执行的SQL语句结果集映射方式

     

    5) 简单测试:使用MyBatis查询

    编写一个简单的测试类进行测试:

    运行结果如下:

    image-20210415231840857

    注意:

    1. 上述案例的完整工程代码可参考附件 mybatis-demo/demo01 工程!

     

     

    3. MyBatis核心类简介

    1) SqlSessionFactoryBuilder

    SqlSessionFactoryBuilder使用了构建者模式,用于解析配置文件和构建SqlSessionFactory,支持的构建方法如下:

    方式1已经在入门案例中介绍,方式2基于Java配置构建方式示例如下:

     

    2) SqlSessionFactory

    SqlSessionFactory使用了工厂模式,用于管理配置信息和创建SqlSession,支持的创建方法如下:

     

    3) SqlSession

    SqlSession是 MyBatis 的核心组件之一,用于执行 SQL 语句管理事务以及获取映射器对象(Mapper)等,主要方法如下:

     

    5) 映射器实例

    映射器通过SqlSessiongetMapper方法获取,本质上是一个 DAO 接口的动态代理类,内部保存了当前SqlSession对象的引用,主要用于执行SQL语句,并通过返回值获得执行结果。

    注意:

    1. 用于创建映射器的 DAO 接口,不能出现方法重载,否则会出现命名空间冲突。

    2. 映射器方法的参数名默认按位置命名为param1、param2...等,可以使用@Param注解进行修改。

     

     

    4. 使用映射器注解

    MyBatis支持在映射器上通过注解进行映射配置,示例如下:

    此时需修改核心配置mybatis-config.xml,通过注解进行扫描:

    注意

    1. 注意删除XML中该方法对应的映射配置,同一个映射器方法,不能同时存在两种配置方式

     

     

    5. MyBatis日志实现

    MyBatis按照SLF4J -> COMMONS_LOGGING -> LOG4J2 -> LOG4J -> JDK_LOGGING的顺序查找日志实现,可在配置文件中进行修改:

    此外,还可以配置为STDOUT_LOGGINGNO_LOGGING,或者其它实现了 org.apache.ibatis.logging.Log 接口的日志适配器

     

     

    第二节 MyBatis-Spring简介

    1. 什么是MyBatis-Spring?

    MyBatis-Spring是一个适配模块,可以将 MyBatis 无缝集成到 Spring 框架中,它可以:

     

     

    2. 基本整合流程

    1) 依赖导入

    引入相关依赖如下:

     

    2) 创建SqlSessionFactory

    Spring需要一个SqlSessionFactory保存配置信息创建SqlSession,可以通过SqlSessionFactoryBean来创建并注册到Spring容器。

    等效的 Java 配置如下:

    注意

    1. 可以直接通过依赖注入或继承 SqlSessionDaoSupport 的方式来获得容器中的 SqlSessionFactory 实例。

    2. 不建议直接调用该实例的 openSession() 方法获取SQL会话,因为通过该会话执行SQL时,不会参与到Spring管理的事务中,并且需要手动关闭该会话。

     

    3) 创建SqlSessionTemplate

    SqlSessionTemplate是SqlSession的实现类,与其它 Spring 模板类似,它将会话数据保存在线程变量中,是线程安全的。

    可以通过如下配置来创建SqlSessionTemplate,以代替 MyBatis 原生的DefaultSqlSession,将其注入到新创建的 Mapper 中,从而让 Spring 介入到 MyBatis 的会话管理,控制事务的提交和异常转换等相关操作。

    等效的Java配置如下:

    SqlSessionTemplate创建完毕并注册到Spring容器后,可以通过注入的方式,来使用它,如下所示。

    注意

    1. SqlSessionTemplate 是通过实现+组合方式对 DefaultSqlSession 的装饰,通过它执行SQL语句时,会获取 Spring 的事务管理器创建或获取当前线程会话,从而参与到Spring管理的事务中。

    2. 请勿直接调用 SqlSessionTemplate 的 commit()、rollback()、close() 方法,这将会抛出 UnsupportedOperationException 异常。

    3. SqlSessionTemplate是线程安全的,但是数据源等配置信息是各线程共享的,如果存在多个数据源,则需要创建多个实例。

     

    4) 创建Mapper

    一般来说,实际开发中,都会使用 MyBatis 的映射器来访问数据库,可以通过MapperFactoryBean来创建并注册到Spring容器。

    等效的java配置如下:

    然后就可以将映射器注入到你的业务对象中进行使用了。

    提示

    1. 你也可以为 MapperFactoryBean 传入一个 SqlSessionTemplate,这样将会使用其内部的 SqlSessionFactory,而忽略传入的那个。

     

     

    2. 创建SqlSessionFactoryBean详解

    在 MyBatis-Spring 整合工程中,一般通过 SqlSessionFactoryBean 来创建 SqlSessionFactory 并注册到 Spring 容器,以便 MapperFactoryBean或继承 SqlSessionDaoSupport 的类注入使用,其主要配置说明如下:

     

    1) configLocation

    configLocation 用来指定MyBatis配置文件路径。但这个配置文件并不是一个完整的MyBatis配置,它会忽略配置中的<environments><dataSource><transactionManager>等信息,但仍会解析<settings><typeAliases>等配置。

     

    2) mapperLocations

    mapperLocations用来指定映射配置文件路径。很多时候,映射配置文件和映射器类不在同一资源路径下,这时可以通过该属性来指定,并且可以同时指定多个路径和递归搜索。

    提示

    1. 你也可以通过配置上面的 configLocation 属性,指定 MyBatis 配置文件,在其<mappers>标签内指定映射器配置文件。

     

    3) databaseIdProvider

    如果你使用了多种数据库,那么需要设置 databaseIdProvider 属性。

     

    4) configuration

    configuration属性能够在没有对应的 MyBatis 配置文件的情况下,直接设置 Configuration 实例。例如:

     

    5) transactionFactoryClass

    transactionFactoryClass属性用于自定义事务工厂,一般不做配置。

     

     

    4. 创建SqlSessionTemplate详解

    MyBatis-Spring 工程提供的 SqlSessionTemplate,将会替代原 MyBatis 的 DefaultSqlSession 注入到映射器中,并且在注入前经过动态代理,在调用其方法时被拦截,用于控制事务和转换异常等操作。下面是创建时可以使用的一些配置参数:

     

    1) ExecutorType

    ExecutorType 用于指定 SqlSessionTemplate 的执行器类型,如下配置创建一个用于批处理的SqlSessionTemplate。

    等效的java配置如下:

    现在所有的映射语句可以进行批量操作了,可以在 DAO 中编写如下的代码。

    注意

    1. 同一个事务只能使用一种执行器,如果你需要不同的执行器执行SQL,请拆分为多个事务或完全不使用事务。

     

    2) SqlSessionDaoSupport

    SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。业务类继承它后,调用 getSqlSession() 方法就会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法,并参与 Spring 事务管理。

    前提是你为业务对象注入了 SqlSessionFactory 或 SqlSessionTemplate,如果两个属性都被注入,那么SqlSessionFactory 将会被忽略。

     

     

    5. 批量创建Mapper

    1) <mybatis:scan>方式

    <mybatis:scan>标签与组件扫描所使用的<context:component-scan/>标签类似,通过base-package属性指定多个以逗号分割的包名,递归扫描发现的映射器,然后创建对应的 MapperFactoryBean 并注册到Spring中。

    下面是<mybatis:scan>标签的一些配置参数:

    默认情况下,注册的映射器都以映射器接口的首字母小写非全限定类名作为名称,你可以通过 @Component 或 JSR-330 标准中 @Named 注解来进行修改。

    注意

    1. <context:component-scan/>标签无法发现并注册映射器。因为映射器是一个接口,组建扫描时无法实例化。

    2. 映射器接口的Bean名称默认为首字母小写类名,可通过 @Component 或 @Named 注解修改。

     

    2) @MapperScan方式

    @MapperScan注解也可以用于批量创建Mapper,它会自动扫描basePackageClassesbasePackages包及其子包的映射器。

    注意

    1. 如果未定义 basePackageClassesbasePackages,则会从声明@MapperScan注解类的包中进行扫描。

    2. 同样的,@MapperScan 也可配置 sqlSessionFactory、sqlSessionTemplate、markerInterface、annotationClass 等属性。

     

    3) MapperScannerConfigurer方式

    MapperScannerConfigurer 是一个 BeanDefinitionRegistryPostProcessor,可以在容器创建的时候扫描映射器。

    如果有多个数据源,可以使用sqlSessionFactoryBeanNamesqlSessionTemplateBeanName 属性指定 sqlSessionFactory 或 sqlSessionTemplate 的 bean 名称(注意使用 vlaue 指定BenaName,而不是 ref 引用对象)。

     

    4) 注意事项

    为了支持 SpringBoot 2.2 的延迟初始化控制功能,新增了lazyInitialization属性,用于控制映射器的延迟初始化,默认为false。如果使用延迟初始化功能,开发人员需要了解以下限制,否则延迟初始化功能无法在您的应用程序上使用。

    但是,你可以通过使用 @DependsOn 同时初始化依赖 bean 来使用它,如下所示:

     

     

    6. 关于事务管理器

    MyBatis 与 Spring 整合后,使用同一个事务管理器(默认为DataSourceTransactionManage),在事务开启时,会创建一个全新的 DefaultSqlSession ,当事务完成后,这个 session 会以合适的方式提交或回滚。

     

    1) 配置事务管理器

    MyBatis使用与 JDBC 相同的事务管理器 DataSourceTransactionManager,并且配置方式一致,详情可以参考 Spring 事务相关讲解。

    等效的java配置如下:

    注意

    1. 为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的是同一个数据源,否则事务管理器就无法工作了。

     

    2) 事务控制

    你可以使用 @Transaction 注解或 AOP 方式来配置哪些方法应该进行事务控制,这和 Spring 事务章节所讲述的方式相同。也可以使用Spring 提供的编程式API来精细控制事务,如下案例所示。

     

     

    第三节 MyBatis-Spring-Boot-Starter

    MyBatis-Spring-Boot-Starter用于快速构建基于SpringBoot 和 Mybatis 的应用程序。

     

    1. 基本整合流程

    1) 依赖导入

    首先从官方文档查找合适的依赖版本。

    image-20220511160136884

    如果你使用 Maven来管理项目,则可以通过下面配置来引入依赖。

     

    2) 自动配置

    当容器中只有一个DataSource时(或存在主候选对象),MyBatis-Spring-Boot-Starter 会进行自动配置。自动配置包括以下一些内容:

     

    3) 基础使用

    只需要将映射器接口加上@Mapper注解即可,容器启动时会自动扫描类路径下带@Mapper注解的映射器并注册到容器中。

    然后就可以通过注入的方式使用该映射器了。

    同样,也可以通过注入的方式使用已配置好的SqlSessionFactory和SqlSessionTemplate。

    注意:

    1. 如果需要修改扫描路径扫描指定的注解/接口,可以结合 MyBatis-Spring 提供的@MapperScan注解。

     

    4) 高级扫描

    MyBatis-Spring-Boot-Starter还会检测容器中存在的InterceptorTypeHandlerDatabaseIdProviderLanguageDriver接口实现类,并将它们添加到 Configuration 中。

     

    5) SpringBootVFS

    MyBatis-Spring-Boot-Starter提供的SpringBootVFS继承自MyBatis框架的VFS(虚拟文件系统),用于从应用程序或应用服务器加载指定的类,如别名对应的类、类型处理器等。

    在自动配置 SqlSessionFactory 时,将会默认使用,但在自定义 SqlSessionFactory 时,需要通过下面示例代码显式调用。

     

     

    2. 修改MyBatis配置

    1) YML方式

    使用mybatis前缀来配置MyBatis的相关属性,部分属性说明如下,完整的属性列表及说明可参考MybatisProperties

    属性说明
    config-locationmybatis.xml配置文件的位置
    mapper-locations映射器xml配置文件的位置
    type-aliases-package需要注册类型别名的包,可用,;\t\n做分隔
    check-config-location是否对mybatis.xml配置文件执行状态检查
    type-aliases-super-type注册别名时,仅当实现了该类时才注册
    type-handlers-package类型处理器所在包,用,;\t、'\n'做分隔
    executor-type默认的执行器类型,可选SIMPLE``REUSE``BATCH
    default-scripting-language-driver默认脚本语言驱动程序类(mybatis-spring 2.0.2+)
    configuration-propertiesMyBatis配置的外部化属性,指定的属性可以用作MyBatis配置文件和映射器文件的占位符
    lazy-initialization是否启用映射器bean的延迟初始化(mybatis-spring 2.0.2+)
    mapper-default-scope通过自动配置扫描的映射器Bean的默认范围(mybatis-spring 2.0.6+)
    mybatis.inject-sql-session-on-mapper-scan是否注入SqlSessionTemplate,2.2.1+版本默认为true(否则注入SqlSessionFactory)
    configuration.*mybatis.xml的setting属性,注意不可与config-location属性一起使用
    scripting-language-driver.thymeleaf.*Thymeleaf语言驱动特定属性
    scripting-language-driver.freemarker.*FreeMarker语言驱动特定属性
    scripting-language-driver.velocity.*Velocit语言驱动特定属性

    下面是一个简单的使用案例。

     

    12) ConfigurationCustomizer方式

    实现ConfigurationCustomizer接口可对 Configuration 进行全面的 Java 配置。

     

    3) SqlSessionFactoryBeanCustomizer方式

    实现SqlSessionFactoryBeanCustomizer接口可对SqlSessionFactoryBean进行全面的Java配置(2.2.2+版本)。

     

     

     

    第02章_配置文件详解

    第一节 properties标签

    1. 定义属性

    通过 properties 标签定义属性名和属性值:

    注意:

    1. 不同位置配置的属性优先级如下:直接通过 build() 方法传入的属性 > 引入文件中配置的属性 > 内部property标签定义的属性。

     

    2. 使用属性

    mybatis-config.xml 中使用属性:

    注意:

    1. 使用属性时可以设置默认值,但需要启用 enable-default-value 开关

     

     

    第二节 settings标签

    1. 设置参数

    通过settings标签可设置各项参数,以调整 MyBatis 的默认行为:

     

     

    第三节 typeAliases标签

    1. 内置别名

    MyBatis默认定义了许多别名,其中基本类型一般为下划线+类型名,包装类型一般为类名小写

    别名(不区分大小写)映射的类型
    _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

     

    2. 定义别名

     

    3. 使用别名

    在MyBatis配置使用全类名的地方,都可以使用别名代替:

     

     

    第四节 typehandlers标签

    1. 内置类型处理器

    在设置SQL参数或从结果集取值时,需要类型处理器进行 JDBC 类型和 Java 类型的转换,MyBatis内置的类型处理器如下:

    类型处理器Java 类型JDBC 类型
    BooleanTypeHandlerjava.lang.Boolean、boolean数据库兼容的 BOOLEAN
    ByteTypeHandlerjava.lang.Byte、byte数据库兼容的 NUMERIC 或 BYTE
    ShortTypeHandlerjava.lang.Short、short数据库兼容的 NUMERIC 或 SMALLINT
    IntegerTypeHandlerjava.lang.Integer、int数据库兼容的 NUMERIC 或 INTEGER
    LongTypeHandlerjava.lang.Long、long数据库兼容的 NUMERIC 或 BIGINT
    FloatTypeHandlerjava.lang.Float、float数据库兼容的 NUMERIC 或 FLOAT
    DoubleTypeHandlerjava.lang.Double、double数据库兼容的 NUMERIC 或 DOUBLE
    BigDecimalTypeHandlerjava.math.BigDecimal数据库兼容的 NUMERIC 或 DECIMAL
    StringTypeHandlerjava.lang.StringCHAR, VARCHAR
    ClobReaderTypeHandlerjava.io.Reader-
    ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
    NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
    NClobTypeHandlerjava.lang.StringNCLOB
    BlobInputStreamTypeHandlerjava.io.InputStream-
    ByteArrayTypeHandlerbyte[]数据库兼容的字节流类型
    BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
    DateTypeHandlerjava.util.DateTIMESTAMP
    DateOnlyTypeHandlerjava.util.DateDATE
    TimeOnlyTypeHandlerjava.util.DateTIME
    SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
    SqlDateTypeHandlerjava.sql.DateDATE
    SqlTimeTypeHandlerjava.sql.TimeTIME
    ObjectTypeHandlerAnyOTHER 或未指定类型
    EnumTypeHandlerEnumeration TypeVARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值)
    EnumOrdinalTypeHandlerEnumeration Type任何兼容的 NUMERIC 或 DOUBLE 类型,用来存储枚举的序数值(而不是名称)。
    SqlxmlTypeHandlerjava.lang.StringSQLXML
    InstantTypeHandlerjava.time.InstantTIMESTAMP
    LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
    LocalDateTypeHandlerjava.time.LocalDateDATE
    LocalTimeTypeHandlerjava.time.LocalTimeTIME
    OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
    OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
    ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
    YearTypeHandlerjava.time.YearINTEGER
    MonthTypeHandlerjava.time.MonthINTEGER
    YearMonthTypeHandlerjava.time.YearMonthVARCHAR 或 LONGVARCHAR
    JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

     

     

    2. 自定义类型处理器

    可以通过实现 org.apache.ibatis.type.TypeHandler 接口, 或继承org.apache.ibatis.type.BaseTypeHandler抽象类(推荐),来自定义类型处理器:

    自定义类型处理器需要在typehandlers标签进行配置:

    注意:

    1. 可以通过@MappedTypes 注解或typeHandler标签的javaType="String" 属性指定 Java 类型(优先)。

    2. 可以通过@MappedJdbcTypes 注解或typeHandler标签的jdbcType="VARCHAR" 属性指定 JDBC 类型(优先)。

    3. @MappedJdbcTypes 注解的 includeNullJdbcType=true 参数可以开启对 NULL 值的映射处理(默认关闭)。

     

     

    3. 泛型类型处理器

    泛型类型处理器可以处理某一类 java 类型和 JDBC 类型之间的转换:

     

     

    4. 枚举类型处理器

    EnumTypeHandlerEnumOrdinalTypeHandler 都是泛型类型处理器,它会处理任意继承了 Enum 的类,用于枚举值和枚举值名称或枚举值顺序之间的转换。

     

     

     

    第五节 objectFactory标签

    1. 自定义ObjectFactory

    ObjectFactory用于实例化结果对象,一般通过无参构造来完成,如果配置了构造参数,则调用对应的有参构造

    如需修改 ObjectFactory 的默认行为,可以对其进行自定义:

    自定义 ObjectFactory 在 mybatis-config.xmlobjectFactory标签中进行配置:

     

     

    第六节 plugins标签

    1. 自定义插件

    MyBatis 的插件可对如下一些方法进行拦截,并在其前后植入自定义代码:

    制作插件需要实现 Interceptor 接口,并指定想要拦截的方法签名:

    自定义插件在 mybatis-config.xmlplugins标签中进行配置:

     

    2. 插件案例:统计SQL执行时间

     

     

    第七节 environments 标签

    1. 配置 environment

    environments 标签定义了 SQL 执行环境相关的配置,并且支持多个 environment 子标签的定义。

    注意:

    1. 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择其中一个,默认环境通过 default 属性指定。

     

     

    2. 事务管理器

    1) 配置事务管理器

    在 MyBatis 中有两种类型的事务管理器:

    注意:

    1. 在使用 MANAGED 事务管理器的时候, 一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 。

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

     

    2) 自定义事务管理器

    如需自定义事务管理器,需要实现TransactionFactoryTransaction接口:

     

     

    3. 数据源

    1) 配置数据源

    dataSource 标签使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。有三种内建的数据源类型:

    注意:

    1. 可通过driver.前缀对数据库驱动进行配置,如:driver.encoding=UTF8,将会通过 DriverManager.getConnection(url, driverProperties) 方法进行传递。

    2. 数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

     

    2) 自定义数据源

    可通过实现 org.apache.ibatis.datasource.DataSourceFactory 接口或继承UnpooledDataSourceFactory 抽象类来使用第三方数据源实现:

    使用自定义的C3P0数据源如下:

     

     

    第八节 databaseIdProvider标签

    1. 配置数据库厂商

    为了方便后续使用,可在 mybatis-config.xml 中对各数据库厂商配置别名:

     

    2. 使用数据库厂商

    可以根据数据库厂商标识,针对不同数据库执行不同SQL:

    注意:

    1. databaseId配置只在同一资源文件生效,在不同资源文件,可能会先把通用的加载,再加载指定库的就会报错。

     

     

    3. 自定义DatabaseIdProvider

    可以通过实现接口 org.apache.ibatis.mapping.DatabaseIdProvider 来自定义数据库厂商别名配置行为(替换DB_VENDOR):

     

     

    第九节 mappers标签

    1. 配置映射文件

    这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了,也就是接下来我们要讨论的。

     

     

     

    第03章_映射文件详解

    第一节 语句定义标签

    1. select 标签

    select标签用于配置查询语句

    其可选的属性配置如下:

    属性描述
    parameterType参数类型,可自动推断,一般不填
    parameterMap参数映射,已废弃,推荐使用行内参数映射
    resultType结果类型
    resultMap结果映射
    flushCache语句执行前,是否清空本地缓存和二级缓存,默认为false
    useCache是否启用二级缓存,默认为true
    timeout查询超时时间,默认为空,取决于驱动配置
    fetchSize结果集提取批次数,默认为空,取决于驱动配置
    statementType语句类型,可选:STATEMENT、PREPARED、CALLABLE
    resultSetType结果集类型,可选:FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE,默认为空(DEFAULT)
    databaseId适用的数据库厂商
    resultOrdered结果是否被排序,默认为false,可能会用于优化性能
    resultSets设置多结果集名称列表,以逗号分隔

     

    2. insert/update和delete标签

    insertupdatedelete标签用于配置更新语句

    注意:

    1. insert、update和 delete 标签仅有语义上的区别,且都可以用来执行 DDL 语句

    2. flushCache属性对更新标签的默认值为true,而对查询标签的默认值为false

     

    此外,更新标签还有几个额外的属性配置,用于自增列回写

    属性描述
    useGeneratedKeys在执行insert和update语句时,是否回写数据库自动生成的主键(getGeneratedKeys),默认为false
    keyColumn主键列名,默认为第一列,复合主键以逗号分隔
    keyProperty主键列对应属性名,复合主键以逗号分隔,会被设置为getGeneratedKeys的返回值或通过selectKey标签设置

     

     

    3. selectKey标签

    selectKey标签可用于生成主键,并设置到 insert 语句的参数中:

    注意:

    1. selectKey 标签支持 keyProperty、keyColumn、resultType、statementType等属性,用法与之前类似。

    2. 此外,selectKey 标签还可以通过order属性选择在 insert 语句之前之后执行(BEFOREAFTER)。

     

     

    4. sql 标签

    sql标签用于定义可重用的SQL片段,以便在其它语句中使用:

    注意:

    1. 引用可嵌套,但注意必须要能够在加载时推断出来(而非运行时)。

     

     

    第二节 参数映射配置

    1. 行内参数映射

    注意:

    1. 默认情况下,MyBatis会按parm1、parm2、parm3....的顺序对参数进行命名。

    2. 如果采用 Java 8 及以上版本编译,并且加上 -parameters 选项,则可直接使用形参名作为参数名。

    3. 此外,也可以直接通过@Parm("xxx")注解显示指定参数名称。

    4. 如果只存在一个POJO参数,则可省略前缀,如参数列表为xxx(User user),则#{user.sex}可简写为#{sex}

    5. 如果参数是SQL语句的一部分,无法作为预编译参数?,则可使用${xxx}进行字符串替换,如:ORDER BY ${columnName} ,但需注意SQL注入问题。

     

     

    第三节 结果映射配置

    1. 简单结果映射

    使用select标签的resultType属性,可以进行简单结果映射

    如果查询数据返回多行,需要将 Mapper 方法的返回类型修改为集合类型,但resultType属性配置无需修改:

    注意:

    1. 可以在mybatis-config.xml中为JavaBean类型配置类型别名,这样resultType中就不用输入全限定类名了。

    2. 在映射到JavaBean类型时,如果列名和属性名无法匹配,则可以通过user_id as "id"方式为列起别名(SQL语法)。

     

     

    2. 自定义结果映射

    1) 基本映射

    使用select标签的resultMap属性,可以进行自定义结果映射

    注意:

    1. 默认情况下,MyBatis会自动映射未配置的列,可通过resultMap标签的autoMapping="false"属性关闭自动映射

    2. resultMap标签支持指定extends="parentResultMap"属性,对另一个映射配置进行继承,然后再覆盖和扩展。

    3. 子标签idresult可以指定jdbcTypetypeHandler,用于声明Java类型(映射到Map时)和自定义类型转换过程

     

    2) 嵌套结果映射

    嵌套结果映射指对复杂的关联查询的结果集进行嵌套映射,下面以一对一关联查询映射为例:

    一对多查询基本类似,只是多了一个ofType属性,用于指明集合元素的类型

    注意:

    1. 引用外部映射配置时,可以添加列别名前缀,如columnPrefix="co_"

    2. 可以通过notNullColumn属性配置非空列(以逗号分隔),只有在这些列非空时才会创建子对象。

     

    3) 嵌套Select查询

    嵌套Select查询指先查询主要字段,再通过N+1查询子对象字段,下面以一对一嵌套Select查询为例:

    一对多查询基本类似,只是多了一个ofType属性,用于指明集合元素的类型

    注意:

    1. column标签可通过column="{prop1=col1,prop2=col2}方式给嵌套Select查询传递多个参数

    2. 嵌套Select查询一般通过fetchType="lazy"方式设置懒加载,以防止过多的N+1查询。

     

    4) 多结果集查询

    某些数据库允许存储过程返回多个结果集,或一次性执行多个语句,每个语句返回一个结果集:

    在MyBatis中,可以对多结果集进行映射,下面以一对一多结果集映射为例:

    一对多查询基本类似,只是多了一个ofType属性,用于指明集合元素的类型

     

    5) 结果对象创建

    一般情况下,MyBatis通过无参构造创建结果对象,然后再通过 getter/setter 方法进行赋值,如果需要指定有参构造方法,则可通过<constructor>标签实现。

    注意:

    1. 如果映射配置顺序和构造方法字段顺序一致,则name属性可以省略。

    2. 此外,idArgarg标签还支持jdbcTypetypeHandlerselectresultMap等一些属性。

     

    6) 鉴别器

    鉴别器可根据某个列值进行不同的映射,类似于switch语句:

    注意:

    1. case标签还支持通过resultMap属性引用自定义映射,并且引用的自定义映射可以配置extends="vehicleResult"属性。

     

     

    3. 复杂案例

    下面是一个非常复杂的查询映射案例,可以作为学习参考。

     

     

    第四节 缓存配置

    1. 一级缓存配置

    一级缓存也叫会话缓存本地缓存(local cache),默认的缓存作用域为SESSION级别,可以在主配置文件的setting标签修改。

    如果想要命中一级缓存,必须要满足下面两个条件:

    同时需要注意,在下面一些情形会直接清空一级缓存。

    另外需注意:

     

     

    2. 二级缓存设置

    1) 全局二级缓存

    MyBatis在查询一级缓存之前,还会优先查找二级缓存,二级缓存是应用级别的缓存,适用于不同会话之间。要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行配置即可。

    使用二级缓存时必须注意一些相关事项:

    下面是一个二级缓存的简单测试案例。

     

    2) 语句级二级缓存

    可以使用 select/update/insert/delete 标签的属性进行更细粒度的缓存控制。

     

     

    3) 二级缓存行为属性

    二级缓存的行为可以通过 cache 标签的属性来修改。比如:

    这个更高级的配置创建了一个 FIFO 缓存,每隔 60000 毫秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

     

    4) 二级缓存引用

    对某一命名空间的语句,只会使用该命名空间的缓存进行缓存或刷新。 但你可能会想要在多个命名空间中共享相同的缓存配置和实例。要实现这种需求,你可以使用 cache-ref 元素来引用另一个缓存。

    注意:

    1. 即使在同一个命名空间,如果是通过注解和XML分别配置,则两者不会共享,需要通过缓存引用进行关联。

     

     

    3. 使用自定义缓存

    通过cache 标签的type属性,可以配置其他第三方缓存的适配器,来代替MyBatis内置的二级缓存模块。

     

    第三方缓存的适配器需要实现org.apache.ibatis.cache.Cache 接口,并提供一个接受 String 参数作为 id 的构造器。

     

    如需对缓存适配器进行配置,可直接通过如下方式,MyBatis将会自动匹配和调用对应的 set 方法

     

    如需对缓存适配器进行初始化,可实现 org.apache.ibatis.builder.InitializingObject 接口,将会在属性设置完毕后调用:

    注意:

    1. 上一节中对缓存的配置(如清除策略、可读或可读写等),不能应用于自定义缓存。

     

     

    第五节 动态SQL

    1. 常见动态SQL标签

    1) if 标签

    <if> 标签用于在动态 SQL 中根据条件动态拼接 SQL 语句:

     

    2) choose(when、otherwise)标签

    <choose> 标签允许根据多个条件动态选择 SQL 片段,类似 Java 中的 switchif-else if-else 的逻辑:

    注意:

    1. <choose> 标签中的 <when> 条件是按顺序检查的,一旦某个条件满足,后续的 <when><otherwise> 将被忽略。

     

    3) trim(where、set)标签

    trim标签用于移除指定前后缀,并在标签内容不为空时,添加新的前后缀

    也可直接使用内置的where标签和set标签:

     

    4) foreach标签

    <foreach> 标签用于处理集合数组类型的参数,适合在批量操作或动态生成 IN 子句等场景中使用。

    注意:

    1. <foreach> 标签的 collection 属性可以是任何可迭代对象,如:集合数组Map 类型。

    2. 当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。

    3. 当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

     

    5) bind标签

    bind 标签允许你在动态 SQL 中定义一个变量,并将其绑定到当前的上下文。

    6) script标签

    要在带注解的映射器接口类中使用动态 SQL,可以使用 script 标签。

     

     

    2. 自定义语言驱动

    前面的动态SQL标签由语言驱动 org.apache.ibatis.scripting.xmltags.XmlLanguageDriver(别名为 xml)提供支持。

    如需自定义语言驱动,可以实现LanguageDriver接口:

    并在 mybatis-config.xml 文件中将它设置为默认语言:

    或者,使用 lang 属性为特定的语句指定语言:

    或者,在 mapper 接口上添加 @Lang 注解:

    注意:

    1. 可以使用 Apache Velocity 作为动态语言,更多细节请参考 MyBatis-Velocity 项目。

     

     

    第六节 映射器注解

    1. 映射器注解概述

    映射器注解也可用于映射配置,下面是所有映射器注解列表:

    注解XML等价形式注解XML等价形式
    @Insert<insert>@CacheNamespace<cache>
    @Update<update>@CacheNamespaceRef<cacheRef>
    @Delete<delete>@FlushN/A
    @Select<delete>@InsertProvider<insert>
    @ParamN/A@UpdateProvider<update>
    @Results<resultMap>@DeleteProvider<delete>
    @Result<result>、<id>@SelectProvider<delete>
    @ConstructorArgs<constructor>@SelectKey<selectKey>
    @Arg<arg>、<idArg>@OptionsN/A
    @One<association>@Property<property>
    @Many<collection>@MapKeyN/A
    @ResultTypeN/A@TypeDiscriminator<discriminator>
    @ResultMapN/A@Case<case>

     

    2. 映射器注解示例

     

     

     

    第04章_MyBatis-Plus框架

    第一节 MyBatis-Plus简介

    1. 什么是MyBatis-Plus?

    MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

     

    2. 入门案例

    1) 导入Jar包

    注意:

    1. 使用 mybatis-plus 后,配置要使用 mybatis-plus 前缀开头:

     

    2) 定义Model

    提示:参考 https://baomidou.com/pages/223848/

     

    3) 定义Mapper

     

    4) 扫描Mapper

     

    5) 测试验证

     

     

    第二节 基本CURD

    1. BaseMapper

    1) BaseMapper<T>

     

    2) CURD案例

     

     

    2. IService

    1) IService<T>

     

    2) 批量CURD案例

     

     

    第三节 条件构造器

    1. QueryWrapper

    注意:

    1. 在 JDK8 版本,需要正确填写 QueryWrapper 的泛型参数,不可省略,否则编译会报错。

     

    2. UpdateWrapper

     

     

    第四节 常用注解

    1. 标识注解

    1) @TableName

    提示:

    1. 也可通过mybatis-plus.global-confi.db-config.table-prefix=t_来指定默认表前缀。

     

    2) @TableId

    注意:

    1. MyBatis-Plus 默认将id作为主键列,并在插入数据时,基于雪花算法的策略生成 id 值。

    2. MyBatis-Plus 不支持联合主键,需通过二次增强框架 MyBatis-Plus-Plus 实现。

    3. 主键生成策略支持雪花算法:IdType.ASSIGN_ID和数据库自增:IdType.AUTO等。

     

    3) @TableField

     

    注意:

    1. 驼峰与下划线风格的字段名与属性名可以相互兼容,例如属性 userName 可以兼容字段 user_name 。

     

    2. 功能注解

    1) @TableLogic

     

    2) @Version

    注意:

    1. 该功能需要注册乐观锁插件:OptimisticLockerInnerInterceptor

     

     

    第五节 扩展补充

    1. 分页插件

    1) 分页插件配置

     

    2) 简单分页查询

     

    3) XML分页查询

    按 MyBatis 的方式编写 Mapper 接口,只需在第一个参数传递@Param("page") Page<User> page

    XML配置无需特殊修改:

    查询时会自动根据分页参数进行分页处理:

     

     

    2. 通用枚举

    一种通过 @EnumValue 注解标识枚举属性值,并在插入和查询时进行映射的方式,不推荐。