mybatis 问答

野鹤闲人 / 2023-08-21 / 原文

1、什么是mybatis

mybatis是半orm(对象关系映射)框架

1)内部封装了jdbc,不用再手动加载驱动,创建连接,创建statement

2)注解或xml形式,pojo映射成数据库记录,不用手动设置参数

将要执行的statement配置起来,通过java对象和statement的sql的动态参数,构成可以执行的sql,再将结果映射成java对象

(执行sql到result返回的过程)

2、mybatis和hibernate区别

mybatis不是完全的orm框架,还需要开发者自己写sql

hibernate对象关系映射较好

3、#{}和${}的区别

#{}:预编译,mybatis会将其替换成?,再用preparedStatement的set进行赋值,可以防止sql注入

${}:替换成变量的值

4、实体类的属性名 和表的字段名不一致时,怎么办

1)select aaa id from table;  查询时取字段别名

2)用resultmap 进行映射

5、Mapper的工作原理,方法参数不同时,能否重载

dao接口就是mapper接口,mapper没有实现类,接口限定名+方法名 拼出的key值,可唯一定位到 MappedStatement 

在mybatis中,<select><insert><delete><update>都会解析成一个MappedStatement 对象

举例:com.mybatis3.mappers.StudentDao.findStudentById,
可以唯一找到 namespace 为com.mybatis3.mappers.StudentDao 下面 id 为findStudentById 的 MappedStatement。

Mapper里面的方法,不能重载,因为用的是 接口限定名+方法 的保存和查找策略

工作原理是jdk动态代理,为mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MappedStatement 代表的sql,再返回结果

 1  private static class DefaultMethodInvoker implements MapperMethodInvoker {
 2     private final MethodHandle methodHandle;
 3 
 4     public DefaultMethodInvoker(MethodHandle methodHandle) {
 5       super();
 6       this.methodHandle = methodHandle;
 7     }
 8 
 9     @Override
10     public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
11       return methodHandle.bindTo(proxy).invokeWithArguments(args);
12     }
13   }

6、如何分页,分页插件的原理

RowBounds进行分页,不过这是对resultset进行内存分页,不是物理分页

可以在sql里面写带有物理分页的参数;或者用分页插件

插件的拦截方法里面 拦截要执行的sql,根据dialect 增加分页语句和参数

7、获取自动生成的key

<insert id="insertname" usegeneratedkeys="true" keyproperty="id">
    insert into names (name) values (#{name})
</insert>

name name = new name();
name.setname("fred");
int rows = mapper.insertname(name);
// 完成后,id 已经被设置到对象中
system.out.println("rows inserted = " + rows);
system.out.println("generated key value = " + name.getid());

 8、用了哪几个动态代理

mapper用了jdk动态代理,延迟加载用了 cglib代理

9、延迟加载原理

mybatis只是对关联对象进行延迟加载,对主加载对象还是直接查询的

直接加载:lazyLoadingEnabled=false

侵入式延迟:lazyLoadingEnabled=true,aggressiveLazyLoading=true

深度延迟:lazyLoadingEnabled=true,aggressiveLazyLoading=false   执行到关联对象详情时,才查询

后面2个延迟的 区别是啥??

cglib创建目标代理对象(一般映射的是javabean,没有接口,所以不能用jdk动态代理),等到调用方式时,才执行语句。

10、一二级缓存 

一级缓存:hashmap, 作用域  session

二级缓存:作用域  namespace

11、接口绑定,实现方式

任意定义接口,方法和sql绑定在一起

两种方式:

1)注解 @select @update

2)xml:复杂sql可以用这个,要指定xml文件里面的namespace是 接口的全路径名

12、

 

 

 

 

 

参考地址:

http://gitbook.chenqiong.net/part1/4/3/1.html