Mybatis面试题(转)
1.#{}和${}区别
#{}是预编译处理,运行时mybatis会将其转换成?,${}是字符串替换,运行时mybatis会将其换成变量的值;
#{}调用preparedStatement的set方法赋值,可以防止SQL注入,提高系统安全。
2.当实体类中的属性名和表中字段不一样,如何处理?
(1)通过sql语句定义别名,让字段名和属性名相同:
<select id="selectById" parametertype="int" resultetype="com.domain.person"> select person_id id,person_name pname,person_age page from person where person_id = #{id}; </select>
(2)通过resultMap来映射字段名和属性名:
<select id="getPersonById" parametertype="id" resultMap="personResultMap"> select * from person where person_id = #{id} </select> <resultMap type="com.domain.person" id="personResultMap"> <id property="id" column="person_id"/> <result property="pName" column="person_name"/> <result property="pAge" column="person_age"/> </resultMap>
3.通常一个Xml映射文件,都会写一个dao接口与之对应,这个dao接口的工作原理是什么?dao接口中的方法,参数不同时是否可以重载?
dao接口就是mapper接口,接口连同所在包一起的名字即全限名就是映射文件的namespace,接口的方法名就是映射文件中对应的id的值,接口方法中的参数就是对应id标签中的传入sql的参数。mapper接口没有实现类,当调用接口方法时,接口全限名+方法名拼接字符作为key值可以唯一确定一个MapperdStatement,而在mybatis中,每一个<select>,<update>,<delete>标签都会被解析成一个MapperdStatement对象。这样就完成了一一对应;
dao接口方法不可以重载,因为找到MapperedStatement是根据接口全限名+方法名唯一确定的。
4.Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能。
5.在mapper中如何传递多个参数?
(1)自带方法:
<select id="getPersonById" parametertype="int" resulttype="com.domain.Person"> select * from person where person_id = #{id} limit #{arg1},#{arg2} </select>
public interface PersonMapper{ public List<Person> getPersonById(int id,int pageNo,int pageCount); }
@Service public PersonServiceImpl implements PersonService{ @Autowird PersonMapper personMapper;
List<Person> ps = personMapper.getPersonById(1,1,4);
}
(2)使用@Param注解
<select id="getPersonById" parametertype="int" resulttype="com.domain.Person"> select * from person where person_id = #{id} limit #{pageNo},#{pageCount} </select>
public interface PersonMapper{ public List<Person> getPersonById(@param("id")int id,int @param("pageNo") pageNo,int @param("pageCount") pageCount); }
(3)采用Map传参数
<select id="getPersonById" parametertype="int" resulttype="com.domain.Person"> select * from person where person_id = #{id} limit #{pageNo},#{pageCount} </select>
public interface PersonMapper{ public List<Person> getPersonById(Map paramMap); }
@Service public PersonServiceImpl implements PersonService{ @Autowired PersonMapper personMapper; public List<Person> getPersonById(Map paramMap){ paramMap.put("id","xxx"); paramMap.put("pageNo","xxx"); paramMap.put("pageCount","xxxx"); List<Person> ps = personMapper.getPersonById(paramMap); } }
6.Mybatis动态sql?
Mybatis动态sql可以让我们在xml映射文件中,以标签的形式编写动态sql,完成逻辑判断和动态sql拼装;
Mybatis提供九种动态sql标签:trim|where|choose|when|otherwise|set|if|foreach|bind;
执行原理为:使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
7.一对一,一对多关联查询注意事项?
一对一:association javaType
一对多:collection ofType
8.Mybatis缓存
Mybatis缓存分为一级缓存和二级缓存,一级缓存放在sqlsession中,默认就有;执行相同的sql语句,会从缓存中查询,执行CUD操作时,会将一级缓存清空,避免脏数据;
二级缓存存放在同一个命名空间的多个映射文件,多个sqlSession共享,使用二级缓存属性类需要实现serializable序列化接口(可用来保存对象的状态),可在他的映射文件中配置<cache/>,当执行CUD操作时,二级缓存会被清空;
开启二级缓存:
(1),在核心配置文件中设置cacheEnabled值:
<settings> ... <setting name="cacheEnabled" value="true"/> </setting>
(2),在映射文件中,加入以下内容,开启二级缓存:
<mapper namespace="com.mapper.PersonMapper"> ... <cache/> </mapper>
(3),实现序列化(由于二级缓存的数据不一定都是存储在内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化,如果该类存在父类,则父类也要实现序列化)
如果不想用二级缓存,可以设置禁用二级缓存:useCache = false
<select id="getPersonById" paramterType="int" resultType="com.domain.Person" useCache="false"> select * from person where person_id = #{id} </select>
刷新二级缓存:flushCache=true