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

在这里插入图片描述

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

知识回顾:
上次我们分享了关于mybatis的一些面试题目【Mybatis面试常问的知识<1>MyBatis编程步骤?框架适用场景?Mybatis是如何进行分页的?分页插件的原理是什么? Mybatis的Xml映射文件中,接口绑定等等】【Mybatis面试常问的知识<2>ORM概念?Mybatis和Hibernate区别?全自动半自动区别?mapper文件中如何传递多个参数?模糊查询实现方式?SQL语句预编译?动态SQL?标签?】
接下来我们继续来学习关于mybatis的一些面试题目。

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

对于支持主键自增的数据库(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<String, MappedStatement>的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。

讲下 MyBatis 的缓存?

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

  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 绑定的比较多;

好了,本篇文章【【Mybatis面试常问的知识<3>获取自动生成主键?实体属性名与表字段不一样?不同xml文件的id是否可以重复?mybatis的缓存?#{},${}区别?指定Executor执行器?延迟加载?绑定】】的面试题目就先到这里了,后面继续更新。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值