MyBatis面试题

MyBatis面试题总结

#{}和${}的区别是什么
  • ${} 是 Properties ⽂件中的变量占位符,它可以⽤于标签属性值和 sql 内部,属于静态⽂本
    替换。拿着字符串直接拼接。
  • #{} 是sql占位符,MyBatis会将sql中的#{}替换为?号,然后在执行sql前使用PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值。拿着数值放在引号号内部后拼接.

优先使用 #{}。因为 ${} 会导致 sql 注入的问题。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。

Xml 映射⽂件中,除了常⻅的 select|insert|updae|delete 标签之外,还有哪些标签?
  • resultMap SQL查询结果字段与实体属性的映射关系
<!-- 与java对象对应的列不是数据库中表的列名,而是查询后结果集的列名 -->
<resultMap id="BaseResultMap" type="com.online.charge.model.Student">
        <id property="id" column="id" />
        <result column="NAME" property="name" />
        <result column="HOBBY" property="hobby" />
        <result column="MAJOR" property="major" />
</resultMap>
  • 动态sql标签 if,foreach

    <!-- foreach多用于in这样的范围 -->
    <select id="selectIn" resultMap="BaseResultMap">
        select name,hobby 
        from student where id in
        <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>
    
  • 定义常量 <sql>,引用常量<include>

通常⼀个Xml映射文件,都会写一个Dao接口与之对应,请问这个Dao接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?

不能

Dao 接⼝,就是⼈们常说的 Mapper 接⼝,接⼝的全限名通过XML中namespace标签与MyBatis定义的语句相关联。这个类并没有实现类,我们调用的时候,是如何执行SQL的呢? 显然MyBatis为我们实现了,因为接口定义明确,通过JDK的动态代理就可以实现,那动态代理实际做了什么工作?

首先一个namespace下的每⼀个 <select> 、 <insert> 、 <update> 、 <delete> 标签,都会被解析为⼀个 MappedStatement 对象,里面有具体的执行sql。然后当调用接口方法时,接口全限名+方法名确定一个MappedStatement,代理对象拦截接口方法执行MappedStatement中的sql,然后返回结果。

Mybatis 是如何进行分页的?分页插件的原理是什么?

Mybatis 使⽤ RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数limit(startIndex, len)来完成物理分页功能,也可以使用分页插件来完成物理分页。

插件原理:使用Mybatis 提供的插件接口,实现自定义插件,在插件的拦截⽅法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。

简述 Mybatis 的插件运行原理,以及如何编写一个插件
  1. 实现Interceptor 2. 配置文件声明
@Intercepts({
        @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class }) })
public class CustomInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(CustomInterceptor.class);

    @Override
    public Object intercept(final Invocation invocation) throws Throwable {
        // MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        // 可以轻松获取原始语句信息,并作处理
        System.out.println("拦截到了mybatis的BaseExecutor中的方法");
        return invocation.proceed();
    }
    
    @Override
    public Object plugin(final Object target) {
        if (target instanceof BaseExecutor || target instanceof CachingExecutor) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(final Properties properties) {

    }
}
<plugins>
    <plugin interceptor="CustomInterceptor"></plugin>
</plugins>

Mybatis 仅可以编写针对ParameterHandler 、 ResultSetHandler 、 StatementHandler 、 Executor 这 4 种接口的插件,Mybatis 使⽤ JDK 的动态代理,为需要拦截的接⼝⽣成代理对象以实现接⼝⽅法拦截功能,每当执行这 4 种接口对象的方法时,就会进⼊拦截方法,具体就是 InvocationHandler 的invoke() ⽅法,当然,只会拦截那些你指定需要拦截的方法。

Mybatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <!--一对一,一篇博客一个作者-->
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="username" column="author_username"/>
    <result property="password" column="author_password"/>
  </association>
  <!--一对多,一篇博客发表多次-->
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <!--多对多-->
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <!--鉴别器-->
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>
Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis 仅支持association 关联对象和 collection 关联集合对象的延迟加载,association指的就是⼀对⼀,collection 指的就是⼀对多查询。在 Mybatis 配置⽂件中,可以配置是否启⽤延迟加载 lazyLoadingEnabled=true|false

原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName() ,拦截器 invoke() 方法发现 a.getB() 是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName() 方法的调用。这就是延迟加载的基本原理。

为什么说 Mybatis 是半自动ORM 映射⼯具?它与全自动的区别在哪里?

Hibernate 属于全自动ORM 映射工具,使用Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动ORM 映射工具。

Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复

如果配置了namespace那么当然是可以重复的,因为我们的Statement实际上就是namespace+id,如果没有配置namespace的话,那么相同的id就会导致覆盖了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355