Mybatis面试常问的知识

简介: Mybatis面试常问的知识<3>获取自动生成主键?实体属性名与表字段不一样?不同xml文件的id是否可以重复?mybatis的缓存?#{},${}区别?指定Executor执行器?延迟加载?绑定

如何获取自动生成的(主)键值?

对于支持主键自增的数据库(MySQL),配置文件设置 usegeneratedkeys 为 true

如何获取生成的主键?

对于支持主键自增的数据库(MySQL)
<insert id="insertUser" useGeneratedKeys="true" keyProperty="userId" >
insert into user(user_name, user_password, create_time) values(#{userName}, #{userPassword} , #{createTime, jdbcType=TIMESTAMP})
</insert>

​ parameterType 可以不写,Mybatis可以推断出传入的数据类型。如果想要访问主键,那么应当parameterType 应当是java实体或者Map。这样数据在插入之后 可以通过ava实体 或者Map 来获取主键值。通过 getUserId获取主键

不支持主键自增的数据库(Oracle)

对于像Oracle这样的数据,没有提供主键自增的功能,而是使用序列的方式获取自增主键。
可以使用<selectKey>标签来获取主键的值,这种方式不仅适用于不提供主键自增功能的数据库,也适用于提供主键自增功能的数据库

<selectKey>一般的用法

<selectKey keyColumn="id" resultType="long" keyProperty="id" order="BEFORE"></selectKey>

属性描述

  1. keyProperty selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列, 也可以是逗号分隔的属性名称列表。
  2. keyColmn 匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
  3. resultType 结果的类型,MyBatis 通常可以推算出来。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性 的 Object 或一个 Map。
  4. order 值可为BEFORE 或 AFTER。如果是 BEFORE,那么它会先执行selectKey设置 keyProperty 然后执行插入语句。如果为AFTER则相反。
  5. statementType 使用何种语句类型,默认PREPARED。 有STATEMENT,PREPARED 和 CALLABLE 语句的映射类型。
<insert id="insertUser" >
    <selectKey keyColumn="id" resultType="long" keyProperty="userId" order="BEFORE">
        SELECT USER_ID.nextval as id from dual
    </selectKey>
    insert into user( user_id,user_name, user_password, create_time) values(#{userId},#{userName}, #{userPassword} , #{createTime, jdbcType=TIMESTAMP})
</insert>

​ 此时会将Oracle生成的主键值赋予userId变量。这个userId 就是USER对象的属性,这样就可以将生成的主键值返回了。如果仅仅是在insert语句中使用但是不返回,此时 keyProperty=“任意自定义变量名”,resultType 可以不写。Oracle 数据库中的值要设置为 BEFORE ,这是因为 Oracle中需要先从序列获取值,然后将值作为主键插入到数据库中。

如果Mysql 使用selectKey的方式获取主键,需要注意下面两点:

​ order : AFTER

​ 获取递增主键值 :SELECT LAST_INSERT_ID()

当实体类中的属性名和表中的字段名不一样 ,怎么办?

第1种: 通过在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

<select id="getOrder" parameterType="int" resultType="com.pojo.Order">
select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};
</select>

第2种: 通过来映射字段名和实体类属性名的一一对应的关系。

<select id="getOrder" parameterType="int" resultMap="orderResultMap">
    select * from orders where order_id=#{id}
</select>
<resultMap type="com.pojo.Order" id="orderResultMap">
  <!–用id属性来映射主键字段–>
  <id property="id" column="order_id">
  <!–用result属性来映射非主键字段,property为实体类属性名,column为数据库表中的属性–>
  <result property ="orderno" column ="order_no"/>
  <result property="price" column="order_price" />
</reslutMap>

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

  1. 不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;
  2. 如果没有配置namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
  3. 原因就是 namespace+id 是作为 Map的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。

讲下 MyBatis 的缓存?

MyBatis 的缓存分为一级缓存和二级缓存,一级缓存放在 session 里面,默认就有,二级缓存放在它的命名空间里,默认是不打开的,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置 \

  1. 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session, 当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储, 不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
  3. 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

#{}和${}的区别是什么?

  1. #{}是预编译处理,${}是字符串替换。
  2. Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
  3. Mybatis 在处理${}时,就是把\${}替换成变量的值。
  4. 使用#{}可以有效的防止 SQL 注入,提高系统安全性。

Mybatis 中如何指定使用哪一种 Executor 执行器?

在 Mybatis 配置文件中,可以指定默认的 ExecutorType 执行器类型,也可以手动给DefaultSqlSessionFactory 的创建 SqlSession 的方法传递 ExecutorType 类型参数。

Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

  1. Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。
  2. 它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。

什么情况下用注解绑定,什么情况下用 xml 绑定?

  1. 当 Sql 语句比较简单时候,用注解绑定;
  2. 当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多;
相关文章
|
7月前
|
缓存 Java 数据库连接
Mybatis缓存相关面试题有多卷
使用 MyBatis 缓存机制需要注意以下几点: 对于频繁更新和变动的数据,不适合使用缓存。 对于数据的一致性要求比较高的场景,不适合使用缓存。 如果配置了二级缓存,需要确保缓存的数据不会影响到其他业务模块的数据。 在使用缓存时,需要注意缓存的命中率和缓存的过期策略,避免缓存过期导致查询性能下降。
109 0
|
7月前
|
Java 关系型数据库 数据库连接
BATJ高频面试249道题:微服务+多线程+分布式+MyBatis +Spring
本文收集整理了各大厂常见面试题N道,你想要的这里都有内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、Spring Boot、Spring Cloud、RabbitMQ、Kafka、Linux 等技术栈,希望大家都能找到适合自己的公司,开开心心的撸代码。
|
2月前
|
SQL Java 数据库连接
面试官问我了解Mybatis吗?我说了解,然后...........
面试官问我了解Mybatis吗?我说了解,然后...........
|
6月前
|
SQL 缓存 Java
MyBatis最经典的20道面试题,你都会了吗?
MyBatis最经典的20道面试题,你都会了吗?
69 0
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
5月前
|
SQL 缓存 Java
【面试官】Mybatis缓存有什么问题吗?
面试官:你说下对MyBatis的理解?面试官:那SqlSession知道吧?面试官:Mybatis的缓存有哪几种?面试官:那Mybatis缓存有什么问题吗?面试官:Mybatis分页插件是怎么
【面试官】Mybatis缓存有什么问题吗?
|
4月前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
7月前
|
SQL 缓存 Java
Mybatis面试题
Mybatis面试题
|
5月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
82 0
|
7月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制