mybatis相关知识整理

mybatis相关知识整理

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

${}是单纯的字符替换,而#{}是预处理,相当于PreparedStatement,可以防止注入问题,提高系统的安全性

2.mybatis的优缺点

优点:

	1.相对于JDBC减少了很多代码量
	2.mybatis是用jdbc去连接数据库,所以支持jdbc的数据库,都可以用mybatis
	3.可以很好的与spring进行兼容

缺点:

	1.sql语句的编写工作量大,对于多字段,多表查询这些,对语句编写的要求比较高
	2.sql语句的编写依赖于数据库,数据库的移植性比较差,不能随意的更改数据库

3.mybatis是个啥

1.mybatis是个半ORM(对象关系映射)框架,内部封装了JDBC,内置驱动,创建连接,创建statement,开发者只需要关注sql语句本身,可以严格控制sql执行性能,灵活度高。
2.为啥说是半:mybatis不像hibernate,hibernate在查询关联对象以及关联集对象时,可以根据对象关系模型直接获取,而mybatis要手动编写sql语句。
3.mybatis用过xml或者注解来配置和映射原生信息,将pojo映射成数据库中的记录,避免了几乎所有的JDBC代码,和手动获得参数以及获取结果集。
4.mybatis的运行流程:mybatis通过xml文件以及注解的方式,将各种要执行的statement配置起来,并通过java对象和statement中的动态参数进行映射生成要执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象返回(从执行sql到返回result的过程)
5.mybatis专注于sql语句本身,灵活度高,适用于对性能有要求的项目。

4.mybatis的XML解析

1.mybatis会把每一个sql标签封装成sqlSource对象,根据语句的不同分成动态sql和静态sql,静态就是String的sql语句,动态就是一个个sqlNode
2.xml文件中每一个sql就对应一个mapperStatement,其中有两个属性很重要:
  1.ID -----> 全限定类名+方法名组成的ID
  2.sqlSource -----> 每个sql标签对应的sqlSource对象
3.创建完mapperStatement对象后,把他们放到configuration中,configuration掌管了所有sql配置信息,当我们执行mybatis时,拿 全限定类名+方法名 找到对应的mapperStatement对象,解析里面的sql内容,执行即可。

5. mybatis的DAO的工作原理

1.mybatis的DAO并没有实现类,在spring中我们一般:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.viewscenes.netsupervisor.dao" />
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>

而在springboot中则使用注解@MapperScan(“com…mapper”),
他们的作用是一样的,就是将包路径下的所有类注册到spring Bean,并且将他们的beanClass设置为MapperFactoryBean,MapperFactoryBean实现了factoryBean的接口,俗称工厂bean。当我们用@Autowired注入这个DAO接口是时,它其实返回的是factoryBean的getObject()方法对象。
2.而getObject()干了啥呢?
简单来说,就是通过JDK的动态代理,返回了DAO的一个代理对象,这个代理对象的处理器是MapperProxy,当我们注入这个接口时,就是注入了这个代理对象,当我们调用DAO接口的方法时,就是调用了MapperProxy的invoke()方法,在这里其实就是调用了sqlSession里面的方法了,它就是通过statement(全限定类型+方法名)拿到MapperStatement 对象,然后通过执行器Executor去执行具体SQL并返回。

6.DAO里面的方法可以重载嘛?

不可以,因为mybatis是根据 全限定类型+方法名的方式进行管理的
全限名就是Dao的namespace ,id就是每一个sql的id,每一个mappedStatement都有一个唯一的 全限定类型+方法名,在调用方法时,也是把它拼成一个唯一的key值,去找对应的唯一的mapperStatement。

7.mybatis不同的xml,他们的id可以重复嘛

老版本中,namespace时可选的选项,这时,id是不能重复的,而新版本中,namespace是必选的,所以现在可以重复

8.mybatis是如何分页的,解释原理

mybatis使用RowBounds进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。
分页插件的基本原理是,使用mybatis提供的插件接口,实现自定义插件,在拦截方法里拦截待执行的sql语句,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

9.内存分页和物理分页?

内存分页就是把所有的数据都到内存中再分页,占用内存较大,物理分页就是只读取一部分数据,占用内存较小

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

mybatis可以编写针对ParameterHandler,ResultSetHandler,StatementHandler以及executor这四种接口的插件,mybatis使用的是JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这四种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler()的invoke()方法,当然只会拦截那些你指定的需要拦截的方法。
编写插件:实现Mybatis的Intercaptor接口并复写intercept()方法,然后再给插件编写注解,指定要拦截哪一个接口的哪些方法即可,最后在配置文件中配置你编写的插件。

11.mybatis是否支持延迟加载,如果支持,它的实现原理是什么

mybatis只支持association关联对象和collection关联集合的延迟加载,association指的是一对一,collection指的是一对多的查询,再配置文件中,可以配置是否启用延迟加载,lazyLoadingEnabled=true|false
实现原理:使用CGLIB创建目标对象的代理对象,当调用方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器发现a.getB()==null,那么就会单独发送事先保存好的查询管理B对象SQL,把B查询出来,然后调用a.setB(),这样就有值了,然后完成getName()方法的调用。

12.什么是延迟加载

就是懒汉/饿汉模式,多表查询时有一些数据并用不到,我们在第一次加载时并不需要加载,所以我们可以在需要的时候再去加载它。

13.什么是缓存,一级缓存,二级缓存,刷新缓存?

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能
一级缓存:基于PerpetualCache的hashMap本地缓存,其存储作用域为Session,当session flysh或者close的时候,该session中所有的Cache就将清空,默认打开一级缓存
二级缓存:默认也是采用PerpetualCache的hashmap存储,不同在于其存储作用域是Mapper(Namespace)并且可自定义存储源,默认不打开二级缓存,也要开启二级缓存,使用二级缓存的属性类需要实现Serializable序列化接口,可在他的映射文件中配置
刷新机制:当某一个作用域(session/Namespaces)的进行的CUD操作后,默认该作用域下所有select中的缓存将被cleear并且重新更新,如果开启了二级缓存,则只根据配置判断是否更新。

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

第一种是使用标签,注意定义数据库列名和对象属性名之间的映射关系
第二种是alise别名功能,将列的别名书写为对象属性名
有了列名与属性名的映射关系后,mybatis通过反射创建对象,同时使用反射给对象的属性逐一复制并返回,那些找不到映射关系的属性,是无法完成赋值的。

15.Mybatis的动态sql有什么用?执行原理?有哪些动态sql?

mybatis动态sql可以在xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断,并动态拼接sql的功能。
trim/where/set/foreach/if/choose/when/otherwise/bind

16.xml中除了 select/delete/update/insert还有哪些标签?

resultMap,parameterMap,sql,include,selectKey加上动态sql9个标签,通过include标签引入sql片段,selectKey为不支持自增的逐渐生成策略标签

17.使用mybatis的mapper接口调用时,有哪些要求?

1.Mapper接口方法名和mappeer.xml中定义的每个sql的id相同
2.Mapper接口方法中的输入参数类型和mapper.xml中定义一样的每个sql的parameterType的类型相同
3.Mapper接口方法的输出参数和mapper.xml中定义的每个sql的resultType的类型相同
4.mapper.xml文件用的namespace即使mapper接口的类路径

18.模糊查询like语句怎么写

第一种:在java代码中添加sql通配符

String str = "%value%";
List<Name> names = mapper.selectLike(str);

<select id="selectLike">
	select * from tb_name where name like #{value}
</select>

第二种:sql语句中添加通配符,有注入的风险

String str = "value";
List<Name> names = mapper.selectLike(str);

<select id="selectLike">
	select * from tb_name where name like "%"${value}"%"
</select>

19.实体类中的属性名和表中的字段不一样,怎么办

第一种:sql语句中定义字段名的别名,让字段的别名和实体类的属性名一致

<select id="selectOne" parameterType="Integer" resultType="com.kobeLiu.entity.order">
	select order_id id,order_no orderNo,order_price orderPrice from orders where order_id = #{id}
</select>

第二种:resultMap来映射字段名和实体类属性名的一一对应的关系。

<select id="selectOne" parameterType="Integer" resultMap="orderMap">
	select order_id id,order_no orderNo,order_price orderPrice from orders where order_id = #{id}
</select>
<resultMap type="com.kobeLiu.entity.order" id="orderMap">
	<!-- 用id属性来映射主键字段 -->
	<id property="id" column="order_id">
	<!- 用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性 ->
    <result property = “orderno” column =”order_no”/>
    <result property=”price” column=”order_price” />\
</reslutMap>

20.如何获取自动生成的主键值

insert方法总是返回一个int值,这个值代表的是插入的行数
如果采用的自增长策略,自动生成的键值在insert方法执行完后可以被设置到传入的参数对象

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

int row = mapper.insertName(name);
sout("rows inserted:" + row);
sout("key:" + name.getId());

21.如何在mapper中传递多个参数?

//第一种
//Dao层函数
User userSelectUser(String name,String area);
//对应的xml
<select id="userSelectUser" resultMap="BaseResultMap">
	select * from user_tb where user_name=#{1} and user_area = #{2}
</select>

//第二种,使用@Param注解
User userSelectUser(@Param("userName")String name,@Param("userArea")String area);
//对应的xml,最好应用resultMap
<select id="userSelectUser" resultMap="BaseResultMap">
	select * from user_tb where user_name=#{userName} and user_area = #{userArea}
</select>

//第三种,用map来装
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
Map<String, Object> map = new HashMap();
     map.put("start", start);
     map.put("end", end);
     return sqlSession.selectList("StudentID.pagination", map);
 }catch(Exception e){
     e.printStackTrace();
     sqlSession.rollback();
    throw e; }
finally{
 MybatisUtil.closeSqlSession();
 }

22.一对一,一对多的关联查询

<mapper namespace="com.mnlm.mapper.UserMapper">
	<!-- association 一对一关联查询 -->
	<select id="getClass" parameterType="INTEGER" resultMap="ClassResultMap">
		select * from tb_class c,tb_teacher t where c.teacher_id = t.t_id and c.c_id = #{id}
	</select>
	<resultMap type="com.mnlm.entity.Classes" id="ClassResultMap">
		<!-- 实体类的字段名和数据表的字段名映射 -->
		<id property="id" column="c_id" />
		<result property="name" column="c_name" />
		<association property="teacher" javaType="com.mnlm.entity.Teacher">
			<id property="id" column="t_id" />
			<result property="name" column="t_name" />
		</association>
	</resultMap>

	<!-- collection 一对多关联查询 -->
	<select id="getClass" parameterType="INTEGER" resultMap="ClassResultMap2">
		select * from tb_class c,tb_teacher t,tb_student s where c.teacher_id = t.t_id and c.class_id = s.class_id and c.c_id = #{id}
	</select>
	<resultMap type="com.mnlm.entity.Classes" id="ClassResultMap">
		<id property="id" column="id" />
		<result property="name" columu="name">
		<association property="teacher" javaType="com.mnlm.entity.Teacher">
			<id property="id" column="t_id" />
			<result property="name" column="t_name" />
		</association>
		<collection property="student" ofType="com.mnlm.entity.Student">
			<id property="id" column="s_id" />
			<result property="name" column="s_name" />
		</collection>
	</resultMap>
</mapper>

23.Mybatis实现一对一有几种方式?具体是怎么操作的?

有联合查询和嵌套查询 ,联合查询是几个表联合查询,只查询一次,通过resultmap中的association节点配置一对一的类就可以完成
嵌套查询是先查一张表,根据这张表中的外键id去查询另一张表,也是通过association,但另外一张表是通过select属性配置

24.Mybatis实现一对多有几种方式?具体是怎么操作的?

一对一是association 一对多是 collection

25.mapper编写的几种方式?

这个白天认真敲

26.什么是mybatis的接口绑定

接口绑定就是在mybatis中定义接口与sql语句进行绑定,我们直接调用接口方法就好,这样比起sqlSesseeion提供的方法更加灵活。
接口绑定有2种方式,一个是在接口方法的上面加上注解 @Select @Delete 等等,里面包含sql语句来绑定;另一种就是xml配置,namespace+id是保证唯一,不可以重载

27.Mybatis和Hibernte有哪些不同?

1.Mybatis需要自己去编写sql语句,不是一个完全的ORM框架
2.Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,但是无法做到数据库无关性,如果需要支持杜仲数据库的软件,则需要自定义多套sql映射文件,工作量大
3.Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用Hibernate开发可以节省很多代码,提高效率。

注明: 个人复习用,参考博客为:https://blog.csdn.net/a745233700/article/details/80977133
以及https://blog.csdn.net/a745233700/article/details/89308762

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值