美文网首页
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