admin管理员组文章数量:1794759
MyBatis面试题(2022最新版)
MyBatis 1、MyBatis 是什么框架?
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。 Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
2、MyBatis 和 ORM 的区别? 3、MyBatis 为什么是半自动 ORM 映射?Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。
4、MyBatis 框架的应用场景? MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。 5、MyBatis 有哪些优点?优点
1.与JDBC相比,减少了50%以上的代码量。 2.MyBatis是最简单的持久层框架,小巧并且简单易学。 3.提供映射标签,支持对象与数据库的ORM字段关系映射。 4.提供XML标签,支持编写动态SQL语句。 6、MyBatis 有哪些缺点?缺点
1.SQL语句编写工作量较大,对开发人员有一定的SQL语句功底要求。 2.SQL语句依赖于数据库,不能随便更改。 7、MyBatis 和 Hibernate 的区别?首先,Spring Data JPA可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。
JPA默认使用hibernate作为ORM实现,所以,一般使用Spring Data JPA即会使用hibernate。Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
所以,这里说 jap和mybatis的区别也就是 hibernate和mybatis的区别了。
9、MyBatis 有哪几种 SQL 编写形式?三种
如果想要的是动态SQL,那么就加上<script>:
public interface UserMapper { @Select("select * from user ") List<User> AnnotationGetUserList(); @Select("<script>" + "select * from user " + "<if test='id!=null'>" + "where id=#{id}" + "</if>" + "</script>") List<User> AnnotationGetUserById(@Param("id")String id); }3.通过@SelectProvider来声明sql提供类
public interface UserMapper { @SelectProvider(type=SqlProvider.class,method="getUserById") List<User> AnnotationProviderGetUserById(String id); } public class SqlProvider { public String getUserById(String id) { String sql = "select * from user "; if (id!=null) { sql += " where id="+id; } return sql; } } 10、MyBatis 支持哪些传参数的方法?方式一、顺序传递参数
mapper.java文件:
public User selectUser(String name, int deptId);mapper.xml文件:
<select id="selectUser" resultType="com.wyj.entity.po.User"> select * from user where userName = #{0} and deptId = #{1} </select>注意:里面的数字代表你传入参数的顺序,不是特别建议使用这种方法传递参数,特别是参数个数多的时候
方式二、注解@Param传递参数
mapper.java文件:
public User selectUser(@Param("userName") String name, int @Param("deptId") id);mapper.xml文件:
<select id="selectUser" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select>注意:在xml文件中就只能以在@Param注解中声明的参数名称获取参数
方式三、使用Map集合传递参数
mapper.java文件:
public User selectUser(Map<String, Object> params);mapper.xml文件:
<select id="selectUser" parameterType="java.util.Map" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select>方式四、使用JavaBean实体类传递参数
mapper.java文件:
public User selectUser(User user);mapper.xml文件:
<select id="selectUser" parameterType="com.wyj.entity.po.User" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select> 11、MyBatis 的 $ 和 # 传参的区别?区别一: #传过来的数据会自动加上引号,$则不会; 区别二: ${} 容易被sql注入,#{} 安全, 安全问题怎么理解?
#{}:解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。#{} 相当于一个占位符,使用占位符,防止sql注入。 ${}:取出的值会直接拼装在sql中,会有安全问题。 12、MyBatis 可以映射到枚举类吗?Mybatis 可以映射枚举类。
可以,需要自定义对枚举类的类型转换器。例如写一个类为EnumTypeHandler继承BaseTypeHandler<枚举类型>,重写其中的方法,在getNullableResult方法中更具返回结果做响应的转换操作。
13、MyBatis 怎么封装动态 SQL?映射方式
1、当列名和封装查询结果的类的属性名一一对应时:
这时MyBatis 有自动映射功能,将查询的记录封装到resultType 指定的类的对象中去
<mapper namespace="com.hanT.dao.UserDao"> <!--id对应接口中的方法名,resultType为返回结果的类型,要用类的全限定名--> <select id="getUserList" resultType="com.hanT.pojo.User"> select * from mybatis.user </select> </mapper>2、当列名和封装查询结果的类的属性名不对应时: 使用resultMap 标签,在标签中配置属性名和列名的映射关系
<resultMap type="cn.mybatis.pojo.User" id="UserResult"> <result property="username" column="name"/> </resultMap> <select id="findUserById" parameterType="java.lang.Long" resultMap="UserResult"> select id,name,email from t_user where id=#{id} </select> 14、Mybatis trim 标签有什么用?1.<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>
prefix:在trim标签内sql语句加上前缀。
suffix:在trim标签内sql语句加上后缀。
suffixOverrides:指定去除多余的后缀内容,如:suffixOverrides=“,”,去除trim标签内sql语句多余的后缀","。
prefixOverrides:指定去除多余的前缀内容
2.下面是一个往购物车表中插入数据的mybatis语句
<insert id="insert" parameterType="com.tortuousroad.groupon.cart.entity.Cart"> insert into cart <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null"> id, </if> <if test="userId != null"> user_id, </if> <if test="dealId != null"> deal_id, </if> <if test="dealSkuId != null"> deal_sku_id, </if> <if test="count != null"> count, </if> <if test="createTime != null"> create_time, </if> <if test="updateTime != null"> update_time, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null"> #{id,jdbcType=BIGINT}, </if> <if test="userId != null"> #{userId,jdbcType=BIGINT}, </if> <if test="dealId != null"> #{dealId,jdbcType=BIGINT}, </if> <if test="dealSkuId != null"> #{dealSkuId,jdbcType=BIGINT}, </if> <if test="count != null"> #{count,jdbcType=INTEGER}, </if> <if test="createTime != null"> #{createTime,jdbcType=TIMESTAMP}, </if> <if test="updateTime != null"> #{updateTime,jdbcType=TIMESTAMP}, </if> </trim> </insert> 15、MyBatis 怎么实现分页? 1、使用SQL的LIMIT做分页,分页参数可以使用Mybatis提供的Page封装,传给Mapper。 然后使用LIMIT (page-1)*size,size方式查询数据 2、使用PageHelper插件实现 3、使用Mybatis的Interceptor拦截器实现 16、MyBatis 流式查询有什么用?流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。
如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。
流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭。
17、MyBatis 模糊查询 like 语句该怎么写?(1)直接传参法
直接传参法,就是将要查询的关键字keyword,在代码中拼接好要查询的格式,如%keyword%,然后直接作为参数传入mapper.xml的映射文件中。
public void selectBykeyWord(String keyword) { String id = "%" + keyword + "%"; String roleType = "%" + keyword + "%"; String roleName = "%" + keyword + "%"; userDao.selectBykeyWord(id,roleName,roleType); } <select id="selectBykeyWord" parameterType="string" resultType="com.why.mybatis.entity.RoleEntity"> SELECT * FROM t_role WHERE role_name LIKE #{roleName} OR id LIKE #{id} OR role_type LIKE #{roleType} </select>注意:此方法可以完成模糊查询任务,但是不推荐,因为与Java代码耦合了,不利于维护和修改。
(2)mysql的CONCAT()函数
MySQL的CONCAT()函数用于将多个字符串连接成一个字符串,是最重要的mysql函数之一。用法:CONCAT(str1,str2,…)
<select id="selectBykeyWord" parameterType="string" resultType="com.why.mybatis.entity.RoleEntity"> SELECT * FROM t_role WHERE role_name LIKE CONCAT('%',#{keyword},'%') OR id LIKE CONCAT('%',#{keyword},'%') OR role_type LIKE CONCAT('%',#{keyword},'%') </select>注意:执行效果与上面的直接传参一样,但比直接传参法更好,因为与代码解耦了,但是此方法只针对mysql数据库所用,如果换成Oracle数据库则需要修改sql代码,因此此方法不通用,但可以使用。
(3)mybatis的bind元素
mybatis针对这种情况作出了调整,提供了一个bind元素,此元素可以跨越数据库限制,也就是说不管是mysql还是Oracle数据库都可以通用模糊查询。
dao层接口如下:
List<RoleEntity> selectBykeyWord(@Param("keyword") String keyword);mapper文件如下:
<select id="selectBykeyWord" parameterType="string" resultType="com.why.mybatis.entity.RoleEntity"> <!--keyword就是传入的参数,bind相当于是一个参数,这个参数的值就是value拼接出来的值--> <bind name="pattern" value="'%' + keyword + '%'" /> SELECT * FROM t_role WHERE role_name LIKE #{pattern} OR id LIKE #{pattern} OR role_type like #{pattern} </select> 18、MyBatis 配置文件中的 SQL id 是否能重复?可以重复,但是需要映射文件的namespace不同;
19、MyBatis 如何防止 SQL 注入?1、使用#{}来设置参数
2、正则表达式过滤非法字符
20、MyBatis 如何获取自动生成的主键id?1、XML配置文件
<insert id="insert" parameterType="Person" useGeneratedKeys="true" keyProperty="id"> insert into person(name,pswd) values(#{name},#{pswd}) </insert>2、Mapper中的方法
int insert(Person person);注意在调用这个方法时,返回的int值并不是主键,而是插入的记录数。主键id会被赋值到输入的person对象里,自动赋值给person对象的id属性。比如:
Person person = new Person("name","psw"); //num是插入的记录数 int num = PersonMapper.insert(person); //person对象的id属性会变成自生成的id int id = person.getId(); 21、MyBatis 使用了哪些设计模式? Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、 XMLStatementBuilder、 CacheBuilder; 工厂模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory; 单例模式,例如ErrorContext和LogFactory; 代理模式,Mybatis实现的核心,比如MapperProxy、ConnectionLogger, 用的jdk的动态代理;还有executor.loader包使用了cglib或者javassist达到延迟加载的效果; 组合模式,例如SqlNode和各个子类ChooseSqlNode等; 模板方法模式,例如BaseExecutor和SimpleExecutor,还有BaseTypeHandler和所有的子类例如IntegerTypeHandler; 适配器模式,例如Log的Mybatis接口和它对jdbc、log4j等各种日志框架的适配实现; 22、MyBatis 中的缓存机制有啥用?做服务器的进程内部缓存,提高查询效率,降低数据库访问频率。Mybatis有三种缓存,一级缓存、二级缓存、第三方缓存EhCache,一级缓存时默认开启的,作用域时SqlSession。二级缓存默认关闭需要在配置中使用enableCache="true"开启,二级缓存时namespace作用域的。第三方缓存需要引入额外Jar包,并且在配置中开启二级缓存开关,配置第三方缓存的核心类。
二级缓存是SqlSessionFactory的缓存。只要是同一个SqlSessionFactory创建的SqlSession就共享二级缓存的内容,并且可以操作二级缓存.
23、MyBatis 一级缓存和二级缓存的区别?1、作用域不同:
一级缓存的作用域是SqlSession级别的Map,二级缓存是namespace级别的,也叫全局缓存
2、默认配置不同
一级缓存默认开启,二级缓存默认关闭,需要在mybatis.cfg.xml配置文件中开启
<settings> <setting name="cacheEnabled" value="true"/> </settings 24、MyBatis-Plus 是什么框架?Mybatis的增强框架,帮助开发人员更加简化开发。这些框架提供了大部分的简单SQL语句封装的API,提供了分页插件,简化了配置流程。不过只对单表有好的支持,多表关联查询支持差,一般需要手动编写多表的SQL,不过可以原生和增强一起使用。
25、mybatis延迟加载延迟加载:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.
懒加载的配置
● 局部懒加载: 在association标签或者collection标签中,设置fetchType属性的值为lazy
<resultMap id="empAndDeptByStepResultMap" type="Emp"> <id property="eid" column="eid"></id> <result property="empName" column="emp_name"></result> <result property="age" column="age"></result> <result property="sex" column="sex"></result> <result property="email" column="email"></result> <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="did" fetchType="lazy"></association> </resultMap>● 全局懒加载: 在mybatis的核心配置文件中添加
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>版权声明:本文标题:MyBatis面试题(2022最新版) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686992912a126395.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论