学习目标
- 了解框架的概念和优点
- 了解MyBatis框架的概念和优点
- 掌握Mybatis环境搭建
- 掌握Mybatis入门程序编写
- 熟悉MyBatis工作原理
当前市场上的Java EE开发主流框架有Spring、Spring MVC和MyBatis等。
1.1 初识框架
1.1.1框架概述
“框架”(framework)一词最早出现在建筑领域,是指建造房屋前期所构建的建筑骨架。在编程领域,框架就是应用程序的“骨架”,开发人员可以在这个骨架上加入自己的东西,搭建出符合自己需求的应用系统。
软件框架是一种通用的、可复用的软件环境。它提供特定的功能,助力软件应用、产品和解决方案的开发工作。软件框架包含支撑程序、编译器、代码、库、工具集和API,他把这些部件汇集在一起,以支持项目或系统的开发。
软件框架可以形象的比喻成人们在盖楼房时,用梁+柱子+承重墙搭建起来的钢筋混凝土结构的建筑框架,他是整个建筑的骨架。而实现的软件功能,也就像在这个建筑框架中所要实现的不同类型、功能的房子,如健身房、商店、酒店、饭店等。
可想而知,一个好的建筑框架是非常重要的,其不仅能够在资源上节约成本,而且能够在资源有限条件下使建筑的质量达到最优,并且能够提供空间利用率,发挥资源的最大功效。
总体来说,建筑框架的目的就是制定规矩、保障品质、节约成本,使工作人员能够以较低的代价完成高质量的工作,软件框架也是如此。
1.1.2 框架的优势
在早期的Java EE应用开发中,企业开发人员是利用JSP+Servlet进行软件应用和系统开发的,但使用JSP+Servlet技术进行Java EE应用的开发有以下两个弊端。
(1)软件应用和系统的可维护性差
如果全部采用JSP+Servlet技术进行软件开发,因为分层不够清晰,业务逻辑的实现无法单独分离出来,所以后期系统维护特别困难。
(2)代码重用性低
企业希望以最快的速度开发出最稳定、最实用的软件。如果系统不使用框架,每次开发系统都需要重新开发和投入大量的人力、物力,并且重新开发的代码可能具有更多的漏洞。这就增加了系统出错的风险。
针对上述两个弊端,开发人员开发出了许多框架。相比于实用JSP+Servlet技术进行软件开发,使用框架有以下优势。
(1)提高开发效率
如果采用成熟、稳健的框架,那么一些通用的基础工作,如事务处理、安全性、数据流控制等都可以交给框架处理,程序员只需要集中精力完成系统的业务逻辑设计即可,从而降低了开发难度。
(2)提高代码规范性和可维护性
当多人进行协同开发时,代码的规范性和可维护性就变得非常重要。成熟的框架都有严格的代码规范,能保证团队整体的开发风格统一。
(3)提高软件性能
使用框架进行软件开发,可以减少程序中的冗余代码。例如,使用Spring框架开发时,通过Spring的控制反转(Inversion of Control,IoC)特性,可以将对象之间的依赖关系交给Spring控制,从而方便接耦,简化开发;使用MyBatis框架开发时,MyBatis提供了XML标签,支持动态的SQL,开发人员无须在类中编写大量的SQL语句,只需要在配置文件中进行配置即可。
1.1.3 当前主流框架
在JavaEE开发中离不开框架,使用框架可以减少代码冗余,提高程序运行速度,规范编程且便于代码维护。下面介绍几种当前JavaEE开发中常见的框架。
1.Spring框架
Spring是一个开源框架,是为了解决企业应用程序开发复杂这一难题而创建的,其主要优势之一就是分层架构。同时,Spring之所以与Struts,Hibernate等单层框架不同,是因为Spring致力于提供一个以统一的、高效的方式构造整个应用,并且可以将单层框架组合在一起建立一个连贯的体系。Spring提供了更完善的开发环境,可以为POJO(Plain Ordinary Java Object,普通Java对象)提供企业级的服务。
2.Spring MVC框架
Spring MVC是Spring提供的一个基于MVC设计模式的Web开发框架,是Spring家族中应用于Web应用的一个模块,可以将它理解为Servlet。在MVC模式中,Spring MVC作为控制器(Controller)用于实现模型与视图的数据交互,是结构非常清晰的JSP Model2实现,即典型的MVC框架。
Spring MVC框架采用松耦合、可拔插的组件结构,具有出色的可配置性,与其他的MVC框架相比,Spring MVC具有更强的扩展性和灵活性。此外,Spring MVC本身就是Spring家族的一部分,可以与Spring框架无缝集成,因此,Spring MVC在互联网开发中应用的越来越广泛。
3.MyBatis框架
MyBatis原本是Apache的一个开源项目iBatis,2010年这个项目有Apache Software Foundation迁移到了Google Code,并且改名为MyBatis,2013年11月MyBatis又被迁移到了GitHub。MyBatis是一个优秀的持久层框架,它可以在实体类和SQL语句之间建立映射关系,是一种半自动化的ORM(Object Relational Mapping,对象关系映射)实现。MyBatis封装性要低于Hibernate,但是他性能优越、简单易学,在互联网应用的开发中被广泛使用。
4.Spring Boot框架
Spring Boot框架是Pivotal团队基于Spring开发的全新框架,其设计初衷是为了简化Spring的配置,使用户能够构建独立运行的程序,提高开发效率。SpringBoot框架本身并不提供Spring框架的核心特性以及扩展功能,他只是用于快速、敏捷地开发新一代基于Spring框架的应用,同时它还集成了大量的第三方类库(如Jackson、JDBC、Redis等),使用户只需要少量配置就能完成相应的功能。
5.Spring Cloud框架
Spring Cloud是一系列框架的有序集合,为开发人员构建微服务框架提供了完整的解决方案,它利用Spring Boot的开发便利性巧妙的简化了分布式系统的开发。例如,配置管理、服务发现、控制总线等操作,都可以使用Spring Boot 做到一键启动和部署。可以说,SpringCloud就是将SpringBoot框架进行了再封装,屏蔽了复杂的配置和实现原理,具有简单易懂、易部署和易维护的特点。
1.2 MyBatis介绍
Java程序依靠Java数据连接(Java Database Connectivity,JDBC)实现对数据库的操作,但是在大型企业项目中由于程序和数据库交互次数较多且读写数据量较大,仅仅使用传统JDBC操作数据库无法满足性能要求。同时JDBC的使用也会带来代码冗余、复杂性低的问题,因此,企业级开发中一般使用MyBatis等ORM框架操作数据库。
1.2.1 传统JDBC的劣势
JDBC是Java程序实现数据访问的基础,它提供了一套数据库操作API。JDBC实现数据库操作的步骤包括加载驱动、获取连接、获取执行者对象、发送SQL语句等,操作比较繁琐,并且传统的JDBC编程存在一定的局限性。JDBC的劣势主要有以下几个方面:
- 频繁的创建、释放数据库连接会造成资源的浪费,从而影响系统的性能。
- 代码中的SQL语句硬编码,会造成代码不易于维护。在实际应用的开发中,SQL变化的可能性比较大。在传统的JDBC编程中,SQL的变动需要更改Java代码,违反了开闭原则。
- 使用PreparedStatement向占位符传参数存在硬编码,因为SQL语句的Where条件不确定,如果有修改需要SQL的需求,必须要修改代码,这样会导致系统难以维护。
- JDBC对结果集解析存在硬编码(查询列名),SQL变化导致解析代码变化,使得系统不易于维护。
1.2.2 MyBatis概述
MyBatis是一个支持普通SQL查询、存储及高级映射的持久化框架,它几乎消除了JDBC的冗余代码,无须手动设置参数和对结果集进行检索,使用简单的XML或注解进行配置和原始映射,将接口和Java的POJO映射成数据库中的记录,使Java开发人员可以使用面向对象的编程思想来操作数据库。
MyBatis框架是一个ORM框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中的数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的数据表中。ORM框架的工作原理如图1-1所示。
从图1-1可以看出,使用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象(Persistent Object,PO),ORM框架会通过映射关系将这些面向对象的操作转换成底层SQL操作。
MyBytis作为一个优秀的持久层框架,它对JDBC操作数据库的过程进行了封装,使开发者只需要关注SQL本身,而不需要花费精力去处理注册驱动、创建Connection对象、创建Statement对象、手动设置参数、结果集检索等JDBC繁杂的过程代码。
针对1.2.1节提到的JDBC编程的劣势,MyBatis提供了以下解决方案,具体如下。
问题一:频繁地创建、释放数据库连接会造成系统资源浪费,从而影响系统性能。
解决方案:在SqlMapConfig.xml中配置数据连接池,使用数据库连接池管理数据库连接。
问题二:代码中的SQL语句硬编码,会造成代码不易于维护。在实际的应用开发中,SQL变化的可能性比较大。在传统的JDBC编程中,SQL变动需要更改Java代码,违反了开闭原则。
解决方案:MyBatis自动将SQL语句配置在MyBatis的映射文件中,实现了与Java代码的分离。
问题三:使用PreparedStatement向占位符传参数存在硬编码,因为SQL语句的where条件不确定,如果有修改SQL的需求,必须要修改代码,这样会导致系统难以维护。
解决方案:MyBatis将Java对象映射到SQL语句,通过Statement中的parameterType定义输入参数的类型。
问题四:JDBC对结果集解析存在硬编码(查询列名),SQL变化导致解析代码变化,使得系统不易于维护。
解决方案:MyBatis自动将SQL执行结果映射至Java对象,通过Statement中的resultType定义输出结果的类型。
1.3 MyBatis环境搭建
使用MyBatis框架进行数据库开发前,需要先搭建MyBatis环境,MyBatis环境搭建的基本步骤包括创建工程、引入相关依赖、创建数据库、创建数据库连接信息配置文件、创建MyBatis的核心配置文件。本书采用MyBatis3.5.2版本搭建MyBatis环境,具体步骤如下:
1.创建工程
启动IntelliJ IDEA开发工具,选择工具栏中的“File”——“New”——“Project”选项,弹出“New Project”对话框。如下图所示:
在“New Project”对话框中,选择左侧菜单中的“Maven”选项,然后单击“Next”按钮,弹出项目命名对话框。
在“Name“文本框中为Maven项目命名,在”Location“文本框中选择项目存放的路径。单击”Artifact Coordinates“选项左侧的下拉按钮可以填写”GroupId“”ArtifactId“和”version“其中”GroupId“通常设置为公司倒置的网络域名,如”com.itheima“;”ArtifactId“通常设置为项目名;”Version“为IDEA默认版本即可。填写完之后,单击”finish“按钮完成项目创建。
2.引入相关依赖
在以往Java项目的开发中,需要在项目中引入许多JAR包以便于调用JAR包中封装好的常用类集。但由于JAR包占用的内存空间较大,给项目的打包和发布带来了极大的不便,基于以上的原因,Apache公司开发了项目管理工具Maven。Maven使用Maven管理不需要再引入一个个的JAR包,只需要将JAR包的依赖引入项目的pom.xml文件中就可以调用JAR包中的类,极大提高了开发人员的编程效率。由于IDEA中集成了Maven,所以本书直接使用IDEA中默认的Maven进行项目构建。
由于本项目要连接数据库并对程序进行测试,所以需要在项目的pom.xml文件中导入MySQL驱动包、JUnit测试包、MyBatis的核心包等相关依赖,具体代码如下:
在上述代码中,第2~6行的代码是MyBatis的核心包;第7~11行代码是MySQL的驱动包;第12~17行的代码是Junit测试包;由于IDEA不会自动编译src/main/java目录下的XML下等资源文件编译进classes文件夹。
由于本书使用的是IDEA默认集成的Maven,所以在第一次引入依赖时,需要在联网的状态下进行,且引入依赖需要较长的时间。
3.创建数据库
在MySQL中创建一个名称为mybatis的数据库,具体的SQL语句如下:
create database mybatis;
4. 创建数据库连接信息配置文件
在项目的src/main/resources目录下创建数据库连接的配置文件,这里将其命名为db.properties,在该文件中配置数据库连接的参数。db.properties文件的具体内容如下1-1所示:
5.创建MyBatis的核心配置文件
在项目的src/main/resources目录下创建MyBatis的核心配置文件,该文件主要用于项目的环境配置,如数据库连接相关配置等。核心配置文件可以随意命名,但通常将其命名为mybatis-config.xml。如无特殊说明,本书中的MyBatis核心配置文件均命名为mybatis-config.xml。mybatis-config.xml的具体实现如文件1-2所示。
在文件1-2中,第2~4行代码是核心配置文件的约束信心;第8行代码用于加载数据库连接信息配置文件db.properties;第13~18行代码是数据库连接参数的配置。
至此,Mybatis的开发环境就搭建完成了。
1.4 MyBatis入门程序
1.3节完成了MyBatis的环境搭建,下面将在Mybatis环境下实现一个入门程序来演示MyBatis框架的使用(如果不做特别说明,后续编码将在1.3节搭建的MyBatis环境下进行),该程序要求实现根据id查询用户信息的操作,具体的实现步骤如下:
1.数据准备
在mybatis数据库中创建users表,并在users表中插入两条数据,具体SQL语句如下:
2. 创建POJO实体
在项目的src/main/java目录下创建com.itheima.pojo包,在com.itheima.pojo包下创建User类,该类用于封装User对象的属性,如文件1-3所示。
docker start JY_mysql 启动mysql数据库
3.创建映射文件UserMapper.xml
在项目的src/main/resources目录下创建一个Mapper文件夹,在mapper文件夹下创建映射文件UserMapper.xml,该文件主要用于配置SQL语句和Java对象之间的映射,使SQL语句和Java对象之间的映射,使SQL语句查询出来的数据能够被封装成Java对象。一个项目中可以有多个映射文件,每个实体类都可以有其对应的映射文件。映射文件通常使用POJO实体类名称+Mapper命名。例如,User实体类的映射文件名称就是UserMapper.xml。UserMapper.xml的实现具体文件如下所示
文件1-4 UserMapper.xml
在文件1-4中,第2—4行的代码是映射文件的约束信息;第9行代码是根元素元素,元素中可包含用于增删改查操作的、、、等元素。元素中的namespace属性用于标识映射文件,namespace属性的值通常设置为对应实体类的全限定类名;第13-第16行代码为查询语句模块,用于SQL查询语句模板的编写。需要注意的是,元素中的id属性用于唯一标识该SQL语句块,Java代码通过id属性的值找到对应的SQL语句块。4.修改mybatis-config.xml配置文件在mybatis-config.xml映射文件的第20行代码后添加UserMapper.xml映射文件路径的配置,用于将UserMapper映射文件加载到程序中。具体代码如下:<!-- mapping文件路径配置 --> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers>PS:如果一个项目有多个映射文件,则需要在mybatis-config.xml核心配置文件中的元素下配置多个元素指定映射文件的路径。
5.编写测试类
在项目的src/test/java目录下创建Test包,在Test包下创建UserTest类,该类主要用于程序测试,如文件1-5所示。
在文件1-5中,第19行代码用于读取mybatis-config.xml文件内容到reader对象当中;第23-26行代码用于创建SqlSessionFactory类的实例,并通过SqlSessionFactory类的实例创建SqlSession实例;第28行代码调用selectOne( )方法,查询id为1的用户信息,并将查询结果返回给User对象。返回结果如下所示:
1.5 MyBatis工作原理
在学习了MyBatis环境搭建和入门程序的编写之后,可结合1.4节MyBatis入门程序,对MyBatis操作数据库的流程进行分析,如图1-6所示。
在上图中,MyBatis操作数据库的流程分为8个步骤,具体介绍如下:(1)MyBatis读取核心配置文件mybatis-config.xml:mybatis-config.xml核心配置文件主要配置了MyBatis的运行环境等信息。(2)加载映射文件Mapper.xm:Mapper.xml文件即SQL映射文件,该文件配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。(3)构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory,用于创建SqlSession。(4)创建SqlSession对象:由会话工厂SqlSessionFactory创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。(5)动态生成SQL语句:MyBatis底层定义了一个Executor接口用于操作数据库,它会根据SqlSession传递的参数动态的生成需要执行的SQL语句,同时负责查询缓存地维护。(6)MappedStatement对象将传入的Java对象映射到SQL语句中:SqlSession内部通过执行器Executor操作数据库,增删改语句通过Executor接口的update()方法执行,查询语句通过query()方法执行。这两个执行方法中包含一个MappedStatement类型的参数,该参数是对映射信息的封装,存储了要映射的SQL语句的id、参数等。Mapper.xml文件中一个SQL语句对应一个MappedStatement对象,SQL语句的id即是MappedStatement的id。(7)输入参数映射:在执行Executor类的update()方法和query()方法时,MappedStatement对象会对用户执行SQL语句时输入的参数进行定义,Executor执行器会在执行SQL语句之前,通过MappedStatement对象将输入的参数映射到SQL语句中。Executor执行器对输入参数的映射过程类似于JDBC编程对PreparedStatement对象设置参数的过程。(8)输出结果映射:excutor()方法在数据库中执行完SQL语句后,MappedStatement对象会对输出的结果进行定义,Executor执行器会在执行SQL语句之后,通过MappedStatement对象将输出结果映射至Java对象中。Executor执行器将输出结果映射到Java对象的过程类似于JDBC编程对结果的解析处理过程。
1.6 本章小节
本章主要针对MyBatis框架进行了讲解。首先对框架的概念、优点和当前一些主流的JavaEE框架进行了讲解,然后对传统JDBC的劣势进行了分析,由此引出了MyBatis框架,并对MyBatis框架的环境搭建、入门程序以及工作原理进行了详细地讲解。通过本章的学习,读者可以了解MyBatis框架及其作用,熟悉MyBatis的工作原理,并能够独立完成MyBatis框架环境的搭建以及入门程序的编写。
【思考题】1.请简述什么是MyBatis?
答:MyBatis是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,使用简单的XML或注解进行配置和原始映射,将接口和Java的POJO映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
2.请简要介绍MyBatis的工作原理。
答:(1)读取MyBatis配置文件mybatis-config.xml。(2)由MyBatis配置文件加载映射文件Mapper.xml。(3)通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。(4)由会话工厂创建SqlSession对象。(5)MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态的生成需要执行的SQL语句。(6)在Executor接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装。(7)在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义封装。(8)在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义封装。