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

 

posted @ 2017-11-14 16:58  港湾小唯  阅读(237)  评论(0编辑  收藏  举报