MVC(SpringMVC)与ORM(MyBatis)

MVC

MVC 模型,它包含了 Model(模型),View(视图)和 Controller(控制器)。是针对表现层的设计模型,MVC是一种设计模式
MVC的原理图: 在这里插入图片描述M-Model 模型(完成业务逻辑:有javaBean构成,service+dao+entity)
V-View 视图(做界面的展示 jsp,html……)
C-Controller 控制器(接收请求—>调用模型—>根据结果派发页面)

MVC 模型的优势
第一:清晰的职责划分。
第二:每个组件作用独立。有利于代码的重用。
第三:由于可重用性强,所以后期维护起来方便。
第四:任何项目都适用

MVC 模型的弊端
任何事情都是有其两面性,MVC 模型也并不是全方位优秀的设计模型。它的弊端体现在:
第一:展示数据响应速度慢
第二:对开发人员的要求高,需要合理的设计和严谨的架构。
第三:异步交互并不方便

基于异步请求的 MVVM模式
在这里插入图片描述它全称是 Model View VielModel。是针对 mvc 模型的再次改良,不过只改良了展示数据的部分。(Controller 的再次优化交给了框架,Model 部分已经无需再优化)
在上一小节,我们提出了异步交互不变的弊端,这主要是在异步展示数据时,javascript 的逻辑处理和数据显示交织在了一起,当我们想进行调整时,需要阅读大量的代码,给后期维护造成了影响。而 MVVM 它把 javascript的逻辑处理和数据展示分开,可以让使用者在后期维护时,针对不同的需求进行调整。例如:如果是逻辑部分需要处理,则修改逻辑部分代码。如果是数据显示位置需要调整,则修改展示部分的代码,使前端展示更加灵活,也更加合理。

SpringMVC

springMVC流程:
(1):⽤户请求发送给DispatcherServlet,DispatcherServlet调⽤HandlerMapping处理器映射器;
(2):HandlerMapping根据xml或注解找到对应的处理器,⽣成处理器对象返回DispatcherServlet;
(3):DispatcherServlet会调⽤相应的HandlerAdapter;
(4):HandlerAdapter经过适配调⽤具体的处理器去处理请求,⽣成ModelAndView返回给DispatcherServlet
(5):DispatcherServlet将ModelAndView传给ViewReslover解析⽣成View返回DispatcherServlet;
(6):DispatcherServlet根据View进⾏渲染视图;
在这里插入图片描述

->DispatcherServlet->HandlerMapping->Handler ->DispatcherServlet->HandlerAdapter处理handler->ModelAndView ->DispatcherServlet->ModelAndView->ViewReslover->View ->DispatcherServlet->返回给客户

组件:
1、前端控制器DispatcherServlet(不需要工程师开发),由框架提供
作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2、处理器映射器HandlerMapping(不需要工程师开发),由框架提供
作用:根据请求的url查找Handler
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
4、处理器Handler(需要工程师开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler。
5、视图解析器View resolver(不需要工程师开发),由框架提供
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。
6、视图View(需要工程师开发jsp…)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

核心架构的具体流程步骤如下:
1、首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为
HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个
HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
5、ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。下边两个组件通常情况下需要开发:
Handler:处理器,即后端控制器用controller表示。
View:视图,即展示给用户的界面,视图中通常需要标签语言展示模型数据

SpringMVC怎么样设定重定向和转发的?
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
SpringMVC常用的注解有哪些?
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应用户。

ORM

通过 Java 语言连接并操作数据库的技术或方式已经有很多了,例如:JDBC,
Hibernate,MyBatis,TopLink 等等。其中 JDBC 是 Java 原生的 API,支持连接并操作各种关系型数据库。JDBC 作为 Java 原生 API,有优点,也有缺点,这里主要说一下缺点:

  1. 编码繁琐,效率低
  2. 数据库连接的创建和释放比较重复,也造成了系统资源的浪费
  3. 大量硬编码,缺乏灵活性,不利于后期维护
  4. 参数的赋值和数据的封装全是手动进行

正是因为 JDBC 存在着各种问题,所以才导致很多持久层框架应运而生,例如:Hibernate
和 MyBatis,这两个都是目前比较流行的持久层框架,都对 JDBC 进行了更高级的封装和优化。

扫描二维码关注公众号,回复: 11753113 查看本文章

第一类:着重对 JDBC 进行 API 层的抽取和封装,以及功能的增强,典型代表是 Apache 的DbUtils。程序员在使用 DbUtils 时仍然需要编写 sql 语句并手动进行数据封装,但是 API 的使用比 JDBC方便了很多。

第二类:借鉴面向对象的思想,让程序员以操作对象的方式操作数据库,无需编写 sql 语句,典型代表是 ORM。ORM(Object Relational Mapping)吸收了面向对象的思想,把对 sql 的操作转换为对象的操作,从而让程序员使用起来更加方便和易于接受。这种转换是通过对象和表之间的元数据映射实现的,这是实现 ORM 的关键,如下图所示:
在这里插入图片描述由于类和表之间以及属性和字段之间建立起了映射关系,所以,通过 sql 对表的操作就
可以转换为对象的操作,程序员从此无需编写 sql 语句,由框架根据映射关系自动生成,这
就是 ORM 思想。
目前比较流行的 Hibernate 和 MyBatis 都采用了 ORM 思想,一般我们把 Hibernate 称之
为全自动的 ORM 框架,把 MyBatis 称之为半自动的 ORM 框架。

什么是MyBatis
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
(2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
MyBatis的优点和缺点
优点:
(1)基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
(2)与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
(4)能够与Spring很好的集成;
(5)提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

MyBatis 的 ORM 实现原理在这里插入图片描述

在这里插入图片描述
在这里插入图片描述MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情:

  • 封装JDBC操作
  • 利用反射打通Java类与SQL语句之间的相互转换

MyBatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便,所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。

流程

1 加载配置:配置来源于两个地方,一是配置文件,一是Java代码的注解,将SQL的配置信息加载成为一个个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
2 SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。
3 SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
4 结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。

Mybatis原理

  • sqlsessionFactoryBuilder⽣成sqlsessionFactory(单例)
  • ⼯⼚模式⽣成sqlsession执⾏sql以及控制事务
  • Mybatis通过动态代理使Mapper(sql映射器)接⼝能运⾏起来即为接⼝⽣成代理对象将sql查询到结果映射成pojo

sqlSessionFactory构建过程

  • 解析并读取配置中的xml创建Configuration对象 (单例)
  • 使⽤Configruation类去创建sqlSessionFactory(builder模式)

#{}和${}的区别是什么?

#{}是预编译处理,KaTeX parse error: Expected 'EOF', got '#' at position 21: …串替换。 Mybatis在处理#̲{}时,会将sql中的#{}替…{}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。

当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};
第2种: 通过来映射字段名和实体类属性名的一一对应的关系。

Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用标签,逐一定义数据库列名和对象属性名之间的映射关系。
第二种是使用sql列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

MyBatis实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
Mybatis的一级、二级缓存:

默认情况下⼀级缓存是开启的,⽽且是不能关闭的。

  • ⼀级缓存是指 SqlSession 级别的缓存 原理:使⽤的数据结构是⼀个 map,如果两次中间出现commit 操作 (修改、添加、删除),本 sqlsession 中的⼀级缓存区域全部清空
  • ⼆级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存; 原理: 是通过 CacheExecutor实现的。CacheExecutor其实是 Executor 的代理对象

1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Sessionflush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。

猜你喜欢

转载自blog.csdn.net/qq_44961149/article/details/108635415