MyBatis

mybatis整合spring之后,mybatis的配置文件“mybatis-config.xml”就好像没什么用了!

在pom.xml文件中不导入如下代码,就会报错:

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

出现如下的错误:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.heng.dao.BirdMapper.insert

at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53)
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:115)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)
at jdk.proxy2/jdk.proxy2.$Proxy8.insert(Unknown Source)

mybatis的核心配置文件:

(JDBC:手动

MyBatis:半自动

Hibernate:自动)

(mybatis-config.xml核心配置文件

<environments>配置连接数据库的环境

<mappers>引入映射文件)

(MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类)

查询功能的标签必须设置resultType或resultMap

resultType:设置默认的映射关系

resultMap:设置自定义的映射关系

id:唯一标识

类型别名不区分大小写

alias可写可不写。

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方法拼凑sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号。

mybatis的在进行对数据库操作的时候,如果在DAO接口中,所传递的参数是一个实例对象,那么在xml配置文件中,不能把对象中的属性名写错了!

<insert id="insert" parameterType="Bird">

insert into mybird (id,namese) values (#{id},#{namese});

</insert>

主键自增,居然用null

resource是路径,/代替‘.’ 。

MyBatis面向接口编程的两个一致:

  1. 映射文件的namespace要和mapper接口的全类名保持一致
  2. 映射文件中SQL语句的id要和mapper接口中的方法名一致

获取mapper接口对象

两者的区别是什么?

Spring 的上下文的使用!

两种转换的形式:

  • SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)
  • SqlSessionFactory:是“生产”SqlSession的“工厂”。
  • 工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类”中,以后都使用这个工厂类来“生产”我们需要的对象。

MyBatis同时支持XML和注解两种配置方式,帮助程序员屏蔽了近乎所有的JDBC代码,提高开发效率。

ORM(Object Relational Mapping)框架: 根据映射配置文件,完成数据在对象模型与关系模型之间的映射,同时也屏蔽了上述重复的代码,只暴露简单的API供开发人员使用。

mybatis的整体架构:

  • 基础支持层
  • 核心处理层
  • 接口层

基础支持层包含整个MyBatis的基础模块:

  • 反射模块
  • 类型转换模块
  • 日志模块
  • 资源加载模块
  • 数据源模块
  • 事务管理
  • 缓存模块
  • Binging模块

核心处理层:

  • 配置解析
  • SQL解析与scripting模块
  • SQL执行
  • 插件

接口层:

  • SqlSession接口

解析器模块

XML解析常见的方式有三种:

  • DOM(Document Object Model)
  • SAX(Simple API for XML)
  • StAX(Streaming API for XML)

DOM是基于树形结构的XML解析方式,他会将整个XML文档读入内存并构建一个DOM树,基于这棵树形结构对各个节点进行操作。

SAX是基于事件模型的XML解析方式,它并不需要将整个XML文档加载到内存中,而只需将XML文档的一部分加载到内存中,即可开始解析,在处理过程中并不会在内存中记录XML中的数据,所以占用的资源比较小。

XPath是一种为查询XML文档而设计的语言,它可以与DOM解析方式配合使用,实现对XML文档的解析。


从 XML 中构建 SqlSessionFactory

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

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="db.properties">
        <property name="username" value="root"/>
    </properties>

<!--    <settings>-->
<!--&lt;!&ndash;        <setting name="logImpl" value="STDOUT_LOGGING"/>&ndash;&gt;-->
<!--        <setting name="logImpl" value="LOG4J"/>-->
<!--    </settings>-->

    <typeAliases>
<!--        <package name="mybatis01.pojo"/>-->
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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>

    <mappers>
        <mapper resource="mybatis01/dao/UserMapper.xml"/>
        <mapper class="mybatis01.dao.UserMapper"/>
        <package name="mybatis01.dao"/>
    </mappers>
</configuration>

environment 元素体中包含了事务管理和连接池的配置。mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。

SqlSession(SQL会话接口)

SqlSession是MyBatis执行数据库操作的主要接口,定义了执行SQL、获取映射器和管理事务的方法。

该接口定义的方法主要有:

  • commit() : 提交事务
  • getMapper() : 通过java接口获取映射器

SqlSessionFactory(SQL会话工厂接口)

SqlSessionFactory接口很简单,其定义了获取SQL会话对象和全局配置实例的方法。openSession()方法用来获取SqlSession类型的实例,该方法有多个不同参数重载方法,设置的参数类型包括事务是否自动提交...

使用不含任何参数的openSession()方法获取会话的行为是:

  • 从数据源DataSource中获取数据库连接Connection对象和预处理语句。
  • 预处理语句不会被复用,也不会批量处理更新。
  • 开启一个事务(也就是不自动提交)
  • 事务隔离级别使用驱动或数据源的默认设置。

SqlSessionFactoryBuilder(SQL会话工厂构建类)

SqlSessionFactoryBuilder同样提供了getConfiguration()方法获取全局配置对象,DefaultSqlSessionFactory是SqlSessionFactory接口的默认实现类,会话工厂的实例通过会话工厂接口构造器(SqlSessionFactoryBuilder)的builder()方法构建。

探究已映射的 SQL 语句

事实上 MyBatis 提供的所有特性都可以利用基于 XML 的映射语言来实现,这使得 MyBatis 在过去的数年间得以流行。

映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。

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

配置

MyBatis全局配置文件的习惯命名是mybatis-config.xml。

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。

属性(properties)

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

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

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

XML映射文件配置

映射文件用来配置

接口方法的SQL执行语句和返回结果类型的映射,在调用映射器接口方法进行数据操作时,MyBatis框架会实际执行该配置中的SQL语句,并将数据库执行的结果转为映射配置的java类型对象。

<select>基本查询映射配置

resultType属性用来指定返回转换的Java对象类型,框架会依据此配置将数据库查询的结果进行自动转换。

JDBC的一般语句(Statement)在条件查询时,条件子句通过替换变量附加在SQL语句后执行;预编译语句()的参数支持使用占位符(?)方式,有效地避免了SQL注入的风险。MyBatis的映射文件对这两种方式都提供了支持,分别提供了${参数}和#{参数}方式进行参数替换。

设置(settings)

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

设置名描述有效值默认值
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | falsetrue
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | falsefalse
aggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
multipleResultSetsEnabled是否允许单个语句返回多结果集(需要数据库驱动支持)。true | falsetrue
useColumnLabel使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。true | falsetrue
useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。true | falseFalse
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehavior指定发现自动映射目标未知列(或未知属性类型)的行为。NONE: 不做任何反应WARNING: 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' 的日志等级必须设置为 WARN)FAILING: 映射失败 (抛出 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)一个类型别名或完全限定类名。未设置

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

org.apache.ibatis.io.Resources 是 MyBatis 框架中的一个类,用于读取资源文件。

getResourceAsStreamorg.apache.ibatis.io.Resources 类中的一个方法,用于读取资源文件并返回一个输入流。

MyBatis的各种查询功能:

  1. 若查询出的数据只有一条:①可以通过实体类对象接受;②可以通过list集合接收
  2. 若查询出的数据有多条:可以通过list集合接收
  3. 注意:一定不能通过实体类对象接收,此时会抛异常TooManyResultException

resultType=""里面的参数值是不区分大小写的(在mybatis中类型别名是不区分大小写的)

可以将查询到的单行数据转换为map集合 !

Map<String,Object> getBirdById2Map(int id);

<select id="getBirdById2Map" resultType="map">

select * from mybird where id = #{id};

</select>

查询多行数据,并将这些数据存入到list集合中:

只需要改变一下映射方法的返回值类型即可!List<Map<String,Object>>

或者:

@MapKey("id")

Map<String,Object> getBirdById2Map(int id);//这样也能实现!

#会报错 #{}与?占位符之间的关系是什么? 呈现出的SQL语句将?当做了字符串中的一部分了!

?不会被解析为占位符!

#会自动加单引号的!

$不会自动加单引号的

模糊查询:(是建议使用${}而使用#{}会报错!(还包括批量删除、动态设置表名))

<select id="queryLike" resultType="map">

select * from mybird where namese like '%${namses}%';

</select>

上图是不会报错的! 也是最常用的!

驼峰 与下划线 的命名格式

mybatis的全局配置:

<settings>

自动将_映射为驼峰,emp_name:empName

<setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

resultMap:设置自定义映射关系

  • id:唯一标识,不能重复
  • type:设置映射关系中的实体类类型
  • 子标签:
  • id:设置主键的映射关系
  • result:设置普通字段的映射关系
  • 属性:
  • property:设置映射关系中的属性名,必须是type属性所设置的实体类类型中的属性名
  • column:设置映射关系中的字段名,必须是sql语句查询出的字段名。

分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。

此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可以通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"

一对多:

分步查询一对多:

分步查询的优点能够实现延迟加载!

动态SQL

MyBatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。

MyBatis的一级缓存

一级缓存时SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。

使一级缓存失效的四种情况:

  • 不同的SqlSession对应不同的一级缓存
  • 同一个SqlSession但是查询条件不同
  • 同一个SqlSession两次查询期间执行了任何一次增删改操作
  • 同一个SqlSession两次查询期间手动清空缓存

一级缓存默认开启

MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取。

二级缓存开启的条件:

  • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  • 在映射文件中设置标签<cache/>
  • 二级缓存必须在SqlSession关闭或提交之后有效
  • 查询的数据所转换的实体类类型必须实现序列化接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

MyBatis缓存查询的顺序:

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
  • 如果二级缓存没有命中,再查询一级缓存。
  • 如果一级缓存没有命中,则查询数据库
  • SqlSession关闭之后,一级缓存中的数据会写入二级缓存

MyBatis的二级缓存为什么不包含了一级缓存呢?

MyBatis的逆向工程

正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。

逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

  • Java实体类
  • Mapper接口
  • Mapper映射文件

v

MyBatis的分页和逆向工程以及二级缓存不理解!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值