- Java EE轻量级框架应用实战:SSM框架(Spring MVC+Spring+MyBatis)
- 石毅
- 2143字
- 2020-08-27 11:30:32
2.1 MyBatis框架的核心接口和类
使用MyBatis框架对项目进行测试时,创建SqlSession对象的代码如下。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_1.jpg?sign=1739174073-78IrM4v3ueBYnRUXQfXoNDaNim4whaTA-0-3a7deb9a3cb70057c5866095e0a42e3e)
代码中涉及两个核心对象:SqlSessionFactory和SqlSession,它们在MyBatis框架中起着至关重要的作用。本节将对这两个对象进行详细讲解。首先介绍MyBatis框架的核心接口和类,如图2.1所示。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_2.jpg?sign=1739174073-e0NKg3Wvg5s3XklGlfEQXwudajl5SSMf-0-b17aeecd149fe7f8042f21c1aaf36cbe)
图2.1 MyBatis框架的核心接口和类
(1)每个MyBatis框架的应用程序都以一个SqlSessionFactory对象的实例为核心。
(2)获取SqlSessionFactoryBuilder对象,可根据XML配置文件或Configuration类的实例构建该对象。
(3)获取SqlSessionFactory对象,可以通过SqlSessionFactoryBuilder对象来获得。
(4)获取SqlSession实例,SqlSession对象包含以数据库为背景的所有执行SQL操作的方法,可以使用该实例直接执行已映射的SQL语句。
2.1.1 SqlSessionFactoryBuilder
1.SqlSessionFactoryBuilder的作用
SqlSessionFactoryBuilder负责构建SqlSessionFactory,并提供多个build()方法的重载,如图2.2所示。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_3.jpg?sign=1739174073-E2AFuQO2EkWaN1WrsNTJhwPxVxoUYjLq-0-d59d9d9eefc91ed5d8722cd7c97dbb41)
图2.2 SqlSessionFactoryBuilder提供的build()方法
通过源码分析,可以发现它们都在调用同一签名方法:
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_4.jpg?sign=1739174073-haQwDkLyqiIADcWa9MHYRsCeqURd1RP9-0-c85a87af6963045d6d078eeafc9c50f8)
由于方法参数environment和properties都可以为null,那么真正的重载方法只有如下3种。
(1)build(Reader reader,String environment,Properties properties)。
(2)build(InputStream inputStream,String environment,Properties properties)。
(3)build(Configuration config)。
通过上述分析发现,配置信息提供给SqlSessionFactoryBuilder的build()方法,包括InputStream(字节流)、Reader(字符流)和Configuration(类),由于字节流与字符流都属于读取配置文件的方式,所以从配置信息的来源就很容易想到构建一个SqlSessionFactory的两种方式:读取XML配置文件和编程。本章采用读取XML配置文件的方式。
2.SqlSessionFactoryBuilder的生命周期和作用域
SqlSessionFactoryBuilder的最大特点是用过即丢。一旦创建SqlSessionFactory后,这个类就不再需要了,因此SqlSessionFactoryBuilder的最佳范围就是存在于方法体内,也就是局部变量。
2.1.2 SqlSessionFactory
1.SqlSessionFactory的作用
SqlSessionFactory就是创建SqlSession实例的工厂,所有的MyBatis框架应用都以SqlSessionFactory实例为中心。SqlSessionFactory实例可以通过SqlSessionFactoryBuilder来获得,然后就可以使用openSession()方法来获取SqlSession实例,如图2.3所示。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_5.jpg?sign=1739174073-1N2MlU9HS8GBK8YdEtVaqZYT4zp2TTyc-0-db190c39fdc42a69d0cc1e4288394d53)
图2.3 SqlSessionFactory提供的openSession()方法
当openSession()方法的参数为boolean值时,若传入true则表示关闭事务控制,自动提交;若传入false则表示开启事务控制。若不传入参数则默认为true。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_7.jpg?sign=1739174073-STWYDT9ebLtqy62xlnPMwtQxNYHpcOUh-0-fc267f49d8c0fa16f90da1c554409ecc)
2.SqlSessionFactory的生命周期和作用域
SqlSessionFactory一旦创建就会在整个应用运行过程中始终存在,没有理由销毁或再创建,并且在应用运行中也不建议多次创建SqlSessionFactory。因此SqlSessionFactory的最佳作用域就是Application,即随着应用的生命周期一同存在。那么这种“存在于整个应用运行期间,并且同时只存在一个对象实例”的模式就是单例模式(指在应用运行期间有且仅有一个实例)。
下面将对获取SqlSessionFactory的代码进行优化,最简单的实现方式就是放在静态代码块下,以保证SqlSessionFactory只被创建一次,其实现步骤如下。
(1)创建工具类MyBatisUtil.java,在静态代码块中创建SqlSessionFactory。
在前面的案例中,每个方法执行时都需要读取配置文件,并根据配置文件的信息构建SqlSessionFactory,然后再创建SqlSession,这就导致了大量的重复代码。为了简化开发,可以先将上述重复代码封装到一个工具类中,然后通过工具类来创建SqlSession,其代码见示例1。
【示例1】 工具类MyBatisUtil.java
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_9.jpg?sign=1739174073-Zfko8R4UKl4NHPeIUPhKNHX3uZqtzq1O-0-51f375fbce222317826ac56ec06d6b66)
(2)创建 SqlSession和关闭SqlSession,其代码见示例2。
【示例2】 创建SqlSession和关闭SqlSession
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_11.jpg?sign=1739174073-FxQIfULG1vGB25cobj9y8u0QWvSTubd7-0-6c4fd1ecbb2c2c789ef70b011206a47a)
通过以上静态类的方式来保证SqlSessionFactory实例只能被创建一次。当然,最佳的解决方案是使用依赖注入容器—Spring框架来管理SqlSessionFactory的单例生命周期。
设计模式中的单例模式将在后续的Spring MVC中具体展开讲解,此处了解即可。
2.1.3 SqlSession
1.SqlSession的作用
SqlSession是用于执行持久化操作的对象,类似于JDBC的Connection。它提供了面向数据库执行SQL命令所需的所有方法,可以通过SqlSession实例直接运行已映射的SQL语句,SqlSession提供的方法如图2.4所示。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_13.jpg?sign=1739174073-i72k3VXKHfO92itlpD1YuOolMsjOO6qP-0-6e7b247870cc2aee4da807ba3d812a47)
图2.4 SqlSession提供的方法
2.SqlSession的生命周期和作用域
SqlSession对应着一次数据库会话,由于数据库会话不是永久的,因此SqlSession的生命周期也不是永久的。相反,在每次访问数据库时都需要创建它(并不是在SqlSession里只能执行一次SQL,是完全可以执行多次的,但若关闭SqlSession则需要重新创建)。创建SqlSession的地方只有一个,就是SqlSessionFactory对象的openSession()方法。
每个线程都有自己的SqlSession实例,SqlSession实例不能被共享,也不是线程安全的。因此最佳的范围是在request作用域或方法体作用域内。
关闭SqlSession是非常重要的,必须确保SqlSession在finally语句块中正常关闭。关闭的标准方式如下。
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_15.jpg?sign=1739174073-Sd0b7munKbs9PxbVfyWYWIYBNmwqFkNU-0-f1e6cf16b4b4de4b30b51f9c1a2642ec)
3.SqlSession的常用方法
SqlSession中包含了很多方法,其常用方法及其说明如表2-1所示。
表2-1 SqlSession的常用方法及其说明
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_16.jpg?sign=1739174073-cDMUWt0AlFHJDz3hdL4f7GQhi1kc0J18-0-c7161604730cafba672732dfcb34ab3a)
续表
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_17.jpg?sign=1739174073-y9SOAuHtvASPSD4j16zA9nxfiDmxw1f1-0-7583a741df087246d7d0f11c7727ca99)
4.SqlSession的两种使用方式
(1)通过SqlSession实例直接执行已映射的SQL语句。
如通过调用selectList方法执行用户表的查询操作,其步骤如下。
修改UserMapper.xml文件,增加查询用户列表的select节点,见示例3。
【示例3】 增加查询用户列表的select节点
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_19.jpg?sign=1739174073-a3lSG8g6wHJ5H5djwSvejQ0OEuOuZuit-0-ad202d5a9cba58429a425acbd391d112)
修改测试类UserMapperTest.java,并调用selectList方法执行查询操作,见示例4。
【示例4】 调用selectList方法执行查询操作
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_21.jpg?sign=1739174073-6lYzO2FHUYtQWlMdrmw0FzUTScN3Il7X-0-3d8b9cbfb3c9d86c8aa4a7b5a0e91d94)
(2)基于Mapper接口方式操作数据。
修改上一个演示示例,其步骤如下。
创建绑定映射语句的UserMapper.java接口,并提供getUserList()接口方法,该接口称为映射器,见示例5。
接口的方法必须与SQL映射文件中SQL语句的id相对应。
【示例5】 UserMapper.java
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_24.jpg?sign=1739174073-k8sXlsY4gilXTSCVnHhldhlJ5vGQETpr-0-fe25229418f22b33d743a293884ea635)
修改测试类UserMapperTest.java,并调用getMapper(Mapper.class)执行Mapper接口方法实现对数据的查询操作,其代码见示例6。
【示例6】 UserMapperTest.java
![img](https://epubservercos.yuewen.com/1B1F03/17545850907267806/epubprivate/OEBPS/Images/txt002_26.jpg?sign=1739174073-tKoEtYT6n4UFFB5jjUU0HG7Uiv8GHw8N-0-1b820ec9b08832c47a7e5d3c76ef9f9a)
第1种方式是MyBatis旧版本提供的操作方式,虽然现在也可以正常工作,但第2种方式是MyBatis官方推荐使用的,其表达方式的代码更清晰且类型安全,不用担心易错的字符串字面值和强制类型转换。
2.1.4 技能训练
上机练习1 实现供应商表的查询
需求说明
在第1章练习搭建的环境中,完成以下操作。
(1)使用MyBatis框架实现对供应商表的查询操作(查询出全部数据)。
(2)编写工具类MyBatisUtil.java,获取SqlSessionFactory实例。
(3)分别使用两种方式(①通过SqlSession实例直接运行已映射的SQL语句;②基于Mapper接口方式操作数据)实现对数据的操作,并对比其区别。
(1)修改SQL映射文件ProviderMapper.xml,增加select元素节点,编写查询语句。
(2)编写MyBatisUtil.java,在静态代码块中实现SqlSessionFactory的创建,并在该类中增加创建SqlSession和关闭SqlSession的静态方法。
(3)创建绑定映射语句的Mapper接口:ProviderMapper.java。
(4)修改测试类ProviderMapperTest.java,按照两种方式分别实现对数据的操作,并在后台运行输出结果。