Mybatis知识点总结
---恢复内容开始---
Mybatis知识点总结
1、#{}和${}的区别是什么?
答:#{}的使用场景:在表的sql映射文件中如下使用:
- <mapper namespace="com.mybatis.test2.userMapper">
- <select id="insertUser" parameterType="_User">
- INSERT INTO users(name,age) values(#{name},#{age})
- </select>
- </mapper>
#{}是sql的参数占位符,Mybatis会将sql中的#{}替换为?号,在sql执行前会使用PreparedStatement的参数设置方法,按序给sql的?号占位符设置参数值。
${}的使用场景:先在配置文件中定义好变量,再在conf.xml中如下使用:
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC" />
- <dataSource type="POOLED">
- <property name="driver" value="${jdbcDriver}" />
- <property name="url" value="${jdbcUrl}" />
- <property name="username" value="${username}" />
- <property name="password" value="${password}" />
- </dataSource>
- </environment>
- </environments>
${}是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如${jdcDriver}会被静态替换为com.mysql.jdbc.Driver。
2、Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?
答:还有很多其他的标签:<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,
加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,
其中<sql>为sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生成策略标签。
3、最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
答:1 Dao接口,就是人们常说的Mapper接口,---这是在基于注解的方式才会创建此接口,接口内定义了增删该查的抽象方法;
- /**
- * 接口: 通过注解的方法操作数据表的CRUD
- * @version 2.2 2016/9/24
- * @author WGS
- *
- */
- public interface UserMapper {
- @Insert("insert into users(name,age) values(#{name},#{age})")
- public int insertUser(User user);
- @Delete("delete from users where id=#{id} ")
- public int deleteUser(int id);
- @Update("update users set name=#{name},age=#{age} where id=#{id}")
- public int updateUser(User user);
- @Select("select * from users where id=#{id}")
- public User getUserById(int id);
- @Select("select * from users")
- public List<User> getAllUsers();
- }
接口的全限名,就是映射文件中的namespace的值:
- <mapper namespace="com.mybatis.test3.orderMapper">
- <select id="selectUser" parameterType="int" resultType="Order">
- select * from users where id=#{id}
- </select>
- </mapper>
接口的方法名(getUserById),就是映射文件中MappedStatement 的id值(selectUser),接口方法内的参数,就是传递给sql的参数(#{id} >>> #{id})。
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis.test2.userMapper.insertUser,可以唯一找到namespace为 com.mybatis.test2.userMapper 下面 id =insertUser 的 MappedStatement。
在Mybatis中,每一个<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象。
2 Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
3 Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
4、Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?
答:Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签 trim|where|set|foreach|if|choose|when|otherwise|bind。
- <!--
- 5 模糊查询:根据条件查询用户(姓名模糊匹配,年龄在指定的最小值和最大值之间)
- SQL:select * from d_user where name like '%o%' and age>=13 and age<=18
- -->
- <!--定义操作 classes 表的sql 映射文件:userMapper2.xml -->
- <mapper namespace="com.mybatis.test6.userMapper2">
- <select id="getUser" parameterType="User" resultType="User">
- select * from d_user where age between #{minAge} and #{maxAge}
- <!--动态sql语句:当输入的name!=null 时就执行下面的语句 -->
- <if test=' name != "%null%" '>
- and name like #{name}
- </if>
- </select>
- </mapper>
其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
5、Mybatis是如何解决sql字段名与实体类名不一致导致的冲突?
答:有两种方式:
1 在sql语句中定义别名:
2 通过<resultSet>标签:
- <!--
- 解决字段名和实体类属性名不相同的冲突
- -->
- <!--定义操作 users 表的sql 映射文件:orderMapper.xml -->
- <mapper namespace="com.mybatis.test3.orderMapper">
- <!-- 方式一:通过在sql语句中定义别名 -->
- <!-- <select id="selectOrder" parameterType="int" resultType="Order">
- select order_id id,order_no orderNo,order_price price from orders where order_id=#{id}
- </select> -->
- <!-- 方式二: 通过resultMap -->
- <select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
- select * from orders where order_id = #{id}
- </select>
- <resultMap type="Order" id="orderResultMap">
- <id property="id" column="order_id"/>
- <result property="orderNo" column="order_no"/>
- <result property="price" column="order_price"/>
- </resultMap>
- </mapper>
6、Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
selectOne
一对一:association
- <!--
- 4、关联表查询:一对一关联
- 如何根据id查询班级信息(包括老师信息)
- Class封装了Teacher属性,即是相互关联的
- -->
- <!--定义操作 users 表的sql 映射文件:orderMapper.xml -->
- <mapper namespace="com.mybatis.test4.classesMapper">
- <!--
- 方式一:嵌套结果
- 使用嵌套结果映射来处理重复的联合结果的子集来封装联表查询的数据(去除重复的数据)
- -->
- <select id="getClassInfo" parameterType="int" resultMap="ClassResultMap">
- select * from class c,teacher t where c.teacher_id = t.t_id and c.c_id = #{id}
- </select>
- <!-- 解决字段名属性名不一致问题 -->
- <resultMap type="Classes" id="ClassResultMap">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <!-- 一对一关联查询 -->
- <association property="teacher" column="teacher_id" javaType="Teacher">
- <id property="id" column="t_id"/>
- <result property="name" column="t_name"/>
- </association>
- </resultMap>
- <!--
- 方式二:嵌套查询
- 通过执行另外一个SQL映射语句来返回预期的复杂类型:
- SELECT * FROM class WHERE c_id =1;
- SELECT * FROM teacher WHERE t_id =1;//1 是上一个查询得到的teacher_id的值
- -->
- <select id="getClassInfo2" parameterType="int" resultMap="ClassResultMap2" >
- select * from class where c_id = #{id}
- </select>
- <!-- 解决字段名属性名不一致问题 -->
- <resultMap type="Classes" id="ClassResultMap2">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <association property="teacher" column="teacher_id"
- javaType="Teacher" select="getTeacher">
- </association>
- </resultMap>
- <select id="getTeacher" parameterType="int" resultType="Teacher">
- select t_id id,t_name name from teacher where t_id=#{id}
- </select>
- </mapper>
一对多:collection
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <!--
- 4、关联表查询:一对多关联
- 如何根据class_id查询班级信息(包括老师和学生信息),学生信息为集合List
- Class封装了Teacher和学生属性,即一张class表中包含teacher表和student表
- -->
- <!--定义操作 classes 表的sql 映射文件:classesMapper.xml -->
- <mapper namespace="com.mybatis.test5.classesMapper2">
- <!--
- 方式一:嵌套结果
- 使用嵌套结果映射来处理重复的联合结果的子集
- SELECT * FROM class c, teacher t,student s
- WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND c.c_id=1
- -->
- <select id="getClassInfo3" parameterType="int"
- resultMap="getClassMap">
- SELECT * FROM class c, teacher t,student s
- WHERE c.teacher_id=t.t_id AND c.C_id=s.class_id AND c.c_id=#{id}
- </select>
- <!-- 解决字段名和属性不一致冲突 -->
- <resultMap type="Classes" id="getClassMap">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <!-- 关联的教师信息 -->
- <association property="teacher" column="teacher_id"
- javaType="Teacher">
- <id property="id" column="t_id"/>
- <result property="name" column="t_name"/>
- </association>
- <!-- 关联的学生信息,是集合 -->
- <collection property="students"
- ofType="Student">
- <id property="id" column="s_id"/>
- <result property="name" column="s_name"/>
- </collection>
- </resultMap>
- <!--
- 方式二:嵌套查询
- 通过执行另外一个SQL映射语句来返回预期的复杂类型
- SELECT * FROM class WHERE c_id =1 //查询后获取到teacher_id,c_id值,传入下两条语句
- SELECT * FROM teacher WHERE t_id =1 //t_id=1 是上条查询得到的teacher_id值
- SELECT * FROM student WHERE class_id =1 //c_id = 1 是上条查询得到的c_id值
- -->
- <select id="getClassInfo4" parameterType="int" resultMap="getClassMap2">
- SELECT * FROM class WHERE c_id =#{id}
- </select>
- <resultMap type="Classes" id="getClassMap2">
- <id property="id" column="c_id"/>
- <result property="name" column="c_name"/>
- <association property="teacher" column="teacher_id" javaType="Teacher"
- select="getTeacher"></association>
- <collection property="students" column="c_id" ofType="Student"
- select="getStudent"></collection>
- </resultMap>
- <select id="getTeacher" resultType="Teacher">
- SELECT t_id id,t_name name FROM teacher WHERE t_id =#{id}
- </select>
- <select id="getStudent" resultType="Student">
- SELECT s_id id,s_name name FROM student WHERE class_id =#{id}
- </select>
- </mapper>
7、Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
答:Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。
在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,
那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
8、为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
答:Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
4、Mybatis是如何进行分页的?分页插件的原理是什么?
注:我出的。
答:Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10
5、简述Mybatis的插件运行原理,以及如何编写一个插件。
注:我出的。
答:Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
6、Mybatis执行批量插入,能返回数据库主键列表吗?
注:我出的。
答:能,JDBC都能,Mybatis当然也能。
11、Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
注:我出的。
答:不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;毕竟namespace不是必须的,只是最佳实践而已。
原因就是namespace+id是作为Map<String, MappedStatement>的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。
12、Mybatis中如何执行批处理?
注:我出的。
答:使用BatchExecutor完成批处理。
13、Mybatis都有哪些Executor执行器?它们之间的区别是什么?
注:我出的
答:Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。
BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
14、Mybatis中如何指定使用哪一种Executor执行器?
注:我出的
答:在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。
15、Mybatis是否可以映射Enum枚举类?
注:我出的
答:Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。
16、Mybatis映射文件中,如果A标签通过include引用了B标签的内容,请问,B标签能否定义在A标签的后面,还是说必须定义在A标签的前面?
注:我出的
答:虽然Mybatis解析Xml映射文件是按照顺序解析的,但是,被引用的B标签依然可以定义在任何地方,Mybatis都可以正确识别。
原理是,Mybatis解析A标签,发现A标签引用了B标签,但是B标签尚未解析到,尚不存在,此时,Mybatis会将A标签标记为未解析状态,然后继续解析余下的标签,包含B标签,待所有标签解析完毕,Mybatis会重新解析那些被标记为未解析的标签,此时再解析A标签时,B标签已经存在,A标签也就可以正常解析完成了。
---恢复内容结束---
Mybatis知识点总结的更多相关文章
- MyBatis知识点总结(一)
前言:本篇主要记录在MyBatis学习过程中的主要知识点. 1.mybatis环境的搭建,通过maven可以快速的进行环境的搭建. <!--文件版本--> <properties&g ...
- MyBatis 知识点梳理
简单地梳理下MyBatis相关的知识点,主要想让自己重新捡起以前学的框架,如果能给广大程序猿朋友有所帮助那就更好了.有疏漏的地方也欢迎大家评论指出.闲言少叙,进入正题....... MyBatis知识 ...
- mybatis知识点
1.Mybatis比IBatis比较大的几个改进是什么 a.有接口绑定,包括注解绑定sql和xml绑定Sql , b.动态sql由原来的节点配置变成OGNL表达式, c. 在一对一,一对多的时候引进了 ...
- MyBatis 知识点
2010年,随着开发团队转投Google Code旗下,ibatis 3.x 正式更名为 Mybatis. orm工具的基本思想 无论是 hibernate.Mybatis,orm工具有一个共同点: ...
- MyBatis知识点整理
1.MyBatis一般使用步骤 1.1获取Configuration实例或编写配置文件 //获取Configuration实例的样例 TransactionFactory transactionFac ...
- mybatis知识点(已掌握)
1.${} 和 #{} 的区别? ${} 直接显示传入数据,不能防止sql注入,一般用于传数据库对象(比如表名). #{} 传入数据被当成字符串,自动加上双引号,防止sql注入. 2.有哪些Execu ...
- 知名互联网公司校招 Java 开发岗面试知识点解析
天之道,损有余而补不足,是故虚胜实,不足胜有余. 本文作者在一年之内参加过多场面试,应聘岗位均为 Java 开发方向.在不断的面试中,分类总结了 Java 开发岗位面试中的一些知识点. 主要包括以下几 ...
- 后端——框架——持久层框架——Mybatis——《Mybatis从入门到精通》读书笔记——初篇
1.Mybatis知识点 框架的知识点大致可以分为三个部分 基础: 介绍编写增,删,改,查: 动态标签: config配置文件 Mapper配置文件 插件:常见的插件有三个 pageHelper:分页 ...
- ORM——Mybatis
引言 ORM 是 blablabla…… Mybatis知识点
随机推荐
- Java环境环境配置
1. 下载并安装JDK,假如安装在D盘 2. 右键计算机->属性->高级系统设置->环境变量 3. 点击新建系统变量:系统变量名:JAVA_HOME 系统变量值:D:\Progr ...
- 樱花漫地集于我心,蝶舞纷飞祈愿相随---总结 适者:survival of the fittest 适者:survival of the fittest
编程什么的最讨厌了,总是忘记一些乱七八糟的,看起来并没有什么乱用的,比如(::“<>{}, 还有交作业的时候总是忽略大小写<(▰˘◡˘▰)> 马马虎虎莫名其妙就错了,其实大小写 ...
- 创建.htaccess文件
在linux下创建.htaccess文件非常简单,直接新建一个文件并重命名为.htaccess即可. 下面我来讲下如何在Window下创建.htaccess文件 一般在本地电脑上是无法建立 .htac ...
- 找做IT的男朋友会不会没有隐私
找做IT的男朋友会不会没有隐私你不觉得自己在网上不断的“秀”啊,“晒”啊的行为才是根本所在吗?你应该怕自己的这种行为才对吧-—————————————————————————————————————— ...
- sql2008 无法附加数据库
sql2008 因为数据库正在使用,所以无法获得对数据库的独占访问权---还原或删除数据库的解决方法 数据库还原出现 3154错误 --主备份 --RESTORE DATABASE [NET_CN] ...
- SQL Server2012关于表内事项出现次数降序排列(存储过程)
USE [growup] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[S_GetRanking ...
- Jmeter—5 关联 响应数据传递-正则表达式提取器
在测试过程中,遇到一个问题:用户登录成功后服务器会返回一个登录凭证,之后所有的操作都需要带上此凭证.我们怎么获取登录凭证并传递给后续的操作? Jmeter提供了正则表达式提取器,用变量提取参数,后续通 ...
- 《Java中的包机制》
/* 包的机制:(1) */ package lee; public class PackageTest { public void Test(int num) { System.out.printl ...
- 团队开发——冲刺2.c
冲刺阶段二(第三天) 1.昨天做了什么? 把“开始游戏”.“退出游戏”.“取消”等文字按钮加工成游戏图标,美化游戏界面背景. 2.今天准备做什么? 因为收集的图标时比较杂乱,没有针对性,把游戏图标进行 ...
- 【OpenCV】图像的遍历
Mat类的两种遍历比较快的方式,分别给出了按行和按列遍历,以及运行过程图. 原图: 按行遍历过程图 按列遍历过程图 代码如下: //ptr逐行访问 void ptrScanX(Mat& src ...