概念/作用:

持久层框架,通过xml或注解的方式将要执行的各种 statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句。最后mybatis框架执行sql并将结果映射为java对象并返回。采用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作。

数据源环境environment可以配置多个

mapper文件里面配置了多个select/insert/update/delete sql语句,取用的时候是采用标识:namespace+id

默认事务不提交

Mybatis----多表操作

一对一查询,一个用户只有一个订单

对应的sql语句:select *  from orders o,user u where o.uid=u.id;

user表和orders表连接,自然就需要user+order两个对象来映射返回的所有列

<mapper namespace="com.mapper.OrderMapper"><resultMap id="orderMap" type="com.domain.Order"><!--手动指定字段与实体属性的映射关系 column: 数据表的字段名称 property:实体的属性名称 --><id column="oid" property="id"></id><result column="ordertime" property="ordertime"></result><result column="total" property="total"></result>//主键使用id标签<id column="id" property="id"></id>       <result column="uid" property="user.id"></result><result column="username" property="user.username"></result><result column="password" property="user.password"></result><result column="birthday" property="user.birthday"></result></resultMap><select id="findAll" resultMap="orderMap">select * from orders o,user u where o.uid=u.id</select></mapper>

注解配置

首先核心配置文件中:

<mappers>
    <!--扫描使用注解的类所在的包-->
    <package name="com.mapper"></package>
</mappers>

在接口中进行sql语句的映射配置public interface UserMapper {@Insert("insert into user values(#{id},#{username},#{password},#{birthday})")public void save(User user);@Update("update user set username=#{username},password=#{password} where id=#{id}")public void update(User user);@Delete("delete from user where id=#{id}")public void delete(int id);@Select("select * from user where id=#{id}")public User findById(int id);@Select("select * from user")public List<User> findAll();@Select("select * from user")@Results({@Result(id=true ,column = "id",property = "id"),@Result(column = "username",property = "username"),@Result(column = "password",property = "password"),@Result(property = "orderList",column = "id",javaType = List.class,many = @Many(select = "com.mapper.OrderMapper.findByUid"))})public List<User> findUserAndOrderAll();上面等价与先在user表中查出uid 然后 在订单表中查询 select * from order where uid=user.uid@Select("SELECT * FROM USER")@Results({@Result(id = true,column = "id",property = "id"),@Result(column = "username",property = "username"),@Result(column = "password",property = "password"),@Result(property = "roleList",column = "id",javaType = List.class,many = @Many(select = "com.itheima.mapper.RoleMapper.findByUid"))})public List<User> findUserAndRoleAll();}

mybatis常见面试题:

具体问题

1、#{}和${}区别

都属于占位符

#{}是预编译处理 使用prepareStatedment的参数设置方法;$ {}是字符串替换,参数传递

#{} :mybatis内部会创建配prepareStatedment 使用#{}格式的语法在mybatis中使用prepareStatedment语句来安全的设置值; MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值;MyBatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。

${}是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc.Driver。

#{} sql 的参数占位符,MyBatis 会将 sql 中的#{}替换为?号, sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值,比如 ps.setInt(0, parameterValue),#{item.name} 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()。

预编译是:指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。

2、mapper.xml 标签有哪些?resultMap和resultType的区别?

常用的<select>  <delete>  <insert>  <update>,除此之外:

<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上动态 sql 的 9 个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中为 sql 片段标签,通过<include>标签引入 sql 片段,<selectKey>为不支持自增的主键生成策略标签。

resultMap 是一种"查询结果集---Bean对象”属性名称映射关系,列和bean对象的属性的映射,一般适用于多表连接

Resulttype---一般适用于pojo(简单对象)类型数据,简单的单表查询

如果配置成类,一般映射会遵循约定:要求Bean对象字段名和查询结果集的属性名相同(可以大小写不同,大小写不敏感)。因为这个自动映射,可以省略调resultMap进行属性名映射。也可以是int long这种pojo类型

3.dao接口的底层原理(如何返回实现类并且封装好结果集合的)?

通过动态代理实现接口的实现类,在mapperPorxy(实现invocationHandler接口)中的invoke中调用sql语句:mapperMethod.execute(sqlSession, args);

===》会进行paramname解析 比如将#{}解析为?

4、MyBatis 是否可以映射 Enum 枚举类?

答:MyBatis 可以映射枚举类,不单可以映射枚举类,MyBatis 可以映射任何对象到表的一列上。映射方式为自定义一个 TypeHandler,实现 TypeHandler 的 setParameter()和 getResult()接口方法。TypeHandler 有两个作用,一是完成从 javaType 至 jdbcType 的转换,二是完成 jdbcType 至 javaType 的转换,体现为 setParameter()和 getResult()两个方法,分别代表设置 sql 问号占位符参数和获取列查询结果。

实现自定义的typeHandler: 继承BaseTypeHandler<T> ---》 Mybatis就是依赖泛型参数<T>,获得泛型参数Class对象,再与反射获得的bean属性Class,进行一一对应的

除了上面的“智能”绑定外,我们还可以手动绑定TypeHandler。

<result property="phone" column="phone" typeHandler="com.mybatis3.typehandlers.PhoneTypeHandler"/>

8、typehandler

mybatis默认提供的typehandler:

比如:

 public TypeHandlerRegistry() {register(Boolean.class, new BooleanTypeHandler());register(boolean.class, new BooleanTypeHandler());register(JdbcType.BOOLEAN, new BooleanTypeHandler());register(JdbcType.BIT, new BooleanTypeHandler());register(JdbcType.VARCHAR, new StringTypeHandler());

自定义注册:

register(typeReference.getRawType(), typeHandler);

.getRawType()就是返回 泛化类型<T>

9、mybatis可以分页吗?如何?

Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结果集进行分页,也就是人们常说的逻辑分页,而非物理分页。

Rowbounds两个属性:offset + limit

offset就是从哪里开始读,最多读limit行

实现:

跳转到offset位置:

for (int i = 0; i < rowBounds.getOffset(); i++) {rs.next();
}private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)throws SQLException {DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();skipRows(rsw.getResultSet(), rowBounds);while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);Object rowValue = getRowValue(rsw, discriminatedResultMap);storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());}}

10、mybatis如何返回在执行insert时生成的自增主键?

在Mybatis中,执行insert操作时,如果我们希望返回数据库生成的自增主键值,那么就需要使用到KeyGenerator对象。

。Mybatis是对JDBC的封装,其Jdbc3KeyGenerator类,就是使用下面的原理,来返回数据库生成的主键值的。

Class.forName("com.mysql.jdbc.Driver");

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123");

conn.setAutoCommit(false);

PreparedStatement pstm = conn.prepareStatement("insert into students(name, email) values(?, ?)",

Statement.RETURN_GENERATED_KEYS);

pstm.setString(1, "name1");

pstm.setString(2, "email1");

pstm.addBatch();

pstm.setString(1, "name2");

pstm.setString(2, "email2");

pstm.addBatch();

pstm.executeBatch();

// 返回自增主键值

ResultSet rs = pstm.getGeneratedKeys();

while (rs.next()) {

Object value = rs.getObject(1);

System.out.println(value);

}

conn.commit();

rs.close();

pstm.close();

conn.close();

output:

246

247

Mapper.Xml配置方式。

<insert id="insertStudents" useGeneratedKeys="true" keyProperty="studId" parameterType="Student">

主键赋值到keyproperty

11、如何批量插入List<student>?

<insert id="insertStudents" useGeneratedKeys="true" keyProperty="studId" parameterType="java.util.ArrayList">

INSERT INTO

STUDENTS(STUD_ID, NAME, EMAIL, DOB, PHONE)

VALUES

<foreach collection="list" item="item" index="index" separator=",">

(#{item.studId},#{item.name},#{item.email},#{item.dob}, #{item.phone})

</foreach>

</insert>

此时返回主键id列表为null

11、Mybatis之foreach批量insert,返回主键id列表(修复Mybatis返回null的bug)

使用simpleExectuor/reuse可以返回

使用batch返回的是null

因为batch:如果传递的是List<Student>,那么,将包装为一个Map<String, Collection>对象

SimpleExecutor和ReuseExecutor可以正确返回foreach批量插入后的id列表的原理:

getParameters()方法,会再次处理参数类型,拆封map,获取map中的vaule 即collection对象

BatchResult又把Map<String, List<Student>>放到List中,于是,参数对象数据结构就变成了List<Map<String, List<Student>>>。

Java接口是否继承Object类?

https://dslztx.github.io/blog/2018/04/22/Java%E6%8E%A5%E5%8F%A3%E6%98%AF%E5%90%A6%E7%BB%A7%E6%89%BFObject%E7%B1%BB/

看似是继承的,因为一个接口可以直接调用hashcode toString方法 可以通过编译

但是如果接口继承了object类 接口就不能实例化

所以是,虚拟机制造了“继承的假象”。虚拟机会在顶层接口(没有父接口的接口)中自动定义一系列对应于Object类中“public”方法的虚方法,除非已经得到了显式定义,这点跟虚拟机会自动定义一个默认构造器类似。

mybatis基础综合/常见面试题相关推荐

  1. 数据库基础(常见面试题)

    数据库基础(面试常见题) 一.数据库基础 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义.数据操纵(Data Manipulation),数据控制( ...

  2. php 基础知识 常见面试题

    1.echo.print_r.print.var_dump之间的区别 * echo.print是php语句,var_dump和print_r是函数 * echo 输出一个或多个字符串,中间以逗号隔开, ...

  3. Mybatis常见面试题总结(详细)

    Mybatis常见面试题总结 SpringMVC常见面试题总结(超详细回答) 2020最新Java面试题(java,JavaWeb,数据库,框架),常见面试题及答案汇总 Spring常见面试题总结(超 ...

  4. BTA 常问的 Java基础40道常见面试题及详细答案,java初级面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  5. BTA 常问的 Java基础40道常见面试题及详细答案

    最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案. 为此我业余时间整理了,Java基础常见的40道常见面试题,及详细答案,望各路大牛,发现不对的地方,不吝赐教,留言即 ...

  6. Java基础常见面试题(一)

    Java基础常见面试题(一) 1. 为什么说 Java 语言"编译与解释并存"? 我们可以将高级编程语言按照程序的执行方式分为两种: 编译型 :编译型语言会通过编译器将源代码一次性 ...

  7. java常见面试题及答案 1-10(基础篇)

    java常见面试题及答案 1.什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被 ...

  8. 测试开发工程师常见面试题

    1. CPU 和 GPU的区别 CPU 力气大啥P事都能干,还要协调. GPU 上面那家伙的小弟,老大让他处理图形,这方面处理简单,但是量大,老大虽然能处理,可是老大只有那么几个兄弟,所以不如交给小弟 ...

  9. java 常用模块_Java 常见面试题的模块

    Java 常见面试题的模块: Java 基础.容器.多线程.反射.对象拷贝.Java Web 模块.异常.网络.设计模式.Spring/Spring MVC.Spring Boot/Spring Cl ...

最新文章

  1. 赠书 | 机器翻译,正在弥补人机翻译之间的差距
  2. 3·15,你“信”了吗
  3. 9:02 2009-7-17 日志
  4. IE8下utf-8编码页面乱码问题解决办法
  5. 第二十三篇:在SOUI中使用LUA脚本开发界面
  6. 历经十年,Windows 7 生命周期将结束,微软:快换 Windows 10
  7. (libgdx学习)Continuous non continuous rendering
  8. 2018年python工作好找吗-2018年最新数据:python、大数据、人工智能从业者薪资表...
  9. Apache目录禁止解析
  10. PostgreSQL数据库常用SQL语句
  11. This property is obsolete now. Use the TextPattern property instead.的警告解决办法
  12. Linux C recv函数阻塞问题
  13. 计算机启动后无法进入系统怎么办,笔记本开机进不了系统,小编教你笔记本开机无法进入系统怎么办...
  14. Android系统教程PPT,Android教程之架构详解.ppt
  15. 投资是一个非常专业的领域,亏钱容易赚钱难
  16. mysql 微博 数据表_微博数据库如何设计-百度经验
  17. ipv6u前缀地址数中/32,/48,/64含义跟一些相关资料
  18. Android图形显示系统——一张图片的显示流程
  19. AE使用中的常见错误01
  20. 王桂林 C++视频 学习笔记

热门文章

  1. Python运行的17个时新手常见错误小结
  2. 使用MSBuild实现完整daily build流程
  3. 两款接口测试工具推荐
  4. 老王教你怎样干掉局域网的IDA验证
  5. 用delphi创建服务程式
  6. Android.mk 用法介绍
  7. php5.3.8添加eaccelerator扩展 加速php代码执行效率
  8. html景图片怎么设置百分比,8个风光照片拍摄技巧
  9. 认识python零基础知识到实战概论的复习和回顾上
  10. Android Studio 选项菜单和动画结合_谷歌准备为Android增加像iOS一样的功能