MyBatis / JDBC面试常问题

3 阅读2分钟

1.#{} 和 ${} 区别

  1. 本质区别
  • #{}:预编译、占位符(PreparedStatement)
  • ${}:字符串拼接、直接替换
  1. 是否防SQL注入
  • #{}:安全,防SQL注入
  • ${}:不安全,会产生注入风险
  1. 处理字符串
  • #{}:自动加单引号
  • ${}:不会加引号,纯文本替换
  1. 使用场景
  • #{}:几乎所有参数都有它(where条件、insert值等)
  • ${}:只能在不能有占位符的地方,比如:
    • 表名
    • 配许字段order by${column}
    • 关键字(asc/desc)

总结

#{}预编译、安全、自动加引号;${}字符串拼接、不安全、只能由来拼表名/排序字段。

2.MyBatis 优缺点

优点

  1. SQL手写可控,优化方便,适合复杂查询
  2. 轻量级,学习成本低,上手快
  3. 半自动ORM,灵活,不屏蔽SQL细节
  4. 与Spring整合友好,生态成熟
  5. 动态SQL方便(if、foreach、choose等)

缺点

  1. SQL写在XML/注解里,维护量大
  2. 数据库移植性差(换库要改SQL)
  3. 简单CRUD也要写SQL,不如JPA省事
  4. 大型项目XML多,管理麻烦

总结

灵活可控、适合复杂业务、但移植差、简单操作繁琐。

3.MyBatis 一级缓存、二级缓存

一级缓存

  • 默认开启,不能关闭
  • Sqlsession级别(同一个会话内有效)
  • 同参数、同SQL、同会话、查询直接走缓存
  • 发生增删改会自动清空缓存

二级缓存

  • 默认关闭,需要手动开启
  • Mapper级别(跨会话,同一个Mapper namespace共享)
  • 多个SQL Session可以共用
  • 同样:增删改会清空二级缓存
  • 实体类需要实现序列化接口

总结

一级缓存是会话级,默认开;二级缓存是Mapper级,手动开,跨会话共享。

4.MyBatis 怎么处理多表查询

  1. 手写关联SQL+结果映射
  • 直接写join多表查询
  • 在里用: :一对一 :一对多
<resultMap id="userMap" type="User"> 
    <id column="id" property="id"/>
    <!-- 一对一:用户 → 身份证 --> 
    <association property="idCard" javaType="IdCard"> 
        <result column="card_no" property="cardNo"/> 
    </association> 
    <!-- 一对多:用户 → 多个订单 --> 
    <collection property="orderList" ofType="Order">
        <result column="order_no" property="orderNo"/> 
    </collection> 
        </resultMap>
  1. 分布查询(懒加载)
  • 先查主表,再根据外键查子表
  • 配置fetchType="lazy"实现懒加载
  • 好处:SQL简单,可按需加载

总结

多表查询要么写join配合association/coolection,要么分步骤查询懒加载