资讯动态

JavaEE期末题库实战:MyBatis与Spring核心考点解析

发布时间:2026/10/14 15:44:12 来源:尧图企业网站定制
简介这份JavaEE期末复习题库面向高校计算机相关专业学生及Java持久层入门者聚焦MyBatis框架的期末备考与知识梳理。题库以章节习题形式覆盖MyBatis删除与更新操作、mapper元素与namespace命名空间、mybatis-config.xml全局配置、ORM框架原理及SqlSessionFactory与SqlSession工作流程等核心考点并针对模糊查询中concat()拼接与#{}参数绑定、SQL注入防范、数据库移植性等易错点设置辨析题。资源包为1个docx文档约41KB内含填空、判断、选择与简答四类题型及参考答案简答题部分完整梳理了MyBatis从读取配置、加载映射到Executor与MappedStatement执行SQL的八步工作原理。目前已有2646人学习下载适合需要系统刷题、快速定位薄弱环节并巩固MyBatis基础概念的学习者使用。1. 从一份 JavaEE 期末题库说起MyBatis 与 Spring 到底考什么期末周前两周某高校实验室里几个同学围着打印出来的复习资料发愁——厚厚一叠 PDF全是 MyBatis、Spring、Spring MVC 的填空、判断、选择、简答题目和答案混在一起翻两页就找不到对应关系。这份 JavaEE 期末复习题库就是在这种场景下被整理出来的它把 MyBatis 框架、动态 SQL、Spring 的 Bean 管理、AOP、Spring MVC 核心注解这些期末高频考点按章节拆开每章配填空、判断、选择、简答四类题型答案直接跟在题目后面方便对照记忆。它适合两类人一是正在准备 JavaEE 相关课程期末考的学生需要快速定位每章重点二是刚接触 SSM 框架、想通过做题反向理解框架运行机制的开发者。题库本身不教你怎么搭项目但它把「MyBatis 的delete元素怎么配」「Spring 的Autowired默认按什么装配」「Spring MVC 的 DispatcherServlet 拦截请求后调用谁」这些容易被忽略的细节用题目形式逼你记住。下面按章节把题库里最值得动手验证的知识点拆开讲顺带补上做题时容易翻车的地方。2. MyBatis 映射文件与全局配置从题库填空到能跑通的 XML2.1delete、update、insert三个元素的参数差异题库第 1 章填空题第一题问「MyBatis 的删除操作在映射文件中是通过配置哪个元素来实现的」答案是delete。这题本身不难但选择题里埋了一个容易错的点删除操作和添加操作一样也需要封装整个实体类——这句话是错的。delete通常只需要传一个主键或条件参数不需要封装完整实体类而insert在需要返回自增主键时反而要配合useGeneratedKeys和keyProperty把主键回写到实体对象里。下面这段 XML 是我在验证题库答案时常用的最小映射文件把增删改查四个元素放在一起对比?xml version1.0 encodingUTF-8 ? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd !-- namespace 必须全局唯一对应 Mapper 接口全限定名 -- mapper namespacecom.example.mapper.UserMapper !-- insertuseGeneratedKeys 让数据库自增主键回写到 user.id -- insert idinsertUser parameterTypecom.example.pojo.User useGeneratedKeystrue keyPropertyid INSERT INTO user(username, password) VALUES(#{username}, #{password}) /insert !-- delete只需传主键不需要封装整个实体类 -- delete iddeleteUser parameterTypeint DELETE FROM user WHERE id #{id} /delete !-- update动态 set 避免最后一个逗号导致语法错误 -- update idupdateUser parameterTypecom.example.pojo.User UPDATE user set if testusername ! nullusername #{username},/if if testpassword ! nullpassword #{password},/if /set WHERE id #{id} /update !-- selectresultMap 处理列名与属性名不一致的情况 -- select idfindUserById parameterTypeint resultMapuserResultMap SELECT id, user_name, user_pwd FROM user WHERE id #{id} /select resultMap iduserResultMap typecom.example.pojo.User id propertyid columnid/ result propertyusername columnuser_name/ result propertypassword columnuser_pwd/ /resultMap /mapper逻辑说明insert的useGeneratedKeystrue告诉 MyBatis 使用 JDBC 的getGeneratedKeys()拿数据库内部生成的主键keyPropertyid指定把主键值塞回User对象的id属性。delete的parameterTypeint说明只传一个整型主键不需要实体类。update里set会自动去掉最后一个多余的逗号如果所有if都不成立set内为空SQL 会变成UPDATE user WHERE id ?直接报语法错误——题库第 3 章填空题第三题考的就是这个点。参数说明namespace必须和 Mapper 接口全限定名一致否则 MyBatis 启动时找不到绑定resultMap的id用于标识主键列result用于普通列映射两者property写 Java 属性名column写数据库列名。2.2 mybatis-config.xml 里真正影响运行的三个配置题库第 1 章填空题第四题问「mybatis-config.xml 中主要内容是获取什么」答案是数据库连接。但实际配置时environments里的dataSource类型选UNPOOLED、POOLED还是JNDI会直接影响连接行为。题库第 2 章填空题第五题考了这三种类型其中POOLED是开发环境最常用的它维护一个连接池避免每次请求都新建物理连接。?xml version1.0 encodingUTF-8 ? !DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//EN http://mybatis.org/dtd/mybatis-3-config.dtd configuration !-- settings 改变运行时行为lazyLoadingEnabled 默认 false -- settings setting namelazyLoadingEnabled valuetrue/ setting namelogImpl valueSTDOUT_LOGGING/ /settings typeAliases !-- 包扫描别名别名不区分大小写注意重复覆盖 -- package namecom.example.pojo/ /typeAliases environments defaultdevelopment environment iddevelopment transactionManager typeJDBC/ !-- POOLED 使用连接池UNPOOLED 每次新建连接 -- dataSource typePOOLED property namedriver valuecom.mysql.cj.jdbc.Driver/ property nameurl valuejdbc:mysql://localhost:3306/test?useSSLfalse/ property nameusername valueroot/ property namepassword value123456/ /dataSource /environment /environments mappers !-- 映射文件需要在全局配置中加载才能执行 -- mapper resourcecom/example/mapper/UserMapper.xml/ /mappers /configuration逻辑说明settings里lazyLoadingEnabled默认是false题库第 2 章选择题第五题说它「默认开启」是错的。typeAliases用package批量注册别名时如果两个包下有同名类后扫描的会覆盖先扫描的这就是题库判断题里说的「重复定义覆盖问题」。mappers里用resource加载 XML路径是相对于类路径的写错一个斜杠就会报IOException。参数说明transactionManager的typeJDBC表示用 JDBC 的事务提交和回滚dataSource的type可选UNPOOLED、POOLED、JNDI本地开发用POOLED容器环境用JNDI。2.3 模糊查询里#{}和${}的安全边界题库第 1 章选择题第三题考模糊查询拼接选项里说「使用${}无法防止 SQL 注入」是对的说「使用concat()函数也无法防止 SQL 注入」是错的——concat()配合#{}可以防注入但会牺牲数据库移植性。实际写模糊查询时我一般用concat(%, #{keyword}, %)而不是%${keyword}%。!-- 安全写法concat #{}预编译参数防注入 -- select idfindByKeyword resultTypecom.example.pojo.User SELECT * FROM user WHERE username LIKE concat(%, #{keyword}, %) /select !-- 危险写法${} 直接拼接存在 SQL 注入风险 -- select idfindByKeywordUnsafe resultTypecom.example.pojo.User SELECT * FROM user WHERE username LIKE %${keyword}% /select逻辑说明#{}在底层会生成PreparedStatement的?占位符参数值经过 JDBC 驱动转义不会改变 SQL 结构${}是字符串替换直接把用户输入拼进 SQL输入 OR 11就能绕过条件。concat()是 MySQL 函数换成 Oracle 就得用||所以题库说它「导致数据库移植性变差」是对的。参数说明resultType用于列名和属性名一致时自动映射resultMap用于不一致时手动映射两者不能同时出现在一个select里——题库第 2 章选择题第三题说「返回时可以同时使用 resultType 和 resultMap」是错的。3. 动态 SQL 与 Spring Bean 装配题库里那些「看起来对」的判断题3.1where、set、foreach的组合用法题库第 3 章简答题要求列出动态 SQL 常用元素答案是if、choose、where、trim、set、foreach。其中where和set最容易在判断题里设陷阱where会自动去掉第一个多余的AND或ORset会自动去掉最后一个多余的逗号但两者都不能处理「所有条件都为空」的情况。select idfindByCondition resultTypecom.example.pojo.User SELECT * FROM user where if testusername ! null and username ! AND username LIKE concat(%, #{username}, %) /if if testminId ! null AND id gt; #{minId} /if /where /select update idupdateSelective parameterTypecom.example.pojo.User UPDATE user set if testusername ! nullusername #{username},/if if testpassword ! nullpassword #{password},/if /set WHERE id #{id} /update delete iddeleteBatch DELETE FROM user WHERE id IN foreach collectionlist itemid open( separator, close) #{id} /foreach /delete逻辑说明where只在至少一个if成立时才插入WHERE关键字并去掉开头多余的AND如果所有if都不成立SQL 变成SELECT * FROM user不会报错。set在至少一个if成立时插入SET并去掉末尾逗号如果全为空SQL 变成UPDATE user WHERE id ?直接语法错误——题库第 3 章判断题第二题考的就是这个。foreach的collectionlist对应传入的List参数item是循环变量名open、separator、close控制拼接格式。参数说明foreach的collection属性值取决于传入参数类型——传List写list传数组写array传Map写 Map 的键名index在 List 中表示下标在 Map 中表示键。3.2 Spring 依赖注入setter 注入和构造注入的取舍题库第 6 章简答题问 Spring 依赖注入的两种实现方式答案是属性 setter 方法注入和构造方法注入。实际项目里如果依赖是必须的且不可变用构造注入如果依赖可选或需要重新配置用 setter 注入。题库第 6 章判断题第一题说「基于构造方法的依赖注入通过调用带参数的构造方法来实现」是对的但选择题第一题里说「ApplicationContext 不仅包含 BeanFactory 所有功能还添加了国际化、资源访问、事件传播支持」也是对的——这两题经常被混淆。!-- setter 注入先调无参构造再调 setter -- bean iduserService classcom.example.service.UserServiceImpl property nameuserDao refuserDao/ /bean !-- 构造注入调带参构造每个参数代表一个依赖 -- bean idorderService classcom.example.service.OrderServiceImpl constructor-arg index0 refuserDao/ constructor-arg index1 value100/ /bean !-- 注解装配Autowired 默认按类型配合 Qualifier 按名称 -- context:component-scan base-packagecom.example/逻辑说明property对应 setter 注入要求 Bean 有无参构造和对应 setterconstructor-arg对应构造注入index指定参数位置ref引用其他 Beanvalue传基本类型。注解方式下Autowired默认按类型装配如果同类型有多个 Bean需要Qualifier(beanName)指定名称——题库第 7 章选择题第四题说Autowired「默认按照 Bean 的名称进行装配」是错的。参数说明Repository标注 DAO 层Service标注 Service 层Controller标注控制层三者功能与Component相同只是语义更明确。Component可以作用在任何层次但题库第 7 章判断题第一题说它「只需标注在相应方法上」是错的——它标注在类上。3.3 Bean 作用域singleton 和 prototype 的生命周期差异题库第 7 章填空题第四题考 prototype 作用域答案是「Spring 只负责创建创建后交给客户端代码管理不再跟踪生命周期」。这和 singleton 正好相反singleton 在容器启动时创建或第一次请求时创建容器关闭时销毁prototype 每次请求都新建容器不负责销毁。Component Scope(prototype) // 每次 getBean 都返回新实例 public class PrototypeBean { public PrototypeBean() { System.out.println(PrototypeBean 构造 this.hashCode()); } } Component Scope(singleton) // 默认作用域容器内唯一实例 public class SingletonBean { public SingletonBean() { System.out.println(SingletonBean 构造 this.hashCode()); } }逻辑说明Scope(prototype)的 Bean 在每次applicationContext.getBean()时都调用构造方法打印不同 hashcodeScope(singleton)只在第一次 getBean 时构造后续返回同一实例。题库第 7 章判断题第三题说「每次客户端请求 singleton 作用域的 Bean 时Spring 容器都会创建一个新的实例」是错的第四题说「prototype 定义的 Bean 在容器中将只有一个实例」也是错的。参数说明Spring 4.3 中 Bean 作用域有singleton、prototype、request、session、application、websocket题库第 7 章选择题第三题问「哪个不属于 Spring 4.3 版本中的作用域」答案是response——它不在标准作用域列表里。4. Spring AOP 与 Spring MVC从代理方式到 DispatcherServlet 执行链4.1 JDK 动态代理和 CGLIB 代理的选用条件题库第 8 章判断题第四题说「Spring 中的 AOP 代理默认就是使用 CGLIB 代理」是错的——Spring AOP 默认规则是如果目标类实现了接口用 JDK 动态代理如果没有实现接口用 CGLIB 代理。Spring Boot 2.x 之后默认改为 CGLIB但题库对应的是传统 Spring 配置所以判断题答案是错。// JDK 动态代理目标类必须实现接口 public class JdkProxyFactory implements InvocationHandler { private Object target; public JdkProxyFactory(Object target) { this.target target; } public Object getProxy() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), // 必须传接口 this); } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(前置增强); Object result method.invoke(target, args); System.out.println(后置增强); return result; } }逻辑说明Proxy.newProxyInstance的第二个参数必须是接口数组如果目标类没有实现任何接口会抛IllegalArgumentException。CGLIB 代理通过继承目标类生成子类所以不能代理final类或final方法。题库第 8 章选择题第四题说「CGLIB 代理的使用非常简单但它还有一定局限性——使用动态代理的对象必须实现一个或多个接口」是错的那是 JDK 动态代理的局限性。参数说明InvocationHandler.invoke的proxy是代理对象method是目标方法args是方法参数method.invoke(target, args)反射调用目标方法。4.2 AspectJ 注解与通知执行顺序题库第 8 章简答题要求列举 Spring AOP 注解答案是Aspect、Pointcut、Before、After、Around、AfterReturning、AfterThrowing。其中After对应最终通知不管是否异常都执行AfterReturning只在正常返回时执行AfterThrowing只在抛异常时执行。Aspect Component public class LogAspect { Pointcut(execution(* com.example.service.*.*(..))) public void servicePointcut() {} Before(servicePointcut()) public void before(JoinPoint jp) { System.out.println(前置 jp.getSignature().getName()); } AfterReturning(pointcut servicePointcut(), returning result) public void afterReturning(Object result) { System.out.println(返回通知结果 result); } AfterThrowing(pointcut servicePointcut(), throwing e) public void afterThrowing(Exception e) { System.out.println(异常通知 e.getMessage()); } After(servicePointcut()) public void after() { System.out.println(最终通知总是执行); } }逻辑说明Pointcut定义切入点表达式execution(* com.example.service.*.*(..))表示service包下所有类的所有方法。Before在目标方法前执行AfterReturning在正常返回后执行AfterThrowing在抛异常后执行After无论是否异常都执行。题库第 8 章判断题第二题说「After用于定义最终 final 通知不管是否异常都执行」是对的。参数说明JoinPoint可以获取方法签名、参数等信息returning属性指定接收返回值的参数名throwing属性指定接收异常的参数名名字必须和方法参数名一致。4.3 Spring MVC 的 DispatcherServlet 执行链题库第 10 章简答题要求简述 Spring MVC 工作流程答案从「用户发送请求被 DispatcherServlet 拦截」开始到「前端控制器向用户响应结果」结束共十步。其中最容易在选择题里出错的是HandlerAdapter 调用 Handler 后返回的是ModelAndView不是直接返回给 ViewResolver——题库第 10 章判断题第一题说「HandlerAdapter 将 ModelAndView 对象返回给 ViewReslover」是错的它返回给 DispatcherServlet。!-- web.xml 中配置 DispatcherServlet -- servlet servlet-namespringmvc/servlet-name servlet-class org.springframework.web.servlet.DispatcherServlet /servlet-class !-- init-param 指定配置文件位置不配则默认找 /WEB-INF/[servlet-name]-servlet.xml -- init-param param-namecontextConfigLocation/param-name param-valueclasspath:springmvc-config.xml/param-value /init-param !-- load-on-startup 为 1 表示容器启动时立即加载 -- load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namespringmvc/servlet-name url-pattern//url-pattern /servlet-mapping逻辑说明init-param不配置时DispatcherServlet 默认去/WEB-INF/下找[servlet-name]-servlet.xmlload-on-startup为 1 表示容器启动时立即加载 Servlet不配置则第一次请求时才加载——题库第 11 章填空题第五题考的就是这个。url-pattern//url-pattern拦截所有请求但不包括.jsp。参数说明contextConfigLocation指定 Spring MVC 配置文件路径classpath:前缀表示从类路径查找load-on-startup的值越小优先级越高写 1 即可。4.4 RequestMapping 和 GetMapping 的映射规则题库第 11 章判断题第三题说「RequestMapping(method RequestMethod.GET)可以缩写为GetMapping」是对的。RequestMapping的method属性不是必须的不写则接受所有 HTTP 方法GetMapping、PostMapping是组合注解分别等价于RequestMapping(method RequestMethod.GET)和RequestMapping(method RequestMethod.POST)。Controller RequestMapping(/user) public class UserController { // 等价于 RequestMapping(value/find, methodRequestMethod.GET) GetMapping(/find) ResponseBody public User findUser(RequestParam(id) int id) { return userService.findUserById(id); } // 返回 String 时默认视为逻辑视图名 GetMapping(/list) public String list(Model model) { model.addAttribute(users, userService.findAll()); return userList; // 视图解析器拼接前后缀 } }逻辑说明ResponseBody表示返回值直接写入 HTTP 响应体不经过视图解析器不加则返回的 String 被当作逻辑视图名由InternalResourceViewResolver拼接前缀和后缀。RequestParam(id)绑定请求参数id到方法参数参数名不一致时必须写value。参数说明RequestMapping的value指定路径method指定 HTTP 方法params限定请求参数headers限定请求头GetMapping只接受 GET 请求PostMapping只接受 POST 请求。5. 题库刷完之后怎么用一套题把 SSM 串起来5.1 用错题反查配置从判断题定位 XML 写错的地方题库里的判断题和选择题错的那一项往往对应一个真实的配置错误。比如第 2 章判断题第四题「映射文件中可以包含多个 id 值相同的resultMap元素」是错的——MyBatis 启动时如果发现同一个 namespace 下有两个相同 id 的resultMap会直接抛IllegalArgumentException。再比如第 3 章判断题第四题「if的 test 属性判断成立后跳过其他if元素」是错的——if是独立判断不会跳过后续if只有choose才会在when成立后跳过其他分支。我一般会这样用题库先按章节做一遍把错题对应的知识点在 XML 或 Java 代码里复现一次。比如错了set全空导致 SQL 语法错误就故意写一个所有if都不成立的 update看控制台打印的 SQL 长什么样。MyBatis 的logImpl配成STDOUT_LOGGING后每次执行都会打印完整 SQL 和参数比对着题库答案猜要快得多。!-- 开启 SQL 日志方便对照题库验证 -- settings setting namelogImpl valueSTDOUT_LOGGING/ /settings逻辑说明STDOUT_LOGGING把 MyBatis 执行的 SQL、参数、返回行数打到控制台做题库时可以直接看到where有没有去掉AND、set有没有去掉逗号、foreach拼接后的IN列表长什么样。参数说明logImpl可选SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING本地调试用STDOUT_LOGGING最省事。5.2 简答题当口述题用「输入-处理-输出」三段式复述题库每章最后都有一道简答题比如「请简要介绍 MyBatis 的工作原理」「请简述 Spring MVC 框架的工作执行流程」。这些题如果只背答案考试时容易漏步骤我习惯用「输入-处理-输出」三段式复述MyBatis 的输入是mybatis-config.xml和Mapper.xml处理是SqlSessionFactory→SqlSession→Executor→MappedStatement输出是封装后的结果对象。Spring MVC 的输入是浏览器请求处理是DispatcherServlet→HandlerMapping→HandlerAdapter→Controller→ViewResolver输出是渲染后的视图。下面这张表是我整理题库简答题时用的对照表把每章核心流程的输入、处理、输出拆开章节输入处理链输出MyBatis 工作原理mybatis-config.xml Mapper.xmlSqlSessionFactory → SqlSession → Executor → MappedStatement封装后的 POJOSpring 依赖注入XML 配置或注解BeanFactory 读取配置 → 反射调用构造/setter装配完成的 BeanSpring AOP目标类 切入点表达式代理工厂 → JDK/CGLIB 代理 → 通知链增强后的代理对象Spring MVC 流程浏览器 HTTP 请求DispatcherServlet → HandlerMapping → HandlerAdapter → Controller → ViewResolver渲染后的视图逻辑说明这张表不是题库原文是我把每章简答题答案按「输入-处理-输出」重新拆了一遍。考试时如果记不住完整步骤先想输入是什么、输出是什么中间的处理链按框架的核心组件顺序推比死记硬背十步流程更稳。参数说明MyBatis 的处理链里Executor是核心接口MappedStatement封装 SQL 和映射信息Spring MVC 的处理链里HandlerMapping负责 URL 到 Controller 的映射HandlerAdapter负责调用 Controller 方法。5.3 从题库到项目把每章填空题变成一次动手验证题库第 1 章填空题考delete、namespace、concat()、数据库连接、MyBatis第 2 章考resultMap、id、result、refid、BEFORE/AFTER、POOLED第 3 章考bind的name、foreach的collection、set全空报错、trim的prefix、SET和逗号。这些填空题的答案每一个都可以在本地用最小配置跑一遍。我自己的习惯是每做完一章填空题就在本地建一个对应的 Mapper XML 和测试类把填空答案填进去跑一次单元测试。比如第 3 章填空题第一题考bind的name属性我就写一个模糊查询用bind定义一个pattern变量然后在 SQL 里引用#{pattern}select idfindByBind resultTypecom.example.pojo.User bind namepattern value% keyword %/ SELECT * FROM user WHERE username LIKE #{pattern} /select逻辑说明bind的name属性定义变量名value属性写 OGNL 表达式% keyword %把传入的keyword拼成模糊查询模式。这样 SQL 里直接用#{pattern}既避免${}注入又不用依赖concat()函数数据库移植性更好。参数说明bind的value里keyword是方法参数名如果参数是 POJO 属性写#{user.username}对应的 OGNL 路径bind定义的变量只在当前select内有效。从那以后我每次刷题库都会把错题对应的配置在本地跑一遍看到控制台打印的 SQL 和预期一致才放过。希望这份题库和上面的验证思路能帮你在期末前把 SSM 的配置细节真正过一遍。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑