Mybatis面试题整理
发现很多公司都要求得会Mybatis,然后就整理些面试题来复习复习。
1.#{}和${}的区别是什么?
在Mybatis中,有#{}和${}两种占位符
- #{} 解析传递进来的参数数据
- ${}对传递进来的参数原样拼接在SQL中
- #{} 是预编译处理,${}是字符串替换。
- 使⽤#{}可以有效的防⽌SQL注⼊,提⾼系统安全性。
2.当实体类中的属性名和表中的字段名不⼀样 ,怎么办 ?
第一种:在查询的sql语句中给字段起和属性名一致的别名
<select id=”test1” parametertype=”int” resultetype=”com.demo.entity.Order”>
select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};
</select>
第二种:通过映射将字段名和属性名对应起来
<select id="test2" parameterType="int" resultMap="testresultmap">
select * from orders where order_id=#{id}
</select>
<resultMap type=”com.demo.entity.Order” id=”testresultmap”>
<!–⽤id属性来映射主键字段–>
<id property=”id” column=”order_id”>
<!–⽤result属性来映射⾮主键字段,property为实体类属性名,column为数据表中的属性–>
<result property = “orderno” column =”order_no”/>
<result property=”price” column=”order_price” />
</reslutMap>
3.如何获取自动生成的(主)键值?
就比如:user对象插⼊到数据库后,新记录的主键要通过user对象返回,通过user获取主键值。
思路:通过LAST_INSERT_ID()获取刚插⼊记录的⾃增主键值,在insert语句执⾏后,执⾏select
LAST_INSERT_ID()就可以获取⾃增主键。
在mysql数据库中实现:
<insert id="insertUser" parameterType="com.demo.entity.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
select LAST_INSERT_ID()
</selectKey>
INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
4.在mapper中如何传递多个参数?
第⼀种:使⽤占位符的思想
- 在映射文件中使用#{0},#{1}代表传递进来的第几个参数
//对应的xml,#{0}代表接收的是dao层中的第⼀个参数,#{1}代表dao层中第⼆参数,更多参数以此类推
<select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1}
</select>
- 使⽤@param注解:来命名参数
public interface usermapper {
user selectuser(@param(“username”) string username,
@param(“hashedpassword”) string hashedpassword);
}
<select id=”selectuser” resulttype=”user”>
select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}
</select>
第⼆种:使⽤Map集合作为参数来装载
try{
//映射⽂件的命名空间.SQL⽚段的ID,就可以调⽤对应的映射⽂件中的SQL
/**
* 由于参数超过了两个,⽽⽅法中只有⼀个Object参数收集
* 因此使⽤Map集合来装载参数
*/
Map<String, Object> map = new HashMap();
//两个参数 start end
map.put("start", start);
map.put("end", end);
return sqlSession.selectList("StudentID.pagination", map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e;
}finally{
MybatisUtil.closeSqlSession();
}
<!--分⻚查询-->
<select id="pagination" parameterType="map" resultMap="studentMap">
/*根据key⾃动找到对应Map集合的value*/
select * from students limit #{start},#{end};
</select>
5. Mybatis动态sql是做什么的?都有哪些动态sql?能简述⼀下动态sql的执行原理不?
-
Mybatis动态sql可以让我们在Xml映射⽂件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。
-
Mybatis提供了9种动态sql标签:
trim|where|set|foreach|if|choose|when|otherwise|bind。 -
其执⾏原理为,使⽤OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能
6.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
首先Statement就是命名空间再加上SQL⽚段的ID,如果不配置命名空间的话,相同的id就会被视为同一个,就会覆盖原来的,就行不通,但若设置了命名空间,相同id就不影响了,就可以重复。
7.接口绑定有几种实现方式,分别是怎么实现的?
接口绑定有两种实现方式:
-
⼀种是通过注解绑定,就是在接⼝的⽅法上⾯加上@Select@Update等注解⾥⾯包含Sql语句来绑定
-
另外⼀种就是通过xml⾥⾯写SQL来绑定,在这种情况下,要指定xml映射⽂件⾥⾯的namespace必须为接⼝的全路径名
8.MyBatis与Hibernate有哪些不同?
-
学习成本和开发速度
- 相较于Hibernate,Mybatis学习⻔槛低,简单易学,更容易上手;
- 如果是简单的CRUD的话,选择Hibernate就比较舒服,因为它封装好了基本的sql语句,直接用就好了;
- 但是对于一个大些的项目,语句较复杂时,就得写专门的sql语句,这个时候选择Mybatis就比较好,管理起来也比较方便。
-
开发工作量
它们两都有相应的代码生成工具,可以生成最基本的Dao层方法,对于高级查询,Mybatis需要写sql语句和ResultMap。而Hibernate它的映射机制就使我们就不用太关注sql语句和结果映射,可以把更多精力放在业务上。
-
sql优化方面
- Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。而Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
- Hibernate HQL语句的调优需要将SQL打印出来,而Hibernate的SQL被很多人嫌弃因为太丑了。MyBatis的SQL是自己手动写的所以调整方便。但Hibernate具有自己的日志统计。Mybatis本身不带日志统计,使用Log4j进行日志记录。
-
是否为全自动
- Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
- 而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具
资料参考于
https://mp.weixin.qq.com/s/0_zTBooRV4RTWQa8VOwiWg
https://zhuanlan.zhihu.com/p/101508485