1.2 MyBatis框架简介
1.2.1 数据持久化概念
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称,如文件的存储、数据的读取等。数据模型可以是任何数据结构或对象模型,而存储模型可以是关系模型、XML、二进制流等。
那么以前是否接触过数据持久化?是否做过数据持久化的操作呢?答案是肯定的。在数据库的课程学习中就编写过应用程序操作的数据表,并对数据表进行“增删改查”的操作,即数据持久化的操作。
那么MyBatis和数据持久化有什么关系呢?请带着这个问题继续学习下面的内容。
1.2.2 MyBatis框架
MyBatis框架是一个开源的数据持久层框架。它内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,消除了所有的JDBC代码和参数的手工设置及结果集的检索。MyBatis框架作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在文件中,以实现SQL的灵活配置。这样做的好处是将SQL与程序代码进行分离,可以在不修改程序代码的情况下,直接在配置文件中修改SQL。
MyBatis网址为https://mybatis.org/mybatis-3/zh/index.html
Github网址为https://github.com/mybatis
1.2.3 ORM框架
MyBatis框架也称ORM(Object Relational Mapping,对象关系映射)框架。所谓的ORM框架就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术。它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。ORM框架是一种数据持久化技术,即在对象模型和关系型数据库之间建立起对应关系,并且提供一种机制,可通过JavaBean对象操作数据库表中的数据,如图1.4所示。
图1.4 ORM映射关系
在实际开发中,程序员使用面向对象的技术操作数据,而存储数据时,使用的却是关系型数据库,这样就造成了很多不便。ORM可以在对象模型和关系型数据库的表之间建立一座桥梁,程序员使用API直接操作JavaBean对象就可以实现数据的存储、查询、更改和删除等操作。MyBatis框架通过简单的XML或注解进行配置和原始映射,将实体类和SQL语句之间建立起映射关系,是一种半自动化的ORM实现。
MyBatis框架是ORM解决方案。基于ORM,MyBatis框架在对象模型和关系型数据库的表之间建立了一座桥梁,并通过MyBatis框架建立SQL关系映射,以实现数据存储、查询、更改和删除等操作。
1.2.4 主流的ORM框架
当前ORM框架产品有很多,常见的框架有Hibernate和MyBatis,其主要区别如下。
(1)Hibernate框架是一个全表映射的框架。通常开发者只要定义好持久化对象到数据库表的映射关系,就可以通过Hibernate框架提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句的编写,Hibernate框架会根据编制的存储逻辑,自动生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis框架。然而Hibernate框架自身也存在一些缺点,如多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
(2)MyBatis框架是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate框架全表映射而言的,MyBatis框架需要手动匹配提供POJO、SQL和映射关系,而Hibernate框架只需提供POJO和映射关系即可。与Hibernate框架相比,虽然使用MyBatis框架手动编写SQL要比使用Hibernate框架的工作量大,但MyBatis框架可以配置动态SQL并优化SQL、通过配置决定SQL的映射规则,以及支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis框架更加合适。
MyBatis框架可应用于需求多变的互联网项目,如电商项目;Hibernate框架可应用于需求明确、业务固定的项目,如OA项目、ERP项目等。
1.2.5 MyBatis框架的环境搭建
关于Java EE企业级应用的常规开发软件安装请参考附录A。在MyEclipse中创建一个名为“Ch01_01”的Java项目后,要使用MyBatis框架,应做好以下准备工作,如图1.5所示。
图1.5 MyBatis框架环境准备的步骤
1.下载jar文件
MyBatis的官方网站为http://mybatis.org,可以下载最新Release版本的MyBatis,其他Release版本的MyBatis的jar包都可从官方网站下载得到。
目前MyBatis官网在国内访问受限,若能访问到官网可将所有下载链接都引导到github上(https://github.com/ mybatis/mybatis-3/releases),推荐下载mybatis-3.5.1.zip和mybatis-3-mybatis-3.5.1.zip(通过相应版本的“Source Code(zip)”链接下载)。如果开发环境版本较低可以选择mybatis-3.2.X.zip的版本。
(1)mybatis-3.5.1.zip(MyBatis的jar包)
mybatis-3.5.1.zip解压后的目录结构如图1.6所示。注意查看根目录(mybatis-3.5.1)和lib目录。在根目录下存放的mybatis-3.5.1.jar为MyBatis的源文件,mybatis-3.5.1.pdf为MyBatis的官方使用手册。lib目录下存放着编译依赖包,如图1.7所示。这些依赖包中部分文件的说明如表1-1所示。
图1.6 目录结构
图1.7 MyBatis编译依赖包
表1-1 依赖包中部分文件的说明
(2)mybatis-3-mybatis-3.5.1.zip(MyBatis源码包)
mybatis-3-mybatis-3.5.1.zip是MyBatis的源码包,里面包含MyBatis的所有源代码,解压后的目录结构如图1.8所示。
图1.8 目录结构
2.部署jar文件
具体的操作步骤如下。
(1)将下载后的mybatis-3.5.1.jar、MySQL-connector-java-5.1.0-bin.jar(MySQL数据库驱动jar包)及log4j-1.2.17.jar(负责日志输出的jar包)复制到工程WEB-INF的lib目录中。
(2)通过MyEclipse导入上述的包。在MyEclipse的工程上右击,选择“Build Path”→“Configure Build Path”选项,如图1.9所示。
图1.9 通过MyEclipse选择“Configure Build Path”选项
在弹出的窗口中单击“Add JARs”按钮,如图1.10所示。
在弹出的“JAR Selection”窗口中选择lib刚复制的jar文件,如图1.11所示。
单击“OK”按钮,这时就在工程中加入了所选的jar文件,如图1.12所示。
图1.10 单击“Add JARs”按钮
图1.11 选择刚复制的jar文件
图1.12 导入支持的jar文件
为了更方便地学习MyBatis,可以在MyEclipse环境中设置当前工程中mybatis-3.5.1.jar的源码。右击选择“mybatis-3.5.1.jar”选项,弹出的快捷菜单如图1.13所示。
图1.13 选择“mybatis-3.5.1.jar”选项弹出的快捷菜单
选择“Properties”选项,进入属性界面,并选择“Java Source Attachment”选项,如图1.14所示。
单击“External Folder”按钮,找到源码所在的目录,即mybatis-3.5.1,如图1.15所示,选中目录,单击“确定”按钮即可。需要注意的是,若源码为jar文件,则单击“External File”按钮,找到源码所在的目录,选中并添加文件即可,此处不再赘述。
图1.14 查看mybatis-3.5.1.jar的属性
图1.15 定位MyBatis源码所在的目录
3.编写MyBatis框架的核心配置文件
MyBatis框架的核心配置文件主要用于配置数据库连接和MyBatis运行时所需的各种特性,包含设置和影响MyBatis行为的属性。
为了方便管理以后各框架集成所需的配置文件,故需在项目工程中新建Source Folder类型的resources目录,并在文件夹中创建database.properties文件存储数据库连接配置信息,内容如下。
MyBatis的示例和上机练习均使用百货中心供应链系统,相关内容请参考本书附录A,该系统使用的数据库是MySQL,在root用户下导入SQL脚本(dsscm.sql)后,数据库为dsscm,其表包括用户表、角色表、供应商表、商品表、采购、销售订单表等。在后续内容中将有百货中心供应链系统的功能介绍。没有特别说明,MyBatis的示例和上机练习都在测试类中运行,运行结果在控制台输出。
由于MyBatis默认使用log4j输出日志信息,所以要查看控制台的输出SQL语句,就需要在classpath路径下配置其日志文件。在项目的resources目录下创建log4j.properties文件,编辑后的内容如下所示。
在日志配置中,包含了全局的日志配置、MyBatis的日志配置和控制台输出,其中MyBatis的日志配置用于将cn.dsscm包中所有类的日志记录级别设置为DEBUG。
由于log4j文件中的具体内容已经超出了本书范围,所以这里不进行讲解,读者可自行查找资料学习。上述配置文件代码也不需要全部手写,在MyBatis使用手册的logging小节中,可以找到如图1.16所示的配置信息,只要将其复制到项目的log4j配置文件中,并对MyBatis的日志配置信息进行简单修改即可使用。
图1.16 MyBatis使用手册中的logging配置
在resources目录中添加MyBatis框架的核心配置文件,默认文件名为“configuration.xml”。需要注意,为了方便在框架集成时更好地区分各个配置文件,一般会将此文件命名为“mybatis-config.xml”。该文件需要配置数据库连接信息和MyBatis的参数,见示例1。
【示例1】 MyBatis框架的核心配置文件mybatis-configuration.xml
在示例1中,第2~3行是MyBatis配置文件的约束信息,下面<configuration>元素中的内容就是开发人员需要编写的配置信息。这里按照<configuration>子元素的功能不同,将配置分为两个步骤:第1步配置环境;第2步配置mapper的位置。关于上述代码中各个元素的详细配置信息将在后续章节进行讲解,此案例中只要按照上述代码配置即可。mybatis-config.xml文件中几个常用元素的作用如下。
(1)configuration:表示配置文件的根元素节点。
(2)properties:表示通过resource属性从外部指定properties属性文件(database.properties)。该属性文件描述数据库连接的相关配置(数据库驱动、连接数据库的url、数据库用户名、数据库密码),位置也是在/resources目录下。
(3)settings:表示设置MyBatis运行中的一些行为,如设置MyBatis的log日志实现为Log4j,即使用log4j实现日志功能。
(4)environments:表示配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上。该元素节点下可以配置多个environment子元素节点,但是必须指定其中一个为默认运行环境(通过default指定)。
(5)environment:表示配置MyBatis的一套运行环境,需指定运行环境id、事务管理、数据源配置等相关信息。
(6)mappers:作用是告诉MyBatis去哪里找到SQL映射文件(该文件内容是开发者定义的映射SQL语句),整个项目中可以有1个或多个SQL映射文件。
(7)mapper:表示mappers的子元素节点,具体指定SQL映射文件的路径,其中resource属性的值表述了SQL映射文件的路径(类资源路径)。
必须注意的是,mybatis-config.xml文件的元素节点是有一定顺序的,节点位置若不按顺序排位,那么XML文件就会报错。配置文件并不需要完全手动编写,在MyBatis使用手册中,已经给出了配置模板(包含约束信息),使用时只需要复制过来,依照自己的项目需求修改即可。
完成MyBatis的配置文件mybatis-config.xml后,就要创建持久化类和SQL映射文件了。
4.创建持久化类(POJO)和SQL映射文件
持久化类是指其实例状态需要被MyBatis持久化到数据库中的类。在应用的设计中,持久化类通常对应需求中的业务实体。MyBatis一般采用POJO编程模型来实现持久化类,与POJO类配合完成持久化工作是MyBatis最常见的工作模式。
POJO(Plain Ordinary Java Object)类就是普通的Java对象。它可以简单地理解为符合JavaBean规范的实体类,不需要继承和实现任何特殊的Java基类或接口。JavaBean对象的状态保存在属性中,访问属性必须通过对应的getter方法和setter方法。
下面先以用户表(tb_user)为例,定义用户POJO类,User.java的代码见示例2。
【示例2】 User.java
在MyBatis中并不需要POJO类名与数据库表名一致,因为MyBatis是POJO与SQL语句之间的映射机制,一般情况下,保证POJO对象的属性与数据库表的字段名一致即可,本示例中的age字段是根据birthday字段计算得出的。建议在每个实体类中都为其提供无参与带参构造方法、toString()方法,以方便后续的测试与使用。
继续进行SQL映射文件的创建,完成与POJO(实体类)的映射,创建包“cn.dsscm.dao”并在里面配置映射文件,该文件也是一个XML文件,命名为UserMapper.xml,见示例3。
【示例3】 UserMapper.xml
经验:SQL映射文件都会对应于相应的POJO,所以一般采用POJO的名称+mapper的规则来进行命名。当然该mapper文件属于DAO层的操作,应该放置在DAO包下,并根据业务功能进行分包放置,如cn.dsscm.dao.UserMapper.xml。
示例3中UserMapper.xml定义了SQL语句,其中各元素的含义如下。
(1)mapper:表示映射文件的根元素节点,只有一个属性namespace。
(2)namespace:表示用于区分不同的mapper,全局唯一。
(3)select:表示查询语句,是MyBatis最常用的元素之一,常用属性如下。
①id属性:表示该命名空间中的唯一标识符。
②resultType属性:表示SQL语句返回值类型,此处通过SQL语句返回的是int数据类型。
说明:在MyBatis的映射文件中,包含了一些约束信息,初学者如果自己动手去编写,不但浪费时间还容易出错。其实,在MyBatis使用手册中就可以找到这些约束信息,具体的获取方法如下。
打开MyBatis的使用手册mybatis-3.5.1.pdf,或者访问官网,在Getting started(入门指南)的2.1.5节Exploring Mapped SQL Statements中,即可找到映射文件的约束信息,如图1.17所示。
图1.17 映射文件的约束信息
可以看出,方框处标注的就是MyBatis映射文件的约束信息。初学者只需将信息复制到项目创建的XML文件中即可。
5.创建测试类
在工程中加入JUnit4,创建包“cn.dsscm.test”并在其中新建测试类(UserMapperTest.java)进行功能测试,然后在后台打印出用户表的记录数,具体的实现步骤如下。
(1)读取全局配置文件:mybatis-config.xml,代码为:
(2)创建SqlSessionFactory对象,此对象可以完成对配置文件的读取,代码为:
(3)创建SqlSession对象,此对象的作用是调用mapper文件进行数据操作,需要注意的是,必须先把mapper文件引入到mybatis-config.xml中才能起效,代码为:
(4)关闭SqlSession对象,代码为:
完整的测试类文件见示例4。
【示例4】 UserMapperTest.java
运行UserMapperTest类的test1()方法,控制台显示为:
本书所有的项目案例及上机练习,不再要求使用System.out.print进行后台日志的输出,一律使用log4j来实现日志的输出,需要在resources目录下加入log4j.properties,并且在MyBatis框架的核心配置文件(mybatis-config.xml)中设置MyBatis的Log实现为log4j。由于控制台输出内容太多,只在本书中显示需要的内容。
至此,我们对MyBatis框架有了一定的了解,并学习了如何搭建MyBatis环境,接下来就根据示例来对比JDBC,介绍MyBatis框架的优、缺点。
1.2.6 MyBatis框架的优、缺点及其适用场合
回顾DAO层代码,以查询用户表记录数为例,直接使用JDBC和MyBatis进行查询的两种实现方式,如图1.18所示。
用JDBC查询返回的是ResultSet对象,ResultSet对象不能直接使用,还需要转换成其他封装类型,通过JDBC查询并不能直接得到具体的业务对象。这样,在整个查询的过程中就需要做很多重复性的转换工作,而使用MyBatis可将这几行代码分解包装(见图1.18)。
第1、2行:表示对数据库连接的管理,包括事务管理。
第3~5行:表示MyBatis通过配置文件管理SQL,以及输入参数的映射。
第6~9行:表示MyBatis获取返回结果到Java对象的映射,也是通过配置文件进行管理的。
图1.18 MyBatis与JDBC的直观对比
1.MyBatis框架的优点
MyBatis框架与JDBC相比,可减少50%以上的代码量。
(1)MyBatis框架是最简单的持久化框架之一,小巧且简单易学。
(2)MyBatis框架相当灵活,不会对应用程序或数据库的现有设计强加任何影响。将SQL写在XML里,可从程序代码中彻底分离降低耦合度,便于统一管理和优化并可重用。
(3)提供XML标签,支持编写动态的SQL语句。
(4)提供映射标签,支持对象与数据库的ORM字段关系映射。
2.MyBatis框架的缺点
(1)编写工作量较大,对开发人员编写SQL语句的能力有一定要求。
(2)依赖于数据库,导致数据库移植性差,不能随意更换数据库。
3.MyBatis框架的适用场合
MyBatis框架专注于SQL本身,是一个足够灵活的DAO层解决方案。它适用于性能要求很高或需求变化较多的项目,如互联网项目。
下面介绍百货中心供应链管理系统,并完成相应的上机练习。
1.2.7 技能训练
百货中心供应链管理系统是一个B/S架构的信息管理平台,该系统的主要业务需求是,记录并维护百货公司的供应商信息,以及该百货公司与供应商、顾客之间交易的订单信息。该系统主要包括系统管理员、经理、普通员工等角色,其具体内容请参考附录A。
上机练习1 查询供应商表的记录数
需求说明
为百货中心供应链管理系统搭建MyBatis框架环境,并实现供应商表(tb_provider)的总记录数查询。
(1)在MyEclipse中创建工程MyBatisDemo,导入MyBatis框架所需的jar文件。
(2)创建MyBatis框架的配置文件mybatis-config.xml。
(3)创建供应商表对应的实体类Provider和SQL映射文件ProviderMapper.xml。
(4)编写测试类ProvideMapperTest.java,并在后台运行输出结果。