后端开发MyBatis框架题库及答案_第1页
后端开发MyBatis框架题库及答案_第2页
后端开发MyBatis框架题库及答案_第3页
后端开发MyBatis框架题库及答案_第4页
后端开发MyBatis框架题库及答案_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

后端开发MyBatis框架题库及答案一、单项选择题(共10题,每题1分,共10分)以下关于MyBatis核心接口SqlSession的描述,哪一项是正确的?A.SqlSession是线程安全的,可以在多个线程间共享。B.SqlSession实例可以通过SqlSessionFactory的openSession()方法获取。C.SqlSession主要负责执行SQL语句,但获取映射器的功能不属于其职责范围。D.一个SqlSession实例通常对应一个数据库物理连接,且其生命周期与应用程序相同。答案:B解析:SqlSession是MyBatis的核心接口,用于执行SQL命令、获取映射器和管理事务。SqlSessionFactory是创建SqlSession的工厂,通过其openSession()方法可以获取SqlSession实例。选项A错误,因为SqlSession是线程不安全的,每个线程都应该有它自己的SqlSession实例。选项C错误,SqlSession提供了getMapper()方法用于获取映射器接口的代理对象。选项D错误,SqlSession的生命周期通常与一次数据库会话(或事务)相关,使用完毕后需要及时关闭,而不是与整个应用程序生命周期相同。在MyBatis的XML映射文件中,用于实现结果集映射的元素是?A.<select>B.<resultMap>C.<parameterMap>D.<sql>答案:B解析:<resultMap>元素是MyBatis中最重要最强大的元素,它用于描述如何从数据库结果集中加载对象,定义了结果列与Java对象属性之间的映射规则。选项A<select>用于定义查询语句。选项C<parameterMap>是已被淘汰的元素,现在通常使用内联参数映射或@Param注解。选项D<sql>用于定义可重用的SQL片段。MyBatis的动态SQL标签<if>通常与哪个标签结合使用来构建灵活的WHERE子句?A.<trim>B.<where>C.<set>D.<foreach>答案:B解析:<where>标签会智能地处理其内部<if>标签生成的SQL片段。只有当其内部有内容时,它才会插入WHERE关键字;并且如果内容以AND或OR开头,它会自动将其去除,从而避免SQL语法错误。选项A<trim>功能更强大,可以自定义前缀后缀及要移除的字符串,<where>可以看作是<trim>的一种特定实现。选项C<set>用于动态生成UPDATE语句中的SET部分。选项D<foreach>用于遍历集合,常用于IN条件。当Java方法有多个参数时,在MyBatis的Mapper接口方法中,如何正确引用这些参数?A.默认按参数顺序使用arg0,arg1…或param1,param2…来引用。B.必须在映射文件中使用{0},{1}…的格式来引用。C.只能将多个参数封装到一个POJO对象中传递。D.MyBatis不支持一个方法有多个参数。答案:A解析:当Mapper接口方法有多个参数且未使用@Param注解时,MyBatis默认会为它们生成名称:arg0,arg1,…或者param1,param2,…。在XML中可以使用{arg0}或{param1}来引用第一个参数。选项B错误,{0}的格式在某些旧版本或特定配置下可能有效,但不是标准且推荐的做法。选项C错误,除了封装成POJO,使用@Param注解是更常见和灵活的方式。选项D明显错误。以下关于MyBatis一级缓存和二级缓存的描述,哪一项是错误的?A.一级缓存是SqlSession级别的缓存,默认开启。B.二级缓存是SqlSessionFactory级别的缓存,需要手动配置开启。C.任何INSERT,UPDATE,DELETE操作都会清空一级和二级缓存。D.二级缓存可以跨SqlSession共享数据,适用于查询多、修改少的应用场景。答案:C解析:选项C的描述不准确。INSERT,UPDATE,DELETE操作(即增删改操作)会清空一级缓存,因为它们可能改变了数据库中的数据,为了保证数据一致性,必须清空当前SqlSession的缓存。对于二级缓存,这些操作会刷新(清空)相关命名空间(namespace)的缓存,但并非无条件清空所有二级缓存,而是通过缓存机制(如LRU)和配置来决定。选项A、B、D的描述均正确。在MyBatis中,{}和${}这两种占位符的主要区别是什么?A.{}是字符串替换,${}是参数占位符。B.{}会将传入的数据原样输出,${}会进行预编译处理。C.{}能有效防止SQL注入,${}无法防止SQL注入。D.{}只能用于参数是简单类型的情况,${}可以用于复杂对象。答案:C解析:{}是MyBatis的参数占位符,MyBatis会使用PreparedStatement的?进行预编译,能有效防止SQL注入攻击。${}是字符串替换,MyBatis会将其中的内容直接拼接进SQL语句中,存在SQL注入风险。选项A和B正好说反了。选项D错误,两者都可以用于简单类型和复杂对象(通过OGNL表达式)。如果想在MyBatis的XML映射文件中引用一个已定义的、可重用的SQL代码片段,应该使用哪个标签?A.<include>B.<refid>C.<import>D.<fragment>答案:A解析:<include>标签用于引用通过<sql>标签定义的SQL片段。其refid属性指向被引用的<sql>标签的id。例如:<includerefid="baseColumnList"/>。选项Brefid是<include>标签的一个属性,不是独立标签。选项C<import>用于在MyBatis配置文件中引入其他配置文件。选项D不是MyBatis标准标签。以下哪种情况,MyBatis的延迟加载(懒加载)特性可能会失效?A.在SqlSession关闭后,调用关联对象的getter方法。B.在配置文件中将lazyLoadingEnabled设置为true。C.使用association或collection标签的fetchType属性设置为lazy。D.在同一个SqlSession生命周期内,先查询主对象,再调用关联对象的getter方法。答案:A解析:MyBatis的延迟加载(懒加载)功能依赖于SqlSession的生命周期。关联对象的数据是在调用其getter方法时,由MyBatis发出额外的SQL查询来加载的。如果SqlSession已经关闭,数据库连接和相关资源已被释放,此时再尝试加载关联数据就会失败,通常会抛出异常。选项B和C是启用延迟加载的正确配置。选项D是延迟加载的正常工作流程。MyBatis的TypeHandler(类型处理器)的主要作用是什么?A.处理Java对象与数据库表之间的映射关系。B.处理Java类型与JDBC类型之间的相互转换。C.处理SQL语句的动态生成。D.处理数据库事务的提交与回滚。答案:B解析:TypeHandler用于在Java类型(javaType)和JDBC类型(jdbcType)之间进行转换。当MyBatis向PreparedStatement设置参数,或者从ResultSet中获取结果时,就会使用注册的TypeHandler来完成这个转换过程。例如,将Java的String类型转换为数据库的VARCHAR类型,或者将数据库的TIMESTAMP转换为Java的Date。选项A描述的是ResultMap的作用。选项C描述的是动态SQL。选项D描述的是事务管理器。在SpringBoot项目中集成MyBatis,通常不需要进行以下哪项配置?A.在pom.xml中添加mybatis-spring-boot-starter依赖。B.在application.yml中配置mapper-locations来指定XML映射文件路径。C.手动编写代码创建SqlSessionFactoryBean并将其注入Spring容器。D.在主应用类上添加@MapperScan注解来扫描Mapper接口。答案:C解析:SpringBoot的自动配置机制极大地简化了MyBatis的集成。使用mybatis-spring-boot-starter后,SpringBoot会自动配置SqlSessionFactory和SqlSessionTemplate等核心Bean,开发者通常无需手动创建SqlSessionFactoryBean。选项A、B、D都是常见的、必要的或推荐的配置步骤。选项B用于告诉MyBatis去哪里找XML文件;选项D用于告诉Spring去哪里扫描Mapper接口并注册为Bean。二、多项选择题(共10题,每题2分,共20分)以下哪些是MyBatis的核心配置文件中<environments>标签内可以配置的组件?()A.事务管理器(transactionManager)B.数据源(dataSource)C.对象工厂(objectFactory)D.数据库厂商标识(databaseIdProvider)答案:AB解析:在MyBatis的核心配置文件(如mybatis-config.xml)中,<environments>标签用于配置环境信息,每个环境对应一个<environment>子标签。每个<environment>必须包含两个核心子标签:<transactionManager>(事务管理器)和<dataSource>(数据源)。选项C的<objectFactory>和选项D的<databaseIdProvider>是配置文件的顶级标签,与<environments>同级,而非其子标签。关于MyBatis的MapperXML文件,以下哪些说法是正确的?()A.其namespace属性必须对应一个Java接口的全限定名。B.文件中定义的SQL语句id必须与对应接口中的方法名一致。C.一个namespace下可以定义任意多个增删改查的SQL语句。D.参数类型(parameterType)和返回类型(resultType)是必须显式声明的属性。答案:ABC解析:选项A正确,namespace用于绑定DAO/Mapper接口,是实现接口与XML映射的关键。选项B正确,id属性值对应接口中的方法名,这样MyBatis才能将两者关联起来。选项C正确,一个MapperXML文件通常对应一个接口,可以定义该接口中所有方法对应的SQL。选项D错误,parameterType和resultType/resultMap在大多数情况下可以省略,MyBatis可以通过反射机制从接口方法签名中推断出来,但使用resultMap进行复杂映射时通常需要显式指定。MyBatis的动态SQL功能包含以下哪些标签?()A.<if>B.<choose>/<when>/<otherwise>C.<bind>D.<script>答案:ABCD解析:MyBatis提供了丰富的动态SQL标签来构建灵活的SQL语句。<if>用于条件判断;<choose>,<when>,<otherwise>用于实现类似Java中的switch-case逻辑;<bind>用于创建一个变量并将其绑定到上下文,常用于模糊查询时拼接%;<script>标签用于在注解中使用动态SQL(如@Select注解),将动态SQL语句包裹起来。因此所有选项均正确。以下哪些操作会导致MyBatis的一级缓存失效?()A.调用了当前SqlSession的clearCache()方法。B.执行了INSERT,UPDATE,DELETE语句(无论是否提交)。C.对MapperXML文件进行了修改并重新加载。D.在配置文件中将localCacheScope设置为STATEMENT。答案:ABD解析:一级缓存是SqlSession级别的。选项A,手动清空缓存当然会使其失效。选项B,任何写操作(增删改)都会清空当前SqlSession的一级缓存,以保证下次查询能获取到最新数据。选项D,将localCacheScope从默认的SESSION改为STATEMENT,意味着缓存作用域仅为当前语句,语句执行完毕即清空,相当于关闭了一级缓存。选项C,修改XML文件通常需要重启应用或特定的热部署机制,这本身不是一级缓存失效的常规触发条件;一级缓存的失效更多与SqlSession内的操作和配置有关。在MyBatis中,插入记录后获取自增主键值,可以采用以下哪些方式?()A.在<insert>标签中使用useGeneratedKeys和keyProperty属性。B.在<insert>标签内部使用<selectKey>子标签。C.在插入语句执行后,立刻执行一条SELECTLAST_INSERT_ID()的查询。D.依赖数据库连接池的特定功能自动回填。答案:AB解析:MyBatis提供了两种主要方式来获取插入后数据库生成的自增主键。选项A,使用useGeneratedKeys="true"keyProperty="id",告诉MyBatis使用JDBC的getGeneratedKeys方法来取出数据库内部生成的主键,并赋值给keyProperty指定的对象属性。选项B,使用<selectKey>标签,可以编写自定义的SQL语句(如调用序列)来获取生成的主键,灵活性更高,尤其适用于不支持自增主键的数据库(如Oracle)。选项C,虽然理论上可行,但这不是MyBatis框架内提供的标准、集成化的方式,且需要手动处理,容易出错。选项D,这不是MyBatis的标准行为。关于MyBatis的ResultMap,以下哪些描述是正确的?()A.可以使用<association>标签映射“一对一”或“多对一”关联关系。B.可以使用<collection>标签映射“一对多”关联关系。C.autoMapping属性可以开启或关闭自动映射行为。D.extends属性允许一个ResultMap继承另一个ResultMap的配置。答案:ABCD解析:ResultMap是MyBatis结果映射的核心。选项A和B正确,<association>用于处理单个关联对象(如订单关联一个用户),<collection>用于处理集合关联对象(如用户关联多个订单)。选项C正确,autoMapping属性(可以在<settings>中全局设置,也可以在<resultMap>中局部设置)控制是否开启非显式映射字段的自动映射。选项D正确,extends属性可以实现ResultMap的继承,复用公共的映射配置,减少重复代码。以下哪些是MyBatis支持的传递查询参数的方式?()A.使用单个基本类型或String类型参数。B.使用单个JavaBean(POJO)对象作为参数。C.使用Map集合作为参数。D.使用@Param注解标注多个参数。答案:ABCD解析:MyBatis提供了非常灵活的参数传递机制。选项A,简单类型参数可以直接使用。选项B,POJO对象的属性可以直接通过{属性名}引用。选项C,Map的键值对可以通过{key}引用。选项D,当方法有多个参数时,使用@Param(“参数名”)注解给每个参数命名,然后在XML中通过{参数名}引用。这四种方式都是MyBatis官方支持的标准用法。在Spring框架中与MyBatis集成时,以下哪些说法是正确的?()A.可以使用SqlSessionTemplate,它是线程安全的,替代原生的SqlSession。B.需要将SqlSessionFactory交给Spring的IoC容器管理。C.Mapper接口可以通过@Autowired直接注入到Service层使用。D.事务管理可以交由Spring的声明式事务(@Transactional)统一管理。答案:ABD解析:选项A正确,SqlSessionTemplate是MyBatis-Spring整合包提供的核心类,它实现了SqlSession接口,并且是线程安全的,管理了SqlSession的生命周期。选项B正确,SqlSessionFactory是创建SqlSession的工厂,需要在Spring配置中定义。选项D正确,整合后可以利用Spring强大的声明式事务管理,无需在MyBatis层手动处理事务。选项C不准确,Mapper接口本身不能直接被@Autowired,需要先通过@MapperScan扫描或<mybatis:scan/>等方式,让Spring为这些接口生成代理对象并注册为Bean,然后才能被注入。仅仅有接口定义,Spring无法知道如何实现它。关于MyBatis的日志输出,以下哪些说法是正确的?()A.MyBatis内置了日志工厂,会自动查找可用的日志实现(如SLF4J,Log4j2)。B.可以在核心配置文件的<settings>中通过logImpl指定具体的日志实现。C.只能输出执行的SQL语句,无法输出参数和结果集信息。D.日志级别需要设置为DEBUG或更低级别(如TRACE)才能看到详细的SQL日志。答案:ABD解析:选项A正确,MyBatis的日志模块提供了与多种常用日志框架(SLF4J,ApacheCommonsLogging,Log4j2,JDKlogging等)的桥接。选项B正确,通过<settingname="logImpl"value="SLF4J"/>可以指定具体的日志实现。选项D正确,要查看SQL执行详情(包括参数和结果),需要将对应Mapper接口或命名空间的日志级别设为DEBUG或TRACE。选项C错误,在DEBUG级别下,MyBatis可以输出完整的SQL语句(包含替换参数后的形式)、执行的参数以及返回的结果集行数等信息。使用MyBatis进行分页查询时,可以考虑以下哪些方案?()A.在SQL语句中使用数据库特定的分页关键字(如MySQL的LIMIT)。B.使用MyBatis内置的RowBounds对象进行逻辑分页(内存分页)。C.使用第三方分页插件,如PageHelper。D.在业务层手动计算分页参数并传递给SQL。答案:ABCD解析:选项A是最原始但最直接有效的方式,编写包含分页参数(如limit{offset},{size})的SQL。选项B,RowBounds是MyBatis提供的逻辑分页对象,它会在查询出所有结果后,在内存中进行截取,数据量大时性能很差,不推荐在生产环境中对大数据集使用。选项C,PageHelper是国内非常流行的MyBatis分页插件,它通过拦截器机制,能自动、透明地改写SQL语句实现物理分页,使用方便。选项D,这是实现选项A方案时,在业务层需要做的准备工作,即计算出正确的offset和pageSize。这四种方式在实践中都有应用,其中A、C(基于A)是推荐的高性能方案。三、判断题(共10题,每题1分,共10分)MyBatis是一个全自动的ORM框架,可以自动生成所有SQL语句。答案:错误解析:MyBatis是一个“半自动”的ORM(对象关系映射)框架。与Hibernate等全自动框架不同,MyBatis需要开发者自己编写SQL语句和结果映射规则。它提供了强大的映射和动态SQL功能,但将SQL的控制权交给了开发者,这使得SQL优化更加灵活直接。SqlSessionFactoryBuilder的最佳作用域是方法作用域,即每次需要时创建一个新的实例。答案:正确解析:SqlSessionFactoryBuilder的作用就是通过XML配置文件或Java代码来构建SqlSessionFactory对象。一旦创建出SqlSessionFactory,这个构建器就完成了它的使命,可以被丢弃。因此,它不需要也不应该被长期持有,其最佳作用域就是方法作用域(局部变量)。在MyBatis的Mapper接口中,方法可以重载。答案:错误解析:MyBatis的Mapper接口方法不能重载。因为MyBatis是通过“接口全限定名+方法名”作为唯一标识来查找对应的SQL语句的(在XML中是namespace.id)。如果存在重载方法,方法名相同,MyBatis将无法确定应该执行哪一条SQL语句,会导致绑定失败。动态SQL标签<set>在更新操作中会自动去除末尾多余的逗号。答案:正确解析:<set>标签会动态地在生成的SQL语句前插入SET关键字,并且会智能地剔除赋值语句末尾多余的逗号。例如,当<if>条件都不成立时,<set>标签内没有内容,则不会生成SET子句;如果最后一个<if>条件成立的内容后面有逗号,<set>标签会将其去除,保证SQL语法正确。MyBatis的二级缓存默认是开启的。答案:错误解析:MyBatis的二级缓存(SqlSessionFactory级别)默认是关闭的。要启用它,首先需要在核心配置文件的<settings>中显式设置<settingname="cacheEnabled"value="true"/>(该设置默认为true,但通常需要检查),其次还需要在需要使用二级缓存的特定MapperXML文件中添加<cache/>标签。使用${}占位符进行ORDERBY动态排序是安全的。答案:错误解析:使用${}进行ORDERBY动态排序存在SQL注入风险。因为${}是直接的字符串替换,如果排序字段参数来自用户不可控的输入(如前端传递),攻击者可能构造恶意参数(如id;DROPTABLEuser)进行注入。安全的做法是避免使用${},或者在业务层对参数进行严格的白名单校验。ResultMap的<id>标签用于指定主键列的映射,其作用是提高性能,特别是使用嵌套查询或延迟加载时。答案:正确解析:在<resultMap>中,<id>标签用于指定哪个属性是对象的主键标识(对应数据库主键列)。明确指定<id>有助于MyBatis在结果集去重和关联对象嵌套查询时进行优化。例如,在“一对多”映射中,MyBatis需要根据主键来正确地将多个结果行分组到同一个父对象下,<id>的指定对此过程至关重要。在Spring管理的事务中,即使不调用SqlSession的commit()方法,事务也会在方法结束时自动提交。答案:正确解析:当MyBatis与Spring集成,并使用Spring的声明式事务管理(如@Transactional)时,事务的提交和回滚由Spring的PlatformTransactionManager控制。在默认的声明式事务中,如果方法执行成功且没有抛出异常,Spring会在方法返回后自动提交事务。开发者不需要也不应该手动调用SqlSession的commit()或rollback()方法。MyBatis的插件(Interceptor)可以拦截的参数处理、SQL执行、结果集处理等核心组件的执行。答案:正确解析:MyBatis提供了强大的插件(或称拦截器)机制,允许用户使用自定义插件来拦截核心组件的执行。插件可以拦截Executor,ParameterHandler,ResultSetHandler,StatementHandler这四个接口的方法调用。这意味着我们可以对SQL执行过程进行全方位的监控和定制,例如实现分页、性能监控、数据加解密等功能。当实体类的属性名与数据库表的列名不一致时,只能通过编写ResultMap来手动映射。答案:错误解析:除了编写完整的ResultMap,还有更简便的方法。例如:1)在SQL查询中使用列别名(AS),让别名与实体类属性名一致。2)在核心配置文件的<settings>中开启全局的mapUnderscoreToCamelCase(下划线转驼峰)功能,如果数据库列名是user_name,实体类属性是userName,开启此功能后可以自动映射。因此,并非“只能”通过ResultMap。四、简答题(共5题,每题6分,共30分)简述MyBatis中{}和${}的区别,以及在何种场景下必须使用${}。答案:第一,{}是预编译处理,MyBatis会将其替换为?,然后使用PreparedStatement的set方法来安全地赋值,能有效防止SQL注入;${}是字符串替换,会直接将参数值拼接到SQL语句中,存在SQL注入风险。第二,{}会对传入的数据进行类型处理(如字符串自动加引号);${}则原样输出,如果传入字符串,需要手动在SQL中加引号。第三,{}适用于绝大多数场景,尤其是WHERE条件中的值。${}必须使用的场景通常是与SQL语法结构本身相关、而非参数值的情况,例如:动态指定表名(SELECT*FROM${tableName})、动态指定排序字段(ORDERBY${orderByColumn}),但这些场景下需要确保参数值绝对安全,通常来自系统内部定义而非用户输入。简述MyBatis一级缓存和二级缓存的作用域与生命周期。答案:第一,一级缓存(本地缓存)作用域为SqlSession。在同一个SqlSession中执行相同的查询,第二次及之后会直接从缓存中获取数据,而不再访问数据库。其生命周期与SqlSession相同,当SqlSession关闭或执行了增删改操作、手动调用clearCache()时,缓存会被清空。第二,二级缓存作用域为SqlSessionFactory(或Mapper命名空间)。它是跨SqlSession共享的,即一个SqlSession查询的数据,可以被另一个SqlSession访问到。其生命周期与整个应用或SqlSessionFactory相同。二级缓存需要显式配置开启,并且缓存的POJO类必须实现Serializable接口。当执行增删改操作时,对应命名空间的二级缓存会被刷新。列举并简要说明MyBatis动态SQL中<if>,<choose>,<foreach>三个标签的用途。答案:第一,<if>标签:用于条件判断。它有一个test属性,其值为一个OGNL表达式。当表达式结果为true时,<if>标签内的SQL片段会被包含在最终的SQL语句中。常用于构建动态的WHERE或SET部分。第二,<choose>,<when>,<otherwise>标签:用于实现多路选择,类似于Java中的switch-case-default结构。<choose>作为父标签,包含多个<when>和一个可选的<otherwise>。MyBatis会按顺序判断<when>的test条件,执行第一个为true的<when>内的SQL;如果所有<when>都不为true,则执行<otherwise>内的SQL。第三,<foreach>标签:用于遍历集合(如List,Set,数组或Map),常用于构建IN条件或批量操作。主要属性有collection(指定要遍历的集合),item(遍历时的每个元素别名),index(索引或键),open/close(循环开始和结束时拼接的字符串),separator(每次循环之间的分隔符)。简述在MyBatis的MapperXML文件中,parameterType和resultType/resultMap的作用,并说明何时可以省略它们。答案:第一,parameterType:指定传入SQL语句的参数类型。可以是简单类型(int,String),POJO类,Map等。第二,resultType:指定SQL语句返回结果的类型。当结果集的列名与Java对象的属性名能够自动匹配(或通过下划线转驼峰配置匹配)时使用,MyBatis会自动创建该类型的对象并填充数据。第三,resultMap:引用一个自定义的<resultMap>,用于定义更复杂的结果集映射规则,特别是当数据库列名与对象属性名不一致,或者存在关联对象(一对一、一对多)映射时。省略情况:在大多数情况下,这两个属性可以省略。MyBatis具有类型推断能力,可以通过Mapper接口方法的参数类型和返回类型自动确定。但是,当使用resultMap进行复杂映射时,通常需要在<select>等标签中显式指定resultMap属性。说明MyBatis插件(拦截器)的基本工作原理和它可以拦截的四大核心对象。答案:第一,工作原理:MyBatis插件基于JDK动态代理实现。在配置文件中声明插件后,MyBatis在启动时会为需要拦截的目标对象(如Executor)创建一个代理对象。当调用目标对象的方法时,调用会先经过插件的intercept方法,在插件中可以执行自定义逻辑(如增强、修改参数、记录日志等),然后通过Iceed()决定是否继续调用链,最终调用原始目标方法。第二,四大核心对象:1)Executor:执行器,负责增删改查和缓存管理,是拦截最核心的对象,可用于分页、缓存管理。2)ParameterHandler:参数处理器,负责将用户传入的参数转换为JDBCStatement所需的参数,可用于参数加解密。3)ResultSetHandler:结果集处理器,负责将JDBC返回的ResultSet转换为Java对象列表,可用于结果集加工。4)StatementHandler:语句处理器,负责创建Statement对象、设置参数、执行SQL,是SQL执行最底层的对象,可用于SQL重写、性能监控。五、论述题(共3题,每题10分,共30分)论述MyBatis相比其他ORM框架(如Hibernate)的主要优势和劣势,并结合一个具体的业务场景说明为何会选择MyBatis。答案:MyBatis作为半自动ORM框架,与全自动框架如Hibernate相比,其核心差异在于对SQL的控制权。优势:SQL控制灵活:开发者直接编写和优化SQL,能充分利用数据库特性,编写复杂、高性能的查询。这对于性能要求苛刻、涉及复杂多表关联和计算的场景至关重要。学习曲线平缓:相对于Hibernate的HQL、CriteriaAPI和复杂的缓存机制,MyBatis更接近原生JDBC,概念简单,易于理解和上手。与遗留系统集成友好:对于使用存储过程、特定数据库函数或非标准SQL的遗留系统,MyBatis能更方便地进行映射和调用。动态SQL强大:XML标签提供的动态SQL功能非常直观和强大,能轻松应对多条件组合查询。劣势:开发效率:需要手动编写所有SQL和结果映射,在简单的CRUD场景下,开发效率低于Hibernate等能自动生成SQL的框架。数据库移植性:由于SQL是手写的,如果涉及数据库特定语法,更换数据库时需要修改大量SQL语句,移植性较差。全表映射:Hibernate的对象化程度更高,而MyBatis更偏向于数据访问层,在复杂的对象关系网络映射上,配置可能相对繁琐。业务场景选择:以一个电商平台的商品搜索和报表系统为例。这个场景的特点是:查询条件极其复杂(价格、品牌、分类、属性、关键词等动态组合),查询性能要求高(响应时间快),并且需要生成复杂的销售统计报表(涉及大量聚合函数和子查询)。选择MyBatis的原因:在这个场景下,SQL的优化是性能的关键。使用MyBatis,开发团队可以精确地编写每一条查询SQL,根据数据分布和索引情况,灵活地使用JOIN、子查询、窗口函数等数据库高级特性,甚至为了极致性能而使用一些数据库特定的优化提示。复杂的动态查询条件可以通过MyBatis的动态SQL标签优雅地构建。报表查询往往是一次性、复杂的,不需要对象状态的持久化管理,MyBatis直接映射到DTO或Map的能力非常合适。虽然初期SQL编写工作量较大,但换来了对系统核心性能瓶颈的完全掌控,这在电商这种高并发、数据量大的系统中是值得的。反之,如果使用Hibernate,复杂的查询可能需要绕过其查询语言,直接使用原生SQL,反而失去了其全自动的优势,且对生成的SQL难以进行精细控制。详细论述MyBatis的ResultMap在解决“N+1查询问题”中的两种策略:嵌套结果映射(联合查询)和嵌套查询映射(分步查询),并比较它们的优缺点。答案:“N+1查询问题”在ORM中常见:查询一个主对象列表(1次查询),然后为了获取每个主对象的关联子对象集合,又发起N次查询(假设有N个主对象)。MyBatis的ResultMap通过<collection>或<association>提供了两种策略来优化此问题。策略一:嵌套结果映射(联合查询,使用resultMap)原理:通过一条复杂的SQL语句(使用JOIN)一次性查询出主对象及其所有关联子对象的所有数据。然后在<resultMap>中使用<collection>标签,通过columnPrefix或列别名区分,将结果集的多行数据正确地映射到一个主对象及其关联的子对象集合中。优点:1.性能高:只有一次数据库往返,减少了网络I/O和数据库连接开销,尤其当N较大时优势明显。

2.数据一致性:所有数据来自同一时间点的快照。缺点:1.SQL复杂:需要编写包含`JOIN`的复杂SQL,当关联层级多时,SQL可能非常庞大且难以维护。

2.结果集冗余:如果是一对多关联,主表数据会在结果集中重复出现,导致数据传输量增大,可能影响性能(尤其是在关联数据很多时)。

3.可能触发笛卡尔积:复杂的多`JOIN`可能导致意想不到的笛卡尔积,使结果集行数爆炸。策略二:嵌套查询映射(分步查询,使用select属性)原理:在<collection>或<association>标签中,不直接映射结果列,而是通过select属性指定另一个查询的id(通常是另一个Mapper方法),并通过column属性将当前结果中的某列值作为参数传递给那个查询。MyBatis会先执行主查询,然后根据主查询的结果,循环执行子查询来填充关联对象。优点:1.SQL简单清晰:每个查询只关注自己的业务逻辑,SQL语句简单易懂,易于复用和维护。

2.避免冗余数据:没有结果集膨胀问题。

3.支持延迟加载:可以与`fetchType="lazy"`结合,实现按需加载关联数据,提升首次查询速度。缺点:1.潜在的N+1问题:如果不开启延迟加载,或者遍历所有主对象时都访问了关联数据,那么实际上会执行1+N次查询,性能可能很差。

2.数据库往返次数多:即使有延迟加载,当需要加载关联数据时,仍然会产生额外的查询请求。比较与选择:数据量小、关联简单:两种方式均可。嵌套结果映射更简单直接。关联层级深、数据量大:需要权衡。如果主对象数量不多(N小),嵌套查询配合延迟加载可能是好选择。如果主对象数量多,且关联数据必须立即使用,嵌套结果映射(联合查询)性能更好,但要警惕结果集冗余和SQL复杂度。MyBatis还提供了@ResultMap和@One/@Many注解在注解配置中实现类似功能,但原理相同。在实际开发中,通常需要根据具体的数据量、查询频率、网络环境等因素进行测试和选择,有时甚至会结合两种方式,或者通过批处理查询来优化嵌套查询的性能。结合实例,论述如何在SpringBoot项目中实现MyBatis的多数据源配置,并说明在事务管理上需要注意的关键点。答案:在复杂的业务系统中,一个应用可能需要连接多个不同的数据库(如主业务库、日志库、报表库等)。SpringBoot结合MyBatis实现多数据源,核心是为每个数据源创建独立的配置组。实现步骤实例:假设我们需要配置primary(主库)和secondary(从库/日志库)两个数据源。配置数据源属性:在application.yml中分别定义两套连接信息。yaml

spring:

datasource:

primary:

jdbc-url:jdbc:mysql://localhost:3306/db_primary

username:root

password:*

driver-class-name:com.mysql.cj.jdbc.Driver

secondary:

jdbc-url:jdbc:mysql://localhost:3307/db_secondary

username:root

password:*

driver-class-name:com.mysql.cj.jdbc.Driver创建主数据源配置类:使用@Configuration,@MapperScan等注解。这里关键是为该数据源创建独立的DataSource,SqlSessionFactory和SqlSessionTemplateBean,并通过@Primary注解指定其中一个为主要数据源(用于未明确指定的自动装配)。java

@Configuration

@MapperScan(basePackages="com.example.mapper.primary",

sqlSessionFactoryRef="primarySqlSessionFactory")

publicclassPrimaryDataSourceConfig{

@Bean(name="primaryDataSource")

@ConfigurationProperties(prefix="spring.datasource.primary")

@Primary//标记为主要数据源

publicDataSourceprimaryDataSource(){

returnDataSourceBuilder.create().build();

}

@Bean(name="primarySqlSessionFactory")

@Primary

publicSqlSessionFactoryprimarySqlSessionFactory(@Qualifier("primaryDataSource")DataSourcedataSource)throwsException{

SqlSessionFactoryBeanbean=newSqlSessionFactoryBean();

bean.setDataSource(dataSource);

bean.setMapperLocations(newPathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*.xml"));

returnbean.getObject();

}

@Bean(name="primarySqlSessionTemplate")

@Primary

publicSqlSessionTemplateprimarySqlSessionTem

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论