Mybatis

Spring框架—Mybatis

1.Mybatis是什么

●Mybatis是一个半ORM(对象关系映射)框架,内部封装了JDBC,开发时只需要关注SQL语句本身,不用去关心加载驱动,创建连接,创建Statement等繁琐的过程,程序员直接编写SQL语句即可。

●使用XML或注解来配置和映射原生信息,将POJO映射为数据库中的记录,避免了JDBC代码和手动设置参数。

2.ORM

●ORM(Object Relation Mapping)对象关系映射,一种为了解决关系型数据库与简单java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库映射的元数据,将程序中的对象自动持久化到关系型数据库中。

●Mybatis在查询关联对象(多表连接,内连接外连接)或关联集合对象时,需要手动编写sql来完成,所以称之为半自动ORM

●Hibernate属于全自动ORM映射关系,当查询关联对象或者关联对象集合时,根据对象模型直接获取。

●ORM的优点(也可以作为Mybatis的优点)

​ ■基于SQL语句编程,不会对应用程序或数据库的现有设计造成任何影响,SQL写在xml里,解除了sql与程序代码的耦合。

​ ■提供xml标签,支持编写动态SQL

​ ▼静态SQL:直接写就可以了,编译器可以确定数据库要做什么(个别参数未定义也算静态sql)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WqlCrL0W-1650540924214)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/163.png)]

​ ▼动态SQL:Mybatis的动态SQL可以让我们在xml文件中以标签的形式编写动态sql,完成逻辑判断和动态拼接的功能,提供9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind(原理是根据表达式的值动态拼接sql)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ycNn5zG5-1650540924215)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/164.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yHrSdTYM-1650540924216)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/165.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uWQdcZDY-1650540924217)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/166.png)]

​ ■与JDBC相比,减少了大量的代码量,不需要手动开关连接。

​ ■提供标签映射,支持对象与数据库ORM字段关系映射

3.JDBC的不足以及Mybatis的改进

● 数据库链接创建、释放频繁造成系统资源浪费,从而影响系统性能。

​ ■在mybatis-congif.xml中配置数据库连接池,使用连接池管理数据库链接。

●Sql语句编写在JAVA代码中间不易维护

​ ■将SQL语句配置在mapper.xml文件中,实现了Java和sql的隔离

●向sql语句传参麻烦,因为sql语句的where条件不一定,可能多可能少,占位符要一一对应

​ ■Mybatis自动将java对象映射至sql语句,参数按名字分配

●结果集解析麻烦

​ ■Mybatis自动将sql执行结果映射至java对象。

4.Mybatis原理过程

●读取mybatis配置文件—mybatis.config.xml

●加载mapper映射文件,即SQL映射文件,这个文件中配置了操作数据库的sql语句,(mapper映射文件在mybatis.config.xml中加载,每个映射文件对应数据库的一张表)

●根据配置文件信息创建sqlSessionFactory

●通过sqlSessionFactory创建sqlSession对象(该对象包含执行sql语句的所有方法)

●通过sqlSession.execute()执行数据库操作(mybatis底层定义了一个Executor接口来操作数据库,根据sqlSession传递的参数动态的生成需要执行的sql语句,同时负责查询缓存的维护)

​ ■MappedStatement对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数就是对映射信息的封装,用于存储要映射的SQL语句的id,参数等信息。

​ ■输入参数/输出参数映射:类型可以是Map、List等集合类型,也可以是基本数据类型和POJO数据类型,映射过程类似JDBC对preparedStatement对象设置参数的过程

●调用session.commit();提交事务

●调用session.close();关闭会话

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHOobELx-1650540924219)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/167.png)]

5.Mybatis功能架构

●使用过SSM框架都应该知道,根据url找到相应的Controller方法,方法中封装着service,service封装着dao,dao层里面指定里采用mapper中的哪个方法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TlhFPslJ-1650540924220)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/168.png)]

Mybatis架构分为三层:

●API接口层(DAO):提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一收到调用请求就会调用数据处理层来完成具体的数据处理。这层写java的基础功能,比如是银行卡中钱增加减少,然后service层中封装为转账业务。

●数据处理层(mapper):负责具体的SQL查找,sql解析,sql执行和执行结果映射。

●基础支持层(配置问价负责的):负责最基础的功能支撑。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xQLfzCpw-1650540924220)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/169.png)]

●初始化(加载配置):一是从mybatis-config.xml中加载,再就是从Java中代码的注解进行加载。

●SQL解析:当API层(提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库)接收到请求(出入SQL的IDhe对象),Mybatis会根据SQL的id找到对应的mappedStatement,然后根据传入参数对象对mappedStatement进行解析,解析后得到最终要执行的SQL语句和参数。

●SQL执行:将最终得到的SQL和参数拿到数据库执行,得到结果

●结果映射:将数据库的结果按映射配置转换,并将结果返回。

6.DBMS

●即数据库管理系统,是一种操纵数据库的大型软件。通过DBMS对数据库进行维护,常见的有Mysql,sqlService,oracle

7.预编译

●预编译指数据库驱动在发送SQL语句和参数给DBMS之前对SQL语句进行编译,这样DBMS执行SQL的时候就不需要再重新编译。

●为什么要预编译:

​ ■JDBC使用对象PreparedStatement来抽象预编译语句,使用预编译。预编译阶段可以优化sql的执行,预编译之后的sql多数情况下可以直接执行,DBMS不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一次操作。同时预编译语句对象可以重复利用。把一个sql预编译后产生的PreparedStatement对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的prepareStatement对象(Mybatis默认对所有的sql进行预编译)

​ ■还有一个原因:防止sql注入

8.Mybatis有哪些Executor执行器

●SimpleExecutor(默认):每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

●ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就用,不存在就创建,用完后,不关闭Statement对象,而是放在Map<String,Statement>内,供下一次使用

●BatchExecutor:执行update(select不支持批处理),将所有sql都添加到批处理中(addBatch()),等待同一执行(executeBatch),它缓存了多个statement对象,每个Statement对象都是addBatch()完毕后,等待逐一executeBatch()批处理

●Mybatis配置文件中,在settings可以指定默认的ExecutorType执行器类型。也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型的参数。

9.Mybatis是否支持延迟加载,原理是什么

●延迟加载又称懒加载,是指在进行表的关联查询时,按照设置延迟规则推迟对关联对象的select查询。(例如在进行一对多查询时,只查询出一方,当程序中需要多方数据时,mybatis再发出sql语句进行查询)主要是为了减少数据库的压力。期延迟加载只是对关联对象的延迟有延迟设置。

●Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的是一对一,collection指的是一对多查询(Mybatis文件中,根据配置lazyLoadingEnable = true|false来设置是否启动延迟加载)

●原理是使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null,那么就会单独发送事先保存好的查询关联B对象的SQL,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB(),getName()方法的调用。

10.映射器

●#{}与${}

​ ■#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理

​ ■Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?,调用perparedStatement的set方法来复制。

​ ■#{}可以有效防止SQL注入,而${}不能

​ ■#{}的变量替换是在DBMS中,而${}的变量替换是在DBMS外

11.mapper中如何传参,mapper层与Dao层建立映射

●参数不多的时候建议使用@param注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sj9uCgra-1650540924221)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/170.png)]

​ ■#{}里面的名称对应的是注解Param括号里面的名字(方法是DAO层里的哦)

●当参数比较多的时候适合用Map传参

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FFYPEZGj-1650540924222)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/171.png)]

​ ■#{}里面的对应的是Map里面key的名称

●当参数恰好都是一个类的属性时使用javaBean传参

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OvCevHRi-1650540924223)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/172.png)]

​ ■#{}里面的对应的是User类中的属性名

12.常见操作

●如何获取生成列的主键:新增标签添加keyProperty = “ID”即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5kPe8Fr-1650540924223)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/173.png)]

●当实体类的属性名与表中字段不一致怎么办:

​ ■在查询语句中定义字段的别名,让别名与实体类属性一致

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EfwqVyhN-1650540924224)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/174.png)]

​ ■使用来进行映射

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ooPlNAtB-1650540924225)(http://luxiaolumm.gitee.io/luxiao-lu-mm/pic/175.png)]

13.Mybatis接口绑定

●就是把Dao层接口中的方法与Mapper层中的Sql语句绑定,这样我们在会接调用接口方法就可以了,比原来使用sqlSession提供的方法更加灵活。

●绑定方式:

​ ■通过xml里面写SQL来绑定,xml映射文件里面的namespace必须为接口的全路径名

​ ■通过注解绑定:在接口的方法上加@select,@update等注解(注解里面是sql语句)

●接口调用时的要求

​ ■Dao接口方法名与mapper.xml中的sql的id相同(第一种绑定方式)

​ ■Dao接口输入参数类型和mapper.xml中定义的每个sql的parameterType类型相同

​ ■Dao接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType相同

​ ■Mapper.xml文件的namespace是mapper接口的类路径

●不同的xml映射文件中,如果配置了namespace,那么id可以重复,因为namespace+id是作为Map<String,MappedStatement>的key 使用的,不会重复即可

●接口就是Dao层,其原理就是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成Proxy对象,代理对象proxy会拦截接口方法,转而执行mappedStatement所代表的sql,并将sql接口返回(Dao里的方法不能重载,因为是全限名+方法名的保存查找策略)

14.Mybatis的一级、二级缓存

●一级缓存:基于HashMap本地缓存,其存储作用域为session,当session flush或close后,该session中的所有Cache就清空。默认打开一级缓存,在同一个SQLSession中,执行相同的SQL查询时,第一次会去查数据库,并写在缓存中,第二次直接从缓存中取。HashMap的key为hashcode+statemendId+sql语句,value为查询出来的结果映射成的java对象。

●二级缓存:机制相同也是采用HashMap存储,其作用域为mapper(nameSpace),可以自定义存储源,默认不打开。第一次调用mapper下的sql会去查询用户的信息,查询到的信息存放在mapper对应的二级缓存区,第二次调用相同的sql去查用户信息,会从二级缓存中取。

●缓存更新机制:当某一个作用域(一级缓存/二级缓存)进行了C/U/D操作后,默认该作用域下所有的select中缓存全被clear●

15.Mybatis如何将sql执行结果封装为对象

●对于得到的每一列,采用别名形式,使其与每个属性对应

●然后将这个mapper的resultType改为对应类的全名。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值