深入分析 iBATIS 框架之系统架构与映射原理
- 格式:doc
- 大小:324.00 KB
- 文档页数:12
mybatis结果集映射原理MyBatis结果集映射原理MyBatis是一个优秀的持久层框架,它可以帮助开发人员轻松地与数据库进行交互。
在使用MyBatis时,结果集映射是其中一个非常重要的功能。
本文将介绍MyBatis结果集映射的原理以及如何正确地使用它。
一、什么是结果集映射?结果集映射是将数据库查询结果映射到Java对象的过程。
在MyBatis中,开发人员可以使用XML配置文件或注解来定义结果集映射规则。
通过结果集映射,我们可以将查询结果转换为Java对象,并直接使用这些对象进行业务逻辑的处理。
二、结果集映射的原理1. SQL语句的执行和结果集的获取在MyBatis中,首先需要执行SQL语句并获取查询结果。
MyBatis 使用JDBC来执行SQL语句,并通过ResultSet对象来获取查询结果。
2. 结果集映射规则的定义在MyBatis中,我们可以使用XML配置文件或注解来定义结果集映射规则。
XML配置文件中可以使用resultMap元素来定义映射规则,注解中可以使用@Results和@Result来定义映射规则。
3. 结果集映射规则的解析和执行在执行SQL语句并获取查询结果后,MyBatis会根据定义的结果集映射规则来解析查询结果。
它会根据映射规则中的属性名和查询结果中的列名进行匹配,并将查询结果映射到Java对象的对应属性中。
4. 结果集映射的处理过程在解析查询结果并映射到Java对象后,MyBatis会根据映射规则来处理结果集映射。
在处理过程中,MyBatis可以根据映射规则中的配置来处理一对一、一对多以及多对多的关联关系。
通过结果集映射,我们可以方便地处理复杂的业务逻辑。
三、结果集映射的配置方式1. XML配置文件方式在XML配置文件中,可以使用resultMap元素来定义结果集映射规则。
resultMap元素可以包含id属性、type属性和子元素。
id属性用于标识结果集映射规则,type属性用于指定映射规则对应的Java 对象类型,子元素用于定义具体的映射规则。
ibaties 动态sql 解析摘要:1.动态SQL概述2.ibatis动态SQL解析原理3.动态SQL的优点与不足4.实战应用案例解析正文:一、动态SQL概述动态SQL,顾名思义,是一种可变的SQL语句,其可以根据特定条件生成不同的SQL查询语句。
这种SQL语句通常应用于需要根据不同情况进行查询的情况下,如参数查询、分页查询等。
动态SQL可以提高代码的可复用性、灵活性,降低维护成本。
二、ibatis动态SQL解析原理ibatis是一款优秀的持久层框架,它支持动态SQL的解析和执行。
其解析动态SQL的原理主要包括以下几个步骤:1.解析动态SQL语句,提取关键字段、条件、动作等元素。
2.生成对应的SQL映射文件,用于存储动态SQL的解析结果。
3.在运行时,根据传入的参数和条件,动态生成最终的SQL语句并执行。
三、动态SQL的优点与不足优点:1.提高代码的可读性和可维护性。
2.降低数据库访问层的复杂性。
3.便于实现分页、参数查询等复杂查询。
不足:1.编写和调试动态SQL较为复杂。
2.过多的动态SQL可能导致性能下降。
四、实战应用案例解析案例一:分页查询```<select id="selectByPage" resultMap="userResultMap"> SELECT * FROM userWHERE 1=1<if test="pageNo != null and pageSize != null">AND (SELECT COUNT(*) FROM user) > (CURRENT_PAGE * PAGE_SIZE)</if></select>```案例二:参数查询```<select id="selectByCondition" resultMap="userResultMap"> SELECT * FROM userWHERE 1=1<if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></select>```总结:动态SQL在实际开发中具有一定的优势,可以提高代码的可读性和灵活性。
目录1.1OR Mapping半自动化的IBatis框架(第1部分) (2)1.1.1IBatis框架相关技术概述 (2)1.1.2下载MyBatis系统库及相关的资源 (5)1.1.3构建应用项目及相关的配置文件 (6)1.1.4熟悉Mybatis的SqlMap映射配置文件 (13)1.1.5熟悉SqlMap映射配置文件 (15)1.1OR Mapping半自动化的IBatis框架(第1部分)1.1.1IBatis框架相关技术概述1、iBATIS一词来源于“internet”和“abatis”的组合(1)它是一个由Clinton Begin在2001年发起的开放源代码项目最初侧重于密码软件的开发,现在是一个基于Java的持久层框架。
iBATIS正确的写法应该是:iBATIS。
(2)iBATIS提供的持久层框架的主要内容iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO),同时还提供一个利用这个框架开发的JPetStore实例。
iBATIS本质上是一个SQL语句映射的框架(工具)。
(3)ibatis是一种“半自动化”的ORM实现相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,ibatis是一种“半自动化”的ORM实现。
当然,这里的“半自动化”,是相对Hibernate等提供了全面的数据库封装机制的“全自动化”的ORM实现而言,“全自动”ORM实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。
而ibatis的着力点,则在于将实体类(POJO)与SQL之间的映射关系。
也就是说,ibatis 并不会为程序员在运行期自动生成SQL执行的语句。
而具体的SQL语句需要程序员自己编写,然后通过映射配置文件,将SQL语句中所需的各个参数,以及返回的结果字段映射到指定的POJO中。
这种策略可以允许开发人员自己来写合适的SQL语句,而Hibernate在实体类和数据库之间建立了映射关系,SQL语句对于开发人员是不可见的,对于那些数据量非常大的应用,无法去优化SQL语句。
iBATIS 框架主要的类层次结构按照 JDBC 规范建立与数据库的衔接;通过反射打通 Java 对象与数据库参数交互之间互相转化关系。
iBATIS 的框架结构也是根据这种思想来组织类层次结构的,其实它是一种典型的交互式框架。
先期预备好交互的须要条件,然后构建一个交互的环境,交互环境中还划分成会话,每次的会话也有一个环境。
当这些环境都预备好了以后,剩下的就是交换数据了。
其实涉及到网络通信,普通都会是类似的处理方式。
图 1 是iBATIS 框架的主要的类层次结构图:上面的类图中左边SqlMapClient 接口主要定义了客户端的操作行为包括 select、insert、up、delete。
而右边主要是定义了当前客户端在当前线程的执行环境。
SqlMapSession 可以分享用法,也可以自己创建,假如是自己创建在结束时必需要调用关闭接口关闭。
当用法者持有了 SqlMapClientImpl 对象就可以用法 iBATIS 来工作了。
这里还要提到另外一个类SqlMapExeorDelegate 这个类从名字就可以看出他是执行代理类。
这个类十分重要,重要是由于他耦合了用户端的执行操作行为和执行的环境,他持有执行操作的所需要的数据,同时提供管理着执行操作依靠的环境。
所以他是一个强耦合的类,也可以看做是个工具类。
iBATIS 主要的设计目的还是为了让我们执行 SQL 时对输入输出的数据管理越发便利,所以如何便利的让我们写出 SQL 和便利的猎取 SQL 的执行结果才是 iBATIS 的核心竞争力。
那么 iBATIS 是怎么实现它的核心竞争力的呢? iBATIS 框架的一个重要组成部分就是其 SqlMap 配置文件,SqlMap 配置文件的核心是 Statement 语句包括 CIUD。
iBATIS 通过解析 SqlMap 配置文件得到全部的 Statement 执行语句,同时会形成 ParameterMap、ReltMap 两个对象用于处理参数和经过解析后交给数据库处理的 Sql 对象。
Ibatis:ibatis和hibernate的区别ibatis是在结果集与实体类之间进行映射hibernate是在数据库与实体类之间进行映射Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate 可以在应用EJB的J2EE架构中取代CMP【CMP(Container-Managed Persistence)表示由EJB 容器来管理实体EJB 的持久化,EJB 容器封装了对象-关系的映射及数据访问细节】,完成数据持久化的重任。
一、基本功能Hibernate作为数据持久化的中间件,足以让数据库在业务逻辑层开发中去冬眠。
它通过可扩展标记语言(XML)实现了类和数据表之间的映射,使程序员在业务逻辑的开发中面向数据库而改为面向对象开发。
使整个项目开发分工更加明确,提高了程序开发的效率。
configuration对象:Configuration 类负责管理Hibernate 的配置信息。
Hibernate 运行时需要获取一些底层实现的基本信息,其中几个关键属性包括:1.数据库URL2.数据库用户3.数据库用户密码4.数据库JDBC驱动类5.数据库dialect,用于对特定数据库提供支持,其中包含了针对特定数据库特性的实现,如Hibernate数据类型到特定数据库数据类型的映射等。
以上信息一般情况下由hibernate.cfg.xml或者hibernate.properties文件来配置,实现与不同数据库的连接。
Session对象:Session是持久层操作的基础,相当于JDBC中的Connection:实例通过SessionFactory实例构建:Configuration config = new Configuration().configure(); SessionFactorysessionFactory = config.buildSessionFactory();Session session = sessionFactory.openSession();之后我们就可以调用Session所提供的save、find、flush等方法完成持久层操作。
目录Ibatis知识点学习总结 (2)简介 (2)特点 (2)资源 (3)第Ⅰ部分:使用ibatis开发第一个程序 (3)准备与测试 (3)使用ibatis完成对数据表的增、删、改、查操作 (4)第Ⅱ部分:Ibatis知识点总结 (11)JDBC回顾 (11)Ibatis配置文件— sqlMapConfig (12)Ibatis OR映射文件— sqlMap (16)第Ⅲ部分:SqlMap API使用方法学习总结 (24)SqlMap API使用方法与简单编程 (24)SqlMap API中重要类学习总结 (25)第Ⅳ部分:Ibatis系统架构与映射原理 (28)Ibatis框架的主要类层次结构 (28)Ibatis框架的设计策略 (29)Ibatis框架的运行原理 (30)Ibatis对SQL语句的解析 (31)Ibatis数据库字段映射到Java对象 (31)Ibatis知识点学习总结简介ibatis一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。
最初侧重于密码软件的开发,现在是一个基于Java的持久层框架。
2010年这个项目由apache software foundation 迁移到了google code,并且改名为mybatis。
特点优点:✧简单易于掌握从只懂得JDBC操作到能够使用ibatis进行创建(Create)、更新(Update)、读取(Read)和删除(Delete)等操作可能只需要一天的时间。
✧易于进行sql优化从第一次开始使用,就会明白,用这个持久层框架需要自己完成sql语句的书写。
而hibernate可以全自动的帮我们完成这个工作。
这个半自动的ORM实现可以让我们进行sql语句的优化。
在项目中我们是使用分库分表进行数据操作,使用的数据库是开源数据库MySql。
我问过师兄这个问题,MySql能不能承受的住这么大的数据库操作频率以及复杂的业务逻辑。
mybatis工作原理MyBatis是一种持久层框架,它提供了一种数据映射技术,可以将程序中操作数据库的代码从java代码中分离出来,避免繁琐的jdbc代码编写。
MyBatis也称为iBATIS,它是Apache的一个开源项目。
MyBatis的工作原理是通过构建一个SQL映射文件,将SQL语句和Java代码关联起来,从而达到解耦的目的。
MyBatis的使用方法是将查询SQL语句写入xml文件中,并将它与Java代码建立映射关系。
xml文件中保存了查询SQL语句,Java代码中则对xml文件中的SQL语句进行参数传递,完成到数据库的查询。
MyBatis的运行原理主要可以分为三个部分:加载配置文件、准备数据和执行SQL语句。
1、加载配置文件MyBatis使用XML文件来配置SQL语句,每个XML文件都包含一个<mapper>标签,它代表一个SQL映射文件,在实际使用中,一般把SQL映射文件和对应的Java实体类放在同一个包中,这样当MyBatis 开始工作的时候,就会自动加载这些映射文件,这是MyBatis的第一步。
2、准备数据当MyBatis加载完SQL映射文件后,它会根据XML文件中的<parameter>标签获取参数,将参数传递给SQL语句,并且根据<result>标签返回SQL查询结果。
3、执行SQL语句最后MyBatis会调用数据库驱动程序来执行SQL语句,将查询结果返回给应用程序,程序也可以根据XML文件中的<result>或<parameter>标签来自动映射Java实体类,从而避免jdbc的反复编写。
MyBatis的工作原理简单易懂,但它的实际实现并不复杂,它能够大大减少java代码的编写,提高数据库查询效率,一般来说,用户仅仅需要配置XML映射文件即可完成对数据库的操作。
MyBatis虽然有着一系列优点,但还是存在一些不足,比如MyBatis不支持复合主键,也不支持多表联查,还有缓存功能不够强大,这些都需要用户注意。
ibatis 面试题iBatis 是一个持久化框架,用于将 Java 对象映射到关系型数据库中的数据表。
它提供了一个简单、直观的方式来管理 SQL 语句与 Java 代码之间的映射关系,使得开发者能够更加便捷地进行数据库操作。
本文将介绍一些常见的 iBatis 面试题,帮助读者更好地了解和掌握这个框架。
1. 什么是 iBatis?iBatis 是一个开源的持久化框架,旨在提供一种简单、直观的方式来执行数据库操作。
它通过将 SQL 语句与 Java 对象之间进行映射,使得开发者能够使用纯粹的 SQL 进行数据库操作,而无需关注数据库底层的细节。
2. iBatis 与 Hibernate 有什么区别?iBatis 和 Hibernate 都是 Java 平台上的持久化框架,但它们有一些不同之处。
主要区别包括:- 对象关系映射方式:iBatis 使用基于 SQL 的映射方式,而Hibernate 使用基于对象的映射方式。
- SQL 控制权:iBatis 中,开发者需要手动编写和管理 SQL 语句;而 Hibernate 则自动生成 SQL 语句,并利用对象的映射信息进行操作。
- 学习曲线:iBatis 相对来说较为简单,易于上手;而 Hibernate 更为复杂,需要更多的学习和理解。
3. iBatis 的工作原理是什么?iBatis 的工作原理可以简单概括为以下几个步骤:- 创建一个与数据库连接的 SqlSessionFactory 对象。
- 使用 SqlSessionFactory 创建一个 SqlSession 对象。
- 在 SqlSession 中执行 SQL 语句,并将结果映射到 Java 对象。
- 关闭 SqlSession。
4. 请简述 iBatis 中的 SqlMapConfig.xml 文件的作用。
SqlMapConfig.xml 是 iBatis 的配置文件,它用于配置数据库连接和其他全局配置信息。
ibatis的原理iBATIS(即Internet-Based Automated Testing Information System)是一种基于Java的持久化框架,用于简化数据库访问的过程。
它采用了一种简单直观的方式来映射Java对象和SQL语句,使得开发人员可以更加专注于业务逻辑的实现,而不用关心底层的数据库操作细节。
iBATIS的原理可以简单概括为以下几个方面:1. SQL映射文件:iBATIS通过XML格式的SQL映射文件来定义数据库操作的语句。
这些映射文件包含了SQL语句的定义,以及与Java对象之间的映射关系。
开发人员可以在映射文件中定义各种操作,如插入、更新、删除和查询等。
2. 数据源配置:在应用程序启动时,需要配置数据源,即数据库的连接信息。
iBATIS支持多种数据源类型,如JDBC、JNDI和DataSource等。
通过配置数据源,iBATIS可以根据需要获取数据库连接,并执行相应的SQL语句。
3. SQL执行:在执行SQL语句之前,需要创建一个SqlMapClient 对象,该对象是iBATIS的核心组件之一。
通过SqlMapClient对象,可以获取一个SqlSession对象,通过该对象可以执行SQL语句。
在执行SQL语句时,iBATIS会根据映射文件中定义的SQL语句,将Java对象与SQL语句进行参数映射,并执行相应的数据库操作。
4. 结果映射:执行SQL语句后,iBATIS会将查询结果映射到Java 对象中。
开发人员可以在映射文件中定义映射规则,将查询结果的列与Java对象的属性进行映射。
iBATIS支持多种映射方式,如自动映射、手动映射和混合映射等。
通过结果映射,可以将数据库查询结果转化为Java对象,便于在应用程序中进行处理和展示。
5. 缓存管理:为了提高数据库访问的性能,iBATIS提供了一种缓存机制。
在执行SQL语句时,iBATIS会将查询结果缓存起来,下次执行相同的查询时,可以直接从缓存中获取结果,而不必再次访问数据库。
/62575/83896iBatis2学习笔记:基本原理和配置iBatis2是一个轻量级的数据持久化框架,它是一个半自动化的ORMapping工具,数据库的操作依赖程序员自己书写的SQL,因此可以最大限度发挥JDBC的性能。
据测试,它的性能和JDBC是一个级别的,但代码比JDBC简单的多,据说相对JDBC节省了60%的代码量。
缺点是映射不灵活,有时候感觉很别扭。
当领域对象关系复杂的时候,关联基本上行不通。
--复杂关系通过存储过程解决吧by scott注.iBatis2整个框架的jar包就一个,337KB,相比Hibernate等其他框架非常的小巧可爱,并且有.net语言版本。
iBatis2的优缺点不是关心的重点,主要是在实际中扬长避短。
下面是iBatis2的框架图:和Hibernate的SessionFactory类似,iBatis2有SqlMapClientBuilder一个类,通过配置文件SqlMapConfig.xml类构建,这个是线程安全的类,并且是单例模式,从它里面可以获取SqlMapClient,SqlMapClient相当于Hibernate的session,用来执行预定义的SQL语句。
因此SqlMapClient Builder、SqlMap Config.xml、SqlMap Client将是学习iBatis2的核心。
以后会逐渐展开,下面是从变成角度来构建SqlMapClientBuilder。
String resource ="SqlMapConfig.xml";Reader reader = Resources.getResourceAsReader(resource);SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);由于SqlMapClient Builder的构建是相当耗时的,因此一般都是在程序启动的时候构建一次,并反复使用。
深入分析iBA TIS 框架之系统架构与映射原理iBATIS 框架主要的类层次结构总体来说 iBATIS 的系统结构还是比较简单的,它主要完成两件事情:1.根据 JDBC 规范建立与数据库的连接;2.通过反射打通 Java 对象与数据库参数交互之间相互转化关系。
回页首iBATIS 框架的设计策略iBATIS 主要的设计目的还是为了让我们执行 SQL 时对输入输出的数据管理更加方便,所以如何方便的让我们写出 SQL 和方便的获取 SQL 的执行结果才是iBATIS 的核心竞争力。
那么 iBATIS 是怎么实现它的核心竞争力的呢?iBATIS 框架的一个重要组成部分就是其 SqlMap 配置文件,SqlMap 配置文件的核心是 Statement 语句包括 CIUD。
iBATIS 通过解析 SqlMap 配置文件得到所有的 Statement 执行语句,同时会形成 ParameterMap、ResultMap 两个对象用于处理参数和经过解析后交给数据库处理的 Sql 对象。
这样除去数据库的连接,一条 SQL 的执行条件已经具备了。
图 2 描述了 Statement 有关的类结构图:图 2. Statement 有关的类结构图图 2 给出了围绕 SQL 执行的基本的结构关系,但是还有一个关键的部分就是,如何定义 SQL 语句中的参数与 Java 对象之间的关系,这其中还涉及到 Java 类型到数据库类型的转换等一系列问题。
数据的映射大体的过程是这样的:根据 Statement 中定义的 SQL 语句,解析出其中的参数,按照其出现的顺序保存在 Map 集合中,并按照 Statement 中定义的 ParameterMap 对象类型解析出参数的 Java 数据类型。
并根据其数据类型构建 TypeHandler 对象,参数值的复制是通过 DataExchange 对象完成的。
图 3 是参数映射相关的类结构图:图 3. 参数映射相关的类结构图图 3 是输入参数的映射结构情况,返回结果 ResultMap 的映射情况也是类似的。
主要就是要解决 SQL 语句中的参数与返回结果的列名与 Statement 中定义的 parameterClass 和 resultClass 中属性的对应关系。
回页首iBATIS 框架的运行原理前面大体分析了 iBATIS 框架的主要类的结构,这里主要看一下这些类是如何串联起来、如何工作的。
图 4 描述了整个过程的主要执行步骤。
图 4.iBATIS 运行的主要执行步骤上图中描述的 SqlMapSession 对象的创建和释放根据不同情况会有不同,因为SqlMapSession 负责创建数据库的连接,包括对事务的管理,iBATIS 对管理事务既可以自己管理也可以由外部管理,iBATIS 自己管理是通过共享SqlMapSession 对象实现的,多个 Statement 的执行时共享一个SqlMapSession 实例,而且都是线程安全的。
如果是外部程序管理就要自己控制SqlMapSession 对象的生命周期。
图 5 是通过 Spring 调用 iBATIS 执行一个 Statement 的一个详细的时序图:图 5. Spring 调用 iBATIS 执行一个 Statement 的时序图(查看图 5 的清晰版本。
)iBATIS 的主要工作连接、交互,所以必须根据不同的交易成本设计不同的交易环境。
示例下面我们将根据一个具体的实例解析一个 Statement 如何完成映射的,我们用一个典型的查询语句看看 Java 对象中的数据时如何赋给 SQL 中的参数的,再看看 SQL 的查询结果是如何转成 Java 对象的。
先看一下示例的部分代码和配置文件,完整的代码请看附件。
Spring 的 applicationContext 配置文件:清单 1. applicationContext.xml<beans><bean id="sqlMapTransactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManag er"><property name="dataSource" ref="dataSource"/></bean><bean id="sqlMapTransactionTemplate"class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"ref="sqlMapTransactionManager"/></bean><!--sql map --><bean id="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"><property name="configLocation"value="com/mydomain/data/SqlMapConfig.xml"/><property name="dataSource" ref="dataSource"/></bean><bean id="dataSource" name="dataSource"class="mons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName"value="oracle.jdbc.driver.OracleDriver"/><property name="url"value="jdbc:oracle:thin:@10.1.5.11:1521:XE"/><property name="username" value="junshan"/><property name="password" value="junshan"/><property name="maxActive" value="20"/></bean><bean id="accountDAO" class="com.mydomain.AccountDAO"><property name="sqlMapClient" ref="sqlMapClient"/><property name="sqlMapTransactionTemplate"ref="sqlMapTransactionTemplate"/></bean></beans>下面是 Account.xml 的一个 Statement:清单 2. Account.xml 中一个 Statement<select id="selectAccount" parameterClass="Account"resultClass="Account">selectACC_ID,ACC_FIRST_NAME as firstName,ACC_LAST_NAME as lastName,ACC_EMAIL as emailAddress,ACC_DATEfrom ACCOUNTwhere ACC_ID = #id:INTEGER# and ACC_FIRST_NAME = #firstName#</select>下面是 Java 的测试类:清单 3. SimpleTestpublic class SimpleTest {public static void main(String[] args) {ApplicationContext factory =newClassPathXmlApplicationContext("/com/mydomain/data/applicationContext .xml");final AccountDAO accountDAO = (AccountDAO)factory.getBean("accountDAO");final Account account = new Account();account.setId(1);account.setFirstName("tao");account.setLastName("bao");account.setEmailAddress("junshan@");account.setDate(new Date());try {accountDAO.getSqlMapTransactionTemplate().execute(new TransactionCallback(){public Object doInTransaction(TransactionStatus status){try{accountDAO.deleteAccount(account.getId());accountDAO.insertAccount(account);//account.setLastName("bobo");//accountDAO.updateAccount(account);Account result =accountDAO.selectAccount(account);System.out.println(result);return null;} catch (Exception e) {status.setRollbackOnly();return false;}}});//accountDAO.getSqlMapClient().commitTransaction();} catch (Exception e) {e.printStackTrace();}}}iBATIS 对 SQL 语句的解析这里所说的 SQL 解析只是针对 iBATIS 配置文件中所定义的 SQL 语句,如前一节中清单 2 中所示的查询语句。