-
Mybatis的DAO实现,其他的ORM框架使用过吗?
Mybatis底层实现是用动态代理做的,MyBatis一开始扫描注解或者XML配置,为每个方法(接口全路径+方法名)生成一个MappedStatement,然后对应每个Mapper接口,MyBatis生成一个动态代理类,当调用对应的方法的时候,取出之前扫描的配置,包括MySQL语句和参数等,然后调用JDBC执行。 -
#{}
和${}
的区别
1、#{}
使用的JDBC对象是PreparedStatement,${}
使用的JDBC对象是Statement。
2、#{}
将在预处理阶段将输入参数设置用占位符?代替,在执行之前使用PreparedStatement按序设置参数值,输入的参数加上双引号,引入的是字符串,${}
使用的是直接拼接,后者容易引起SQL注入(SQL注入是什么)。
3、虽然${}
容易引起SQL注入,但是在order by等要直接使用列名等数据库对象的后面一定得使用${}
,因此这类情况可以在保证安全的情况下使用${}
-
Xml 映射文件中,除了常见的 select|insert|update|delete 标签之外,还有哪些标签?
参考
按照类别来记,除了下面还有ResultType,ParameterType,分别对应输入参数类型和输出参数类型。ResultType和ResultMap只能使用其中一个。
ResultMap定义了列名和属性的对应关系
<resultMap id="BaseResultMap" type="com.meikai.shop.entity.TShopSku">
<id column="ID" jdbcType="BIGINT" property="id" />
<result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" />
<result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" />
</resultMap>
sql和include是一对的,分别用来定义和引用SQL片段
set用来清楚update user set使用if标签的时候多出来的逗号
trim可以代替set或者where
choose、when、otherwise起到的作用有点类似于java中的switch、case、default等作用。
foreach一般用在sql语句的in里面。
- 最佳实践中,通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?
全限定类名对应映射文件的namespace
方法名对应映射文件中的id
可以重载,但映射文件的id不允许重复
Dao 接口,就是人们常说的 Mapper 接口,接口的全限名,就是映射文件中的 namespace 的值,接口的方法名,就是映射文件中 MappedStatement 的 id 值,接口方法内的参数,就是传递给 sql 的参数。 Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个 MappedStatement ,举例: com.mybatis3.mappers. StudentDao.findStudentById ,可以唯一找到 namespace 为 com.mybatis3.mappers. StudentDao 下面 id = findStudentById 的 MappedStatement 。在 MyBatis 中,每一个 <select> 、 <insert> 、 <update> 、 <delete> 标签,都会被解析为一个 MappedStatement 对象。
Dao 接口方法可以重载,但是需要满足以下条件:
仅有一个无参方法和一个有参方法
多个有参方法时,参数数量必须一致。且使用相同的 @Param ,或者使用 param1 这种
- MyBatis 是如何进行分页的?分页插件的原理是什么
答:(1) MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页;(2) 可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,(3) 也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
举例:select _ from student
,拦截 sql 后重写为:select t._ from (select \* from student)t limit 0,10
为啥拦截后的sql是那样的?
- 简述 MyBatis 的插件运行原理,以及如何编写一个插件
参考:MyBatis插件的使用及其原理
2、在MyBatis配置文件中配置
这个时候可以定义配置数据

-
一级缓存和二级缓存
MyBatis缓存原理 -
MyBatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
答:不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。 原因就是 namespace+id 是作为 Map<String, MappedStatement> 的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。 -
为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?(或者MyBatis和Hibernate的区别是什么?)
答:Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。 -
在Spring中Mapper接口是如何被注入的?
通过 SqlSession 的 getMapper(Class<T> type) 方法,可以获取到 Mapper 接口的动态代理对象,那么在 Spring 中是如何将 Mapper 接口注入到其他 Spring Bean 中的呢?
在 MyBatis 的 MyBatis-Spring 集成 Spring 子项目中,通过实现 Spring 的BeanDefinitionRegistryPostProcessor 接口,实现它的 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 方法,也就是在 Spring 完成 BeanDefinition 的初始化工作后,会将 Mapper 接口也解析成 BeanDefinition 对象注册到 registry 注册表中,并且会修改其 beanClass 为 MapperFactoryBean 类型,还添加了一个入参为 Mapper 接口的 Class 对象的名称
这样 Mapper 接口会对应一个 MapperFactoryBean 对象,由于这个对象实现了 FactoryBean 接口,实现它的 getObject() 方法,该方法会通过 SqlSession 的 getMapper(Class<T> type) 方法,返回该 Mapper 接口的动态代理对象,所以在 Spring Bean 中注入的 Mapper 接口时,调用其 getObeject() 方法,拿到的是 Mapper 接口的动态代理对象 -
当实体类中的属性名和表中的字段名不一样 ,怎么办?
使用resultMap配置或者开启数据库字段名到属性的映射 -
MyBatis加载mapper有多少种方式
MyBatis加载mapper有多少种方式
网友评论