文章很长,建议收藏起来慢慢读! 总目录 博客园版 为您奉上珍贵的学习资源 :
免费赠送 :《尼恩Java面试宝典》持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备
免费赠送 经典图书:《Java高并发核心编程(卷1)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Java高并发核心编程(卷2)》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《Netty Zookeeper Redis 高并发实战》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 经典图书:《SpringCloud Nginx高并发核心编程》 面试必备 + 大厂必备 +涨薪必备 加尼恩免费领
免费赠送 资源宝库: Java 必备 百度网盘资源大合集 价值>10000元 加尼恩领取
尼恩Java面试宝典,35个最新pdf,含2000多页,不断更新、持续迭代 具体详情,请点击此链接
Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语
句本身,不需要花费精力去处理加载驱动、创建连接、创建statement 等繁杂的过程。程序员直
接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高。
MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了
几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
优点
与传统的数据库访问技术相比,ORM有以下优点:
XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并
可重用
很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库
MyBatis都支持)
组件维护
缺点
要求
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动 ORM映射工具。
频繁创建数据库连接对象、释放,容易造成系统资源浪费,影响系统性能。
可以使用连接池解决这 个问题。但是使用jdbc需要自己实现连接池。
sql语句定义、参数设置、结果集处理存在硬编码。
实际项目中sql语句变化的可能性较大,一旦发 生变化,需要修改java代码,系统需要重新编译,重新发布。不好维护。
使用preparedStatement向占有位符号传参数存在硬编码,
因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
结果集处理存在重复代码,处理麻烦。
如果可以映射成Java对象会比较方便。
答:
1)MyBatis 把 sql 语句从 Java 源程序中独立出来,放在单独的 XML 文件中编写,给程序的 维护带来了很大便利。
2)MyBatis 封装了底层 JDBC API 的调用细节,并能自动将结果集转换成 Java Bean 对象, 大大简化了 Java 数据库编程的重复工作。
3)因为 MyBatis 需要程序员自己去编写 sql 语句,程序员可以结合数据库自身的特点灵活 控制 sql 语句,因此能够实现比 Hibernate 等全自动 orm 框架更高的查询效率,能够完成复 杂查询。
MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。
由于它的异常强大,映射器的 XML 文件就显得相对简单。
在MyBatis开发中,涉及到主要开发要素是:Dao接口类,Mapper映射文件,以及PO类。
它们之间的关系如下:
映射器(mapper)的XML文件,有几个顶级元素:
1. 最基本的查询
上述配置类似于:
// Similar JDBC code, NOT MyBatis…
String selectMember = "select ID,NAME,PERSONMOBILE,ADDRESS,AGE FROM MEMBER_USER WHERE ID=?";
PreparedStatement ps = conn.prepareStatement(selectMember);
ps.setInt(1,id);
2. select 元素有很多属性允许你配置,来决定每条语句的作用细节
示范:
详细说明:
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType | 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
resultType | 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。 |
flushCache | 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。 |
useCache | 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。 |
fetchSize | 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
resultOrdered | 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 |
resultSets | 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。 |
1. 数据变更语句 insert,update 和 delete 的实现非常接近,参考如下配置:
select SEQ_MEMBER_USER.nextval from DUAL
INSERT INTO MEMBER_USER (ID, NAME, PERSONMOBILE, ADDRESS, AGE)
VALUES(#{id}, #{name}, #{personMobile}, #{address}, #{age})
update MEMBER_USER set
NAME = #{name},
PERSONMOBILE = #{personMobile},
ADDRESS = #{address},
AGE = #{age}
where id = #{id}
delete from MEMBER_USER where ID = #{id}
2 .Insert, Update 和 Delete 的属性:
属性 | 描述 |
---|---|
id | 命名空间中的唯一标识符,可被用来代表这条语句。 |
parameterType | 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。 |
flushCache | 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。 |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 |
useGeneratedKeys | (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 |
keyProperty | (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。 |
3. 关于insert元素
如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK了。示范:
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
如果是Oracle数据库,则用上面示范代码即可。selectKey 元素描述如下:
selectKey 的属性:
属性 | 描述 |
---|---|
keyProperty | selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
keyColumn | 匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 |
resultType | 结果的类型。MyBatis 通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。 |
order | 这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素 - 这和像 Oracle 的数据库相似,在插入语句内部可能有嵌入索引调用。 |
statementType | 与前面相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 语句的映射类型,分别代表 PreparedStatement 和 CallableStatement 类型。 |
这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。
1. 简单示范:
PRODID,PRODSERIAL,PRODNAME,CATEGORYNAME,PRODSPEC,PRODPRICE,PRODDESC,PRODIMAGE,ISNEW,ISRECOMMEND,ISSHOW,USERNAME,HANDLETIME,PRODTHUMBNAIL
2. 进阶用法:
${alias}.id,${alias}.username,${alias}.password
这个 SQL 片段可以被包含在其他语句中,例如:
ResultMap 的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系。resultmap构成元素:
1. id:
>> 一般对应数据库中改行的主键ID,设置此项可以提高Mybatis的性能
2. result
>> 映射到JavaBean的某个“简单类型”属性
3. association
>> 映射到javaBean的某个“复杂类型”属性,比如:javabean类
4. collection
>> 映射到javabean的某个“复杂类型”属性,比如:集合
正常情况,它用来作为将数据库字段与PO类的字段进行映射,比如:
OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,
它是一种功能强大的表达式语言。strusts/MyBatis大量使用了 OGNL表达式。
OGNL 表达式的作用:可以存取对象的属性
和调用对象的方法,通过OGNL 表达式可以迭代获取对象的结构图
MyBatis中使用了OGNL,MyBatis中可以使用OGNL的地方有两处:
上面这两处地方在MyBatis中处理的时候都是使用OGNL处理的。
e1 or e2
e1 and e2
e1 == e2
,e1 eq e2
e1 != e2
,e1 neq e2
e1 lt e2
:小于e1 lte e2
:小于等于,其他gt(大于),gte(大于等于)e1 in e2
e1 not in e2
e1 + e2
,e1 * e2
,e1/e2
,e1 - e2
,e1%e2
!e
,not e
:非,求反e.method(args)
调用对象方法e.property
对象属性值e1[ e2 ]
按索引取值,List
,数组和Map
@class@method(args)
调用类的静态方法@class@field
调用类的静态字段值上述内容只是合适在MyBatis中使用的OGNL表达式,完整的表达式点击这里。
#{ }: 是指上下文(环境)对象
OGNL 表达式获取属性举例:
对象person:{id:10,age:18,name:小明};
若上下文(环境)的对象是person,通过#{ } 可以直接获取到对象的属性值
#{id} 相当于 perosn.getId()
#{age} 相当于 person.getAge()
#{name} 相当于 person.getName()
1234
OGNL 在mybatis框架中的应用:
/* User 类*/
@Data
public class User {
private Long id;
private String name;
private BigDecimal salary;
}
/* 测试类 */
User user = new User();
user.setId(2L);
SqlSession session = factory.openSession();
//4、进行数据库操作(CRUD)
User user = session.selectOne("com.shan.hello.UserMapper.get", user);//将user作为上下文对象(javaBean类型)传入
/* 映射文件 */
<select id="get" parameterType="java.lang.Long" resultType="com.shan.hello.User">
select * from t_user where id = #{id} //上下文是javaBean类型,OGNL 表达式格式必须为 #{属性名}
</select>
12345678910111213141516171819
(1)javaBean对象,例如上面的User,则 OGNL 表达式格式必须为 #{属性名}
(2)map 对象,OGNL 表达式格式为 #{key}
(3)简单类型对象(基本类型、String类型),OGNL 表达式格式为 #{随便写,不过一般写得见名知意,增加代码的阅读性}
简单类型举例子:
/* 测试类 */
SqlSession session = factory.openSession();
//4、进行数据库操作(CRUD)
User user = session.selectOne("com.shan.hello.UserMapper.get", 2L);//将2L作为上下文对象(简单类型)传入
/* 映射文件 */
<select id="get" parameterType="java.lang.Long" resultType="com.shan.hello.User">
select * from t_user where id = #{id}//上下文是javaBean类型,OGNL 表达式格式可以写成#{aa},不过增强代码阅读性也会写成#{id}
</select>
123456789
1、语法:${属性名}
2、OGNL 表达式的作用:通过 ${属性名} 直接获取属性值,属性的内容。
1、sql语句分别使用#{} 和 ${}的实际情况:
(1)使用 #{}:
<select id="login" resultType="Client">
select id, username, password from client where username = #{username} and password = #{password} ;
select>
select id, username, password from client where username = ? and password = ?;
PreparedStatement.setString(1, "小明");
PreparedStatement.setString(2,"1");
(2)使用 ${}:
<select id="login" resultType="Client">
select id, username, password from client where username = ${username} and password = ${password} ;
select>
select id, username, password from client where username = "小明" and password = "1";
2、# 和 $ 的异同:
相同:都可以获取对象的信息。
不同:
使用# 传递的参数,会先转成占位符?,再通过设置占位符参数的方式设置值【会给值用单引号引起来】,不会导致sql注入问题,比较安全。
使用$ 传递的参数,直接把解析出来的数据作为sql语句的一部分。可能会出现sql注入安全问题,比较不安全。
{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。
Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用 PreparedStatement的set方法来赋值。
#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入
#{} 的变量替换是在DBMS 中;${} 的变量替换是在 DBMS 外
答:
1)#{}是预编译处理,${}是字符串替换。
2)Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
3)Mybatis 在处理 时,就是把 {}时,就是把 时,就是把{}替换成变量的值。
4)使用#{}可以有效的防止 SQL 注入,提高系统安全性。
1 ’%${question}%’ 可能引起SQL注入,不推荐
2 “%”#{question}“%” 注意:
因为#{…}解析成sql语句时候,会在变量外侧自动加单引号’ ',所 以 这里 % 需要使用双引号" ",不能使用单引号 ’ ',不然会查不到任何结果。
3 CONCAT(’%’,#{question},’%’) 使用CONCAT()函数,(推荐)
4 使用bind标签(不推荐)
方法1:顺序传参法
public User selectUser(String name, int deptId);
#{}里面的数字代表传入参数的顺序。
这种方法不建议使用,sql层表达不直观,且一旦顺序调整容易出错。
方法2:@Param注解传参法
public User selectUser(@Param("userName") String name, int @Param("deptId")
deptId);
#{}里面的名称对应的是注解@Param括号里面修饰的名称。
这种方法在参数不多的情况还是比较直观的,(推荐使用)。
方法3:Map传参法
public User selectUser(Map params);
#{}里面的名称对应的是Map里面的key名称。
这种方法适合传递多个参数,且参数易变能灵活传递的情况。(推荐使用)。
方法4:Java Bean传参法
public User selectUser(User user);
#{}里面的名称对应的是User类里面的成员属性。
这种方法直观,需要建一个实体类,扩展不容易,需要加属性,但代码可读性强,业务逻辑处理方 便,推荐使用。(推荐使用)。
第一种是使用 标签,逐一定义列名和对象属性名之间的映射关系。
第二种是使用sql列的别名功能,将列别名书写为对象属性名
比如T_NAME AS NAME,对象属性 名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。
有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那 些找不到映射关系的属性,是无法完成赋值的
还有很多其他的标签,
、 (被弃用) 、 、 、 ,
加上动态sql的9个标签
trim|where|set|foreach|if|choose|when|otherwise|bind等,
其中 为sql片段标签,通 过 标签引入sql片段, 为不支持自增的主键生成策略标签
第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。
第二 种是使用 sql 列的别名功能,将列别名书写为对象属性名,比如 T_NAME AS NAME,对象属性名一般是 name,小写,但是列名不区分大小写,Mybatis 会忽略列名大小 写,智能找到与之对应对象属性名,
你甚至可以写成 T_NAME AS NaMe,Mybatis 一样可以正常工作。
有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象 的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态 拼接sql的功能,
Mybatis提供了9种动态sql标签 trim|where|set|foreach|if|choose|when|otherwise|bind。
其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此 来完成动态sql的功能。
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将 清空。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存 储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如Ehcache。
要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:
3 ) 对 于 缓 存 数 据 更 新 机 制 , 当 某 一 个 作 用 域 ( 一 级 缓 存 Session/ 二 级 缓 存 Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将 被 clear。
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 解析 Xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以定义在任何地方,Mybatis 都可以正确识别。
原理是,Mybatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签尚未解析到, 尚不存在,
此时,Mybatis 会将 A 标签标记为未解析状态,然后继续解析余下的标签, 包含 B 标签,待所有标签解析完毕,Mybatis 会重新解析那些被标记为未解析的标 签,
此时再解析 A 标签时,B 标签已经存在,A 标签也就可以正常解析完成了。
Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内 部。
在 Xml 映射文件中,标签会被解析为 ParameterMap 对象,
其每个子元素会被解析为 ParameterMapping 对象。标签会被解析为 ResultMap 对象,其每个子元素会被解析为 ResultMapping 对象。
每一个、 、、标签均会被解析为 MappedStatement 对象,
标签 内的 sql 会被解析为 BoundSql 对象。
答:接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select@Update 等注解里面包含 Sql 语句来绑定,另外一种就是通过 xml 里面写 SQL 来绑 定,在这种情况下,要指定 xml 映射文件里面的 namespace 必须为接口的全路径名.
答:当 Sql 语句比较简单时候,用注解绑定;当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多
答:有联合查询和嵌套查询,
联合查询是几个表联合查询,只查询一次,通过在 resultMap 里面 配置 association 节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面 的结果的外键 id,去再另外一个表里面查询数据,也是通过 association 配置,但另外一个表的 查询通过 select 属性配置。
答:
MyBatis 里面的动态 Sql 一般是通过 if 节点来实现,
通过 OGNL 语法来实现,但是如果要 写的完整,必须配合 where,trim 节点,where 节点是判断包含节点有内容就插入 where,
否则不 插入,trim 节点是用来判断如果动态语句是以 and 或 or 开始,那么会自动把这个 and 或者 or 取掉。
答:
第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。
第二种是使用 sql 列的别名功能,将列别名书写为对象属性名,比如 T_NAME AS NAME,对 象属性名一般是 name,小写,但是列名不区分大小写,Mybatis 会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成 T_NAME AS NaMe,Mybatis 一样可以正常工 作。
有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
答:
1)通过在查询的 sql 语句中定义字段名的别名。
2)通过来映射字段名和实体类属性名的一一对应的关系。
载?
答:不能重载,因为通过 Dao 寻找 Xml 对应的 sql 的时候全限名+方法名的保存和寻找策
略。接口工作原理为 jdk 动态代理原理,运行时会为 dao 生成 proxy,代理对象会拦截接口
方法,去执行对应的 sql 返回数据。
答:
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;
如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
原因就 是 namespace+id 是作为 Map
如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。
有了 namespace,自然 id 就 可以重复,namespace 不同,namespace+id 自然也就不同。
答:
Mybatis 有三种基本的 Executor 执行器,SimpleExecutor、ReuseExecutor、 BatchExecutor。
1)SimpleExecutor:每执行一次 update 或 select,就开启一个 Statement 对 象,用完立刻关闭 Statement 对象。
2)ReuseExecutor:执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象, 而是放置于 Map
3)BatchExecutor:完成批处理。
答:
在 Mybatis 配置文件中,可以指定默认的 ExecutorType 执行器类型,也可以手动给 DefaultSqlSessionFactory 的创建 SqlSession 的方法传递 ExecutorType 类型参数。
答:能,JDBC 都能,Mybatis 当然也能。
答:配置文件设置 usegeneratedkeys 为 true
答:
1)Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用 Mybatis 的分页插件。
2)分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦 截待执行的 sql,然后重写 sql。
举例:
select * from student,
拦截 sql 后重写为:
select t.* from (select * from student)t limit 0,10
答:
1)Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑 判断和动态拼接 sql 的功能。
2)Mybatis 提供了 9 种动态 sql 标签:
trim|where|set|foreach|if|choose|when|otherwise|bind。
3)其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼 接 sql,以此来完成动态 sql 的功能。
答:
1)MyBatis 把 sql 语句从 Java 源程序中独立出来,放在单独的 XML 文件中编写,给程序的 维护带来了很大便利。
2)MyBatis 封装了底层 JDBC API 的调用细节,并能自动将结果集转换成 Java Bean 对象, 大大简化了 Java 数据库编程的重复工作。
3)因为 MyBatis 需要程序员自己去编写 sql 语句,程序员可以结合数据库自身的特点灵活 控制 sql 语句,因此能够实现比 Hibernate 等全自动 orm 框架更高的查询效率,能够完成复 杂查询。
答:当 Sql 语句比较简单时候,用注解绑定;当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多
答:
MyBatis 里面的动态 Sql 一般是通过 if 节点来实现,通过 OGNL 语法来实现,
但是如果要 写的完整,必须配合 where,trim 节点,
where 节点是判断包含节点有内容就插入 where,否则不 插入,
trim 节点是用来判断如果动态语句是以 and 或 or 开始,那么会自动把这个 and 或者 or 取掉。
答:
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;
如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
原因就 是 namespace+id 是作为 Map
如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。
有了 namespace,自然 id 就 可以重复,namespace 不同,namespace+id 自然也就不同。
答:
1)类的名字和数据库相同时,可以直接设置 resultType 参数为 Pojo 类
2)若不同,需要设置 resultMap 将结果名字和 Pojo 名字进行转换
答:
1)Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
2)Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的 类型相同
3)Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型 相同
4)Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。
https://www.cnblogs.com/nayitian/p/15075090.html
https://blog.csdn.net/weixin_45630258/article/details/122784096
https://www.cnblogs.com/wolf-lifeng/p/11153569.html
https://www.w3cschool.cn/mybatis/f4uw1ilx.html
https://www.cnblogs.com/kenhome/p/7764398.html
https://www.cnblogs.com/Charles-Yuan/p/9900279.html