mybatis 八股篇
1、#{} 和 ${}的区别
#{} : 预编译 --> 将 sql 中的 #{} 替换为 ? 用 PreparedStatement 的 setString 方法 进行赋值
赋值之后的 参数的值 会带上 双引号
${} : 字符串替换,直接将 sql 语句中的 ${} 替换为 对应的变量值
替换后不会带 双引号
#{} 可以 有效的 防止 sql 注入问题,提高系统的安全性。
解释 :MyBatis的#{}之所以能够预防SQL注入是因为底层使用了PreparedStatement类的setString()方法来设置参数,此方法会获取传递进来的参数的每个字符,然后进行循环对比,如果发现有敏感字符(如:单引号、双引号等),则会在前面加上一个'/'代表转义此符号,让其变为一个普通的字符串,不参与SQL语句的生成,达到防止SQL注入的效果。
${} 字符串替换 , 直接换 不带双引号 其实就是真实传递的值 安全性很低
2、类中实体和表中的字段 不同 如何解决?
1、如果列名和属性名不能匹配上,可以在 sql 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配
例子 :
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>
2、 resultMap 映射字段 id为主键字段 result 为非主键字段
例子 :
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
3 模糊查询 like 语句
1、 Java代码中添加sql 通配符
2、 在 sql 语句中 拼接通配符 会引起 sql 注入问题
4、 mapper 接口 和 mapper.xml 文件
1、 映射文件中的 namespace : 接口的全类限定名
2、 接口方法名 : xml 文件中 stament 中的 id 值
3、 接口方法内的参数 传递给 sql 的参数 parameter
mapper 接口 无 实现类 接口全类限定名 + 方法名 --> 拼接字符串 作为 key 值,唯一定位一个 mapperstament 。 在 mybatis 中,
每一个 crud 标签都会被解析为一个 mapperstament 对象。
mapper接口方法 不能重载~ 因为寻找策略为 : 接口全类限定名 + 方法名
mapper 接口的工作原理 : jdk 动态代理
Mybatis 运行时会使用 JDK 动态代理为 Mapper 接口生成代理对象 proxy,代理对象会拦截接口方法 然后执行 statment 对应的sql 语句 然后将 sql 结果返回
5、Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用<resultMap>标签,逐一定义数据库列名和对象属性名之间的映射关系。
第二种是使用 sql 列的别名功能,将列的别名书写为对象属性名。
有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
6、 如何 获取 自增 主键值?
insert 方法总是返回一个 int 值 ,这个值代表的是插入的行数。
如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中
7、多参如何传 ?
1、#{0 … 1 … 2 … 3}
DAO 层的函数
public UserselectUser(String name,String area);
对应的 xml,#{0}代表接收的是 dao 层中的第一个参数,#{1}代表 dao 层中第二参数,更多参数一致往后加即可。
<select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name = #{0}
anduser_area=#{1}
</select>
2、@param(“”) 注解
public interface UserMapper {
User selectuser(@param(“username”) String
username,@param(“password”) String password);
}
<select id=”selectuser” resulttype=”User”>
select id, username, dpassword
from some_table
where username = #{username}
and xpassword = #{password}
</select>
3、 Map 传值 推荐使用
public interface Mapper {
ArrayList<HashMap> searchByPage(Map param);
}
sql 部分语句省略
<select id="searchByPage" parameterType="Map" resultType="HashMap">
<if test="name!=null">
AND d."name" LIKE '%${name}%'
</if>
<if test="deptId!=null">
AND md."id" = ${deptId}
</if>
<if test="degree!=null">
AND d."degree" = #{degree}
</if>
</select>
8、动态 sql ? 原理 ?
-
Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql
-
9 种动态 sql 标签:trim | where | set | foreach | if | choose
| when | otherwise | bind
执行原理:
- 是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。
9、 Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;
原因就是 namespace+id 是作为 Map<String, MapperStatement>的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。
有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。
10、 Xml 映射文件中,除了常见的 crud标签 和 动态sql 标签 还有哪些标签?
<resultMap>、<parameterMap>、<sql>、<include>、
<selectKey>
<sql>为 sql 片段标签,通过 <include>标签引入 sql 片段
<selectKey>为不支持自增的主键生成策略标签