美文网首页
Mybatis(四):myBatis面试相关

Mybatis(四):myBatis面试相关

作者: aix91 | 来源:发表于2019-02-27 20:15 被阅读0次

1. #{} 和${} 的区别

${}是用来获取properties文件中的配置属性;#{}是Mybatis中的占位符,可以用来防止依赖注入。具体原理是,mybatis在创建prepareStatement时,会用 ?来替换#{}, 然后在执行前sql语句前,通过反射的方式在statement里set 相应的参数。

2. myBatis xml中有哪些标签

标签 说明
select
insert
update
delete
resultMap
parameterMap
sql
include
selectKey

3. Mapper 接口

Mapper接口是没有实现类的;mapper 的 namespace和mapper方法名,可以唯一定位一个MappedStatement;同一个mapper里面不能重载方法,因为方法是由namespace+类名+方法名唯一确定的。
Mapper的工作原理是JDK动态代理生成对象,获取sql执行语句,然后根据参数拼接成正确的sql语句进行执行。

4. 当实体类中的属性名和表中的column名不一致时,应该怎样解决?

  • 在select时使用别名,别名和实体类的属性名保持一致
  • 使用resultMap 或者 @Results注解
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
        <!–用id属性来映射主键字段–>
        <id property=”id” column=”id”/>
        <result property = “descccc” column =”description”/>
        <result property=”title222” column=”title” />
</resultMap>
    @Results({@Result(column = "description",property = "descccc"),
            @Result(column = "title",property = "title222")
    })
    TestModel select(@Param("uniqueCode") String uniqueCode);

5. Mybatis是如何进行分页操作?

  • RowBounds: 性能太差了,不如自己使用limit写分页
  • 延迟关联优化
select a.salary from salaries as a inner join (select emp_no from salaries limit 2800000,10) as b using(emp_no);
  • 书签优化
select * from salaries where emp_no>=495317 limit 10

6. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

  • 使用<resultMap>
  • 在SQL 语句中使用别名
    Mybatis通过反射创建对象,并且直接对属性进行赋值(没有用到set方法);要想成功创建对象,要保留对象的无参构造函数,或者创建一个包含所有属性的构造函数

7. 如何执行批量插入?

使用<foreach> 拼接SQL语句,批量插入数据库。

    <insert id="insertList" parameterType="java.util.List">
        insert into tb_test(
        unique_code,
        title,
        keywords,
        description
        ) values
        <foreach collection="list" item="element" open="(" separator="),(" close=")">
            #{element.uniqueCode},
            #{element.title222},
            #{element.keword},
            #{element.descccc}
        </foreach>
        on duplicate key update
        unique_code = values(unique_code),
        title = values(title),
        keywords = values(keywords),
        description = values(description)
    </insert>

8. 如何获取自动生成的(主)键值?

    <insert id="insertOne" parameterType="com.xxx.Test"useGeneratedKeys="true" keyProperty="element.id">
        insert into test(
        unique_code,
        title,
        keywords,
        description
        ) values(
            #{element.uniqueCode},
            #{element.title222},
            #{element.keword},
            #{element.descccc}
        );
    </insert>

注意keyProperty = 对象名.id

9. 一对一、一对多的关联查询

  • 一对多:使用collection + resultMap
    <select id="selectEmployee" resultMap="employeeResultMap">
        select a.emp_no, a.last_name, b.salary from employees as a
        inner join salaries as b on a.emp_no = b.emp_no
        where a.emp_no = #{emp_no}
    </select>

    <resultMap id="employeeResultMap" type="com.test.Employee">
        <result property="empNo" column="emp_no"/>
        <result property="lastName" column="last_name"/>
        <collection property="salaries" resultMap="salaryResultMap"/>
    </resultMap>

    <resultMap id="salaryResultMap" type="com.test.Salary">
        <result property="empNo" column="emp_no"/>
        <result property="salary" column="salary"/>
    </resultMap>
  • 一对多:collection+select
    <select id="selectEmployee" resultMap="employeeResultMap">
        select a.emp_no, a.last_name from employees as a
        where a.emp_no = #{emp_no}
    </select>

    <resultMap id="employeeResultMap" type="com.test.Employee">
        <result property="empNo" column="emp_no"/>
        <result property="lastName" column="last_name"/>
        <collection property="salaries"
                    select="com.test.TestMapper.selectSalary"
                    column="{emp_num= emp_no}"/>
    </resultMap>

    <resultMap id="salaryResultMap" type="com.test.Salary">
        <result property="empNo" column="emp_no"/>
        <result property="salary" column="salary"/>
    </resultMap>

    <select id="selectSalary" resultMap="salaryResultMap">
        select emp_no, salary from salaries where emp_no=#{emp_num}
    </select>
  • 一对一:使用association+resultMap
    <resultMap id="salaryResultMap" type="com.test.Salary">
        <result property="empNo" column="emp_no"/>
        <result property="salary" column="salary"/>
    </resultMap>

    <resultMap id="employeeResultMap2" type="com.test.Employee">
        <result property="empNo" column="emp_no"/>
        <result property="lastName" column="last_name"/>
        <association property="salaries" resultMap="salaryResultMap"/>
    </resultMap>

    <select id="selectCurrentEmployee" resultMap="employeeResultMap2">
        select a.emp_no, a.last_name, b.salary from employees as a
        inner join salaries as b on a.emp_no = b.emp_no
        where a.emp_no = #{1}
        and b.to_date='9999-01-01'
    </select>

10. 简述Mybatis的插件运行原理,以及如何编写一个插件

myBatis插件原理

11. Mybatis延迟加载

mybatis 仅支持"collection", "association" 的懒加载,且只能用在association/collection+select模式上。

  • 全局设置懒加载模式
<setting name="lazyLoadingEnabled" value="true"/>  
<setting name="aggressiveLazyLoading" value="false"/>
  • 在collection/association 中单独设置 "fetchType = lazy"(eager 禁用懒加载)
    <resultMap id="employeeResultMap" type="com.test.Employee">
        <result property="empNo" column="emp_no"/>
        <result property="lastName" column="last_name"/>
        <collection property="salaries"
                    select="com.test.TestMapper.selectSalary"
                    column="{emp_num= emp_no}" fetchType="lazy"
        />
    </resultMap>

原理: 使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。

12. Mybatis 缓存

Mybatis(七):mybatis缓存

相关文章

网友评论

      本文标题:Mybatis(四):myBatis面试相关

      本文链接:https://www.haomeiwen.com/subject/erttyqtx.html