1.Mybatis中#{}和${}的区别
#{}时预编译处理,在运行的时候会被替换成?;KaTeX parse error: Expected 'EOF', got '#' at position 12: {}会被替换成字符串 #̲{}有效的防止SQL注入;{}不能防止SQL注入
使用场景不同,当传递的参数时普通参数时,需要使用#{};当传递参数时SQL命令或SQL关键字时,需要使用${},来对SQL中的参数进行直接替换
2.Mybatis的缓存机制
MyBatis中的一级缓存作用域是同一个SqlSession,在同一个SqlSession中两次执行相同的语句,第一次执行完毕后会将查询到的结构放到一级缓存中,第二次执行的时候直接从缓存中取,不用查询数据库,从而提高效率。当一个sqlSession执行结束后该sqlSession中的一级缓存也就不存在了。一级缓存默认开启。
二级缓存是多个SqlSession共享,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递的参数也相同,即最终执行相同的sql语句。第一次执行后会将查询结果存到二级缓存中,第二次执行的时候会从缓存中取,从而提高效率。二级缓存不会默认开启,需要在setting全局参数中配置开启二级缓存
如果二级缓存是开启的,那么查询顺序是:二级缓存-》一级缓存-》数据库
3.Mybatis的延迟加载
4.Mybatis中 Dao接口和XML文件的SQL如何建立关联
(1)首先创建SqlSource和SqlNode
MyBatis会将每个SQL标签封装成SqlSource对象,根据SQL语句的不同,又分成动态SQL和静态SQL
<select id="getUserById" resultType="user">
select * from user
<where>
<if test="uid!=null">
and uid=#{uid}
</if>
</where>
</select>
上面这段sql生成的SqlSource是这样的
(2)创建mappedStatement
MyBatis会为XML中的每个SQL标签都生成MappedStatement对象。包含两个重要的属性: id + sqlSource
创建完的MappedStatement会被放到Configuration中,Configuration是Mybatis中的大管家,基本所有的配置信息都维护在这里。当把所有的SQL信息解析完,Configuration就包含所有的SQL信息。
xml文件解析完,我们就可以通过”全限定名+方法名“找到MappedStatement,然后解析里面的SQL并进行执行
(3)Dao接口代理
@MapperScan注解将包路径下的所有类注册到Spring Bean中,并将他们的beanClass设置为MapperFactoryBean。当我们通过@Autowired注入这个Dao接口时,返回的对象就是MapperFactoryBean这个工厂Bean中getObject()方法对象。这个方法的作用就是,通过JDK动态代理,返回Dao接口的代理对象MapperProxy,当我们通过@Autowired注入Dao接口时,注入的就是这个对象。我们调用Dao接口中的方法时,则会调用到MapperProxy对象的invoke()方法。
(3)执行:
通过statement拿到MapperStatement对象,然后通过执行器Executor去执行具体SQL并返回
5.一对一、一堆多怎么用MyBatis实现
<mapper namespace="com.lcb.mapping.userMapper">
<!--association 一对一关联查询 -->
<select id="getClass" parameterType="int" resultMap="ClassesResultMap">
select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
<!-- 实体类的字段名和数据表的字段名映射 -->
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<!--collection 一对多关联查询 -->
<select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">
select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<collection property="student" ofType="com.lcb.user.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
</mapper>
6.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
如果配置了namespace,不同的Xml映射文件,id是否可以重复;如果没有配置namespace,那么id不可重复
7.Mybatis是如何进行分页,分页插件的原理是什么
Mybatis使用RowBounds进行分页,属于逻辑分页而非物理分页,是在内存中进行分页
分页插件的原理:通过Mybatis提供插件接口,实现自定义插件,拦截器拦截要分页的sql语句,添加dialet(方言)和分页参数,重写sql
8.简述Mybatis的插件运行原理,以及如何编写一个插件
Mybatis使用JDK动态代理机制,为插件生成动态代理对象以实现接口方法的拦截功能。当执行ParameterHandler、ResultSetHandler、StatementHandler、Executor这四种接口对象的方法时,就会进入invocationHandler中的invoke方法,指挥拦截指定的方法。
编写插件:实现Mybatis中的Interceptor接口
重写intercept方法,指定要拦截的接口,在配置文件中配置编写的插件
9.Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联对象的延迟加载。association时一对一,collection是一对多。在Mybatis配置文件中配置 LazyLoadingEabled 的值为true或false
实现原理:当使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截方法。例如:a.get(B).getName(),此时a.get(B)是空,就会执行sql语句,查询B,再a.set(B),最后再执行a.get(B).getName()。
10.Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
1.使用标签,逐一定义数据库列名和属性名的映射关系。
2.使用别名,将列的别名书写为对象的属性名
有了列名和属性名的映射关系,Mybatis通过反射创建对象,同时通过反射给属性逐一赋值并返回
11.Mybatis动态sql有什么用?执行原理?有哪些动态sql?
Mybatis在xml文件中以标签的形式编写sql,执行原理是根据表达式完成逻辑判断并拼接sql的功能。
动态标签有 where if foreach when otherwise
12.Xml映射文件中,除了常见的select|insert|updae|delete标签外,还有哪些标签?
、、、、,加上动态sql的9个标签 trim | where | set | foreach | if | choose | when | otherwise | bind 等,其中 为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。
13.使用MyBatis的mapper接口调用时有哪些要求?
Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
Mapper.xml文件中的namespace即是mapper接口的类路径。
14.模糊查询like语句该怎么写?
1.在Java代码中添加通配符
2.在sql语句中拼接通配符,这样会引起sql注入
15.当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
1.起别名的方式
2.通过resultMap标签实现数据库字段名和属性名对应
16.如何获取自动生成的(主)键值?
xml的方式
<!--添加检查组信息 void add
useGeneratedKeys="true" keyProperty="id"
取出数据库自动生成的主键,放在id属性中-->
<insert id=”add” usegeneratedkeys=”true” keyproperty=”id”>
insert into t_user values(null,#{birthday},#{gender},#{username},#{password},#{remark},#{station},#{telephone})
</insert>
注解的方式
/*添加注解 @Options(useGeneratedKeys = true,keyProperty = "id")*/
@Insert("insert into t_user values(null,#{birthday},#{gender},#{username},#{password},#{remark},#{station},#{telephone})")
@Options(useGeneratedKeys = true,keyProperty = "id")
void add(User user);
17.Mybatis中如何传递多个参数
(1)第一种:
//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(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper):
<select id=”selectuser” resulttype=”user”>
select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}
</select>
(3)第三种:多个参数封装成map
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
Map<String, Object> map = new HashMap();
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();
}
18.MyBatis实现一对一有几种方式?具体怎么操作的?
有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置。
19.Mapper编写有哪几种方式?
1.实现类继承SqlSessionDaoSupport
2.使用SqlSessionFactory
3.使用mapper扫描
20.什么是MyBatis的接口绑定?有哪些实现方式?
在mybatis中任意定义接口,将接口与xml语句绑定,直接调用方法名就可以。
实现方式:
1.使用注解,在接口上面加注解
2.使用xml文件,注意namespace必须为接口的全路径名
21.MyBatis与Hibernate有哪些不同?
1.Mybatis不完全是一个对象映射框架,开发者需要自行编写sql
2.Mybatis可以严格控制语句的执行时间、性能,非常适合关系数据模型不高的软件开发。Mybatis做到数据库无关性
3.Hibernate对象映射能力强,数据库无关性号,对关系模型要求高的软件,可以节省很多代码