Java面试题之Mybatis

Java面试题之Mybatis

一、什么是MyBatis?

  • MyBatis是一个优秀的基于Java的持久层框架,支持自定义SQL,存储过程和高级映射。

  • MyBatis对原有JDBC操作进行了封装,几乎消除了所有JDBC代码,使开发者只需关注 SQL 本身。


二、#{}和${}的区别是什么? 应用场景

#{}是预编译处理,${}是字符串替换。

#{}:
sql语句中; //占位符 == ?
spel注入方式中; //#{user1.name}

${}:
sql语句中; //字符串拼接,不包含引号
properties文件中; //${driver} == com.mysql.jdbc.Driver
jsp页面中; //EL表达式


三、在mapper中如何传递多个参数,都有哪几种?

方法1:顺序传参法

public User selectUser(String name, int deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{0} and dept_id = #{1}
</select>

方法2:@Param注解传参法

public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);

<select id="selectUser" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

方法3:Map传参法

public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

方法4:Java Bean传参法

public User selectUser(Map<String, Object> params);

<select id="selectUser" parameterType="com.test.User" resultMap="UserResultMap">
    select * from user
    where user_name = #{userName} and dept_id = #{deptId}
</select>

四、说出MyBatis动态标签(至少5个)

  • if 标签:如果test为true,则生成标签里的内容;false,则忽略标签里的内容

  • where 标签:如果标签内有返回值,则where留下,并自动消除其后的and,or。如果没有,则where自动消失。

  • set标签:如果set内有返回值,set留下,并自动消除最后的逗号。如果没有,则set会引发SQL错误(所以,set标签后,有必要给一个where语句,比如:where
    1=1)。

  • trim 标签:prefix:当trim元素内包含内容时,给内容增加prefix指定的前缀

  • choose 标签 bind标签 foreach标签


五、parameterType和resultType的区别

  • parameterType : 主要针对于 将信息存入到数据库中
  • resultType : 主要针对于从数据库中提取相应的数据出来

六、在用MyBatis插入时,如何得到数据库自增的主键值?

  • 在mapper.xml中添加属性“useGeneratedKeys”和“keyProperty”,其中keyProperty是Java对象的属性名!
  • Mybatis执行完插入语句后,自动将自增长值赋值给对象ElZEquipmentListReportItem
    的属性id。因此,可通过ElZEquipmentListReportItem 对应的getter方法获取!

七、MyBatis批量删除/添加时,代码实现

   <mapper namespace="cn.itsource.mybatis.batch_options.UserMapper">
       <!--
         select:标签名字:  CRUD的时候对应的名字
         id:这个语句的唯一标识;   【必须和接口的方法名字一样】;
         parameterType:传入参数类型
         resultType:返回值类型
         #{id}:参数的接收
   
         collection=""  遍历集合
         index=""  遍历时候的索引
         item=""   每此遍历得到的对象
         open=""   以什么开始
         close=""  以什么结束
         separator="" 以什么作为分割符
       -->
       <select id="saveBatch" parameterType="list">
           INSERT INTO user (username,password) VALUES
           <foreach collection="list" item="user" separator=",">
               (#{user.username},#{user.password})
           </foreach>
       </select>
    
       <delete id="deleteBatch" parameterType="list">
           delete from user where id in
           <foreach collection="list" item="id" open="(" close=")" separator=",">
               #{id}
           </foreach>
       </delete>
   </mapper>

八、MyBatis动态SQL执行流程和原理

  • 创建StatementHandler

  • 准备Statement包括获得数据库连接、参数设置等

  • 然后是给preparedStatement设置参数,这个和我们jdbc一样的顺序

  • 执行sql (基本也和原生差不多)

  • 其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。


九、JDBC为什么比Mybatis效率快?

  • mybatis需要去映射

十、MyBatis框架中用到了哪些设计模式?(3个)

Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;

 工厂模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;

  单例模式,例如ErrorContext和LogFactory;

 代理模式,Mybatis实现的核心,比如MapperProxy、ConnectionLogger

 适配器模式,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现

十一、描述@Transactional注解

  • @Transactional 可以作用于接口、接口方法、类以及类方法上。
  • 类上:该类的所有 public 方法将都具有该类型的事务属性
  • 方法加上这个注解之后,事务管理就交由Spring来处理。
  • 简单解析:如果有事务,那么加入事务,没有的话新建一个; 串行化最高级隔离级别; 遇到异常回滚。

十二、@Transactional什么情况会事务回滚,注意事项/问题

  • 当程序发生 RuntimeException 和 Error 的这两种异常的时候事务会回滚,但是如果发生了checkedExcetions
    如fileNotfundException 则不会回滚,所以 rollbackFor = Exception.class 这个一定要加!
  • 不要在接口上声明@Transactional ,而要在具体类的方法上使用 @Transactional 注解,否则注解可能无效。
  • 使用了@Transactional的方法,只能是public

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

  • Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
  • 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

十四、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

  • 第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。
  • 第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

十五、什么是数据持久化?

数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。例如,文件的存储、数据的读取等都是数据持久化操作。数据模型可以是任何数据结构或对象的模型、XML、二进制流等。 当我们编写应用程序操作数据库,对表数据进行增删改查的操作的时候就是数据持久化的操作。


十六、使用MyBatis的mapper接口调用时有哪些要求?

  • Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
  • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
  • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
  • Mapper.xml文件中的namespace即是mapper接口的类路径。

十六、Mybatis的一级、二级缓存?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值