目录
问题二、在Mapper映射文件中,namespace名字,与mapper接口名字不一致
问题三:在传递多个参数时,xml文件中传入的值,不能与映射器接口中的属性相互对应,导致找不到
问题四:错误理解resultMap与resultMap的区别
一、什么是MyBatis?
MyBatis
是一个开源、轻量级的数据持久化框架,是 JDBC
和 Hibernate
的替代方案。MyBatis
内部封装了 JDBC
,简化了加载驱动、创建连接、创建 statement
等繁杂的过程,开发者只需要关注 SQL
语句本身。
MyBatis
支持定制化 SQL
、存储过程以及高级映射,可以在实体类和 SQL
语句之间建立mapping
映射关系,是一种半自动化的 ORM
实现。、
二、MyBatis的优点
MyBatis
是免费且开源的。- 与
JDBC
相比,减少了50%
以上的代码量。 MyBatis
是最简单的持久化框架,体积小巧并且学习门槛低。MyBatis
相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL 写在 XML 中,和程序逻辑代码分离,降低耦合度,便于同一管理和优化,提高了代码的可重用性。- 提供
XML
标签,支持编写动态SQL
语句。 - 提供映射标签,支持实体对象与数据库的表字段关系映射。
三、MyBatis Mapper
Mapper
映射器是 MyBatis
中最重要的文件,文件中包含一组 SQL
语句(例如查询、添加、删除、修改),这些语句称为映射语句或 SQL
映射语句。在mybatis框架中封装了jdbc,使用Mapper映射来对数据库操作。
四、动态SQL
动态 SQL 是 MyBatis
的强大特性之一。在 JDBC
或其它类似的框架中,开发人员通常需要手动拼接 SQL
语句。例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL
恰好解决了这一问题,可以根据场景动态的构建查询。
动态 SQL
只有几个基本元素,大量的判断都可以在 MyBatis
的映射 XML
文件里配置,以达到许多需要大量代码才能实现的功能。所以,使用动态 SQL
,可以 大大减少了编写代码的工作量,更体现了 MyBatis
的灵活性、高度可配置性和可维护性。
五、高级映射
在MyBatis框架中,主要靠映射来实现SQL语句,在映射过程中,有些数据是靠关系来来实现的,常见的关系有:
- 一对多,例如:角色和用户
- 一对一,例如:学生基本信息和学籍档案信息
- 多对多,例如:订单与商品
一、一对一关联查询
一对一关联查询可采用以下两种方式:
- 分步查询,通过两次或多次查询,为一对一关系的实体 Bean 赋值。
- 单步查询,通过关联查询实现。
例如:一个学生基本信息对应一个学籍档案。
在 MyBatis
中,通过 <resultMap>
元素的子元素 <association>
处理一对一级联关系。
在 <association>
元素中通常使用以下属性。
property
:指定映射到实体类的对象属性。column
:指定表中对应的字段(即查询返回的列名)。javaType
:指定映射到实体对象属性的类型。select
:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
二、一对多关联查询
在 MyBatis
中,通过 <resultMap>
元素的子元素 <collection>
处理一对多级联关系
在 <collection>
元素中通常使用以下属性。
property
:指定映射到实体类的对象属性。column
:指定表中对应的字段(即查询返回的列名)。javaType
:指定映射到实体对象属性的类型。select
:指定引入嵌套查询的子 SQL 语句,该属性用于关联映射中的嵌套查询。
三、resultMap与resultType的区别
查询映射的返回类型:我们提供的返回类型是 resultType
时,MyBatis
会自动把对应的值赋给 resultType
所指定对象的属性,而当我们提供的返回类型是 resultMap
时,MyBatis
会将数据库中的列数据复制到对象的相应属性上,可用于复制查询。
六、批处理
批处理是 JDBC
编程中的一种优化手段。JDBC
在执行 SQL
语句时,会将 SQL
+参数值,利用JDBC
驱动包,在底层使用基于TCP
协议的网络请求将SQL
语句发送到数据库。
在结合MyBatis框架进行批处理操作时,通常使用两种方式:
1使用动态SQL进行批量添加。
<!-- 使用动态SQL进行批量添加 -->
<insert id="insertWebsiteBatch">
INSERT INTO website(NAME,url,age,country,createtime)VALUES
<foreach collection="list" item="web" separator=",">
(#{web.name},#{web.url},#{web.age},#{web.country},now())
</foreach>
</insert>
2使用MyBatis BATCH模式进行批量添加。
public static SqlSession getBatchSqlSession() {
SqlSession session = null;
//创建批处理模式下的SqlSession
//ExecutorType.BATCH => BatchExecutor
//所以,使用的Executor执行器对象类型为BatchExecutor
if(factory != null) {
session = factory.openSession(ExecutorType.BATCH);
}
return session;
}
七、学习过程中遇到的问题
问题一:Mapper映射文件没有加载至主配置文件中
解决方法:将Mapper映射接口添加至主配置文件中,在加载时,会读取该SQL映射接口
问题二、在Mapper映射文件中,namespace名字,与mapper接口名字不一致
解决方法:
- mapper.xml文件中的namespace的名称要与mapper接口的地址相同。
- mapper接口中的方法名称要与mapper.xml中的statement id的名称相同。
- mapper接口中方法的输入参数的类型要与mapper.xml中statement的ParameterType指定的类型一致。
- mapper接口中方法的返回值的类型要与mapper.xml中statement的ResultType指定的类型一致。
问题三:在传递多个参数时,xml文件中传入的值,不能与映射器接口中的属性相互对应,导致找不到
解决方法:使用@Param
注解,当我们把参数传递给后台时,MyBatis
通过 @Param
提供的名称就会知道 #{name}
代表 name
参数,提高了参数可读性。
问题四:错误理解resultMap与resultMap的区别
在上述问题中,使用了resultType处理一对多的关联查询,返回的结果只能返回一条,而我查找到的结果有两条
解决方法:使用resultMap自定义结果集作为返回值类型
问题五:#{}
与${}
的区别没有理解透彻
在排序过程中,使用order by进行排序时,传入的参数使用#{},导致排序无效
解决方法:使用${},进行SQL语句的拼接,${}
一般用于在SQL中拼接数据库表名、视图或关键字,例如动态使用order by
进行排序时,就需要使用${}
来拼接排序字段名称和排序规则。
八、小结
一、使用MyBatis的必要性:
与传统的JDBC代码相比,可以省掉百分之95的代码量
MyBatis真正强大之处在于它的映射语句,XML(或者注解)的方式易于编写和应用
二、Mybatis核心组件:
SqlSessionFactoryBuilder(构造器):它会根据配置或者代码来生成SqlSessionFactory,采用的是分步构建的建造者模式。
SqlSessionFactory(工厂接口):依靠宅来生成SqlSession,使用的是工厂模式。
SqlSession(会话):一个既可以发送SQL执行返回结果,也可以获取Mapper的接口。在现有的技术中,一般我们会让其在业务逻辑代码中“消失”,而使用的是My Batis 提供的SQLMapper 接口编程技术,它能提高代码的可读性和可维护性o
SQL Mapper(映射器):MyBatis 新设计存在的组件,它由一个Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。它负责发送SQL去执行,并返回结果。
三、SQL映射文件常用元素:
select:查询语句
insert:插入语句
update:更新语句
delete:删除语句
sql:可被其他语句引用的重用语句块
cache 和 cache-ref: 命名空间的缓存配置引用
resultMap:用来描述如何从数据库结果集中加载对象
四、#{}
与${}
的区别
1.使用#{}会产生1个?占位符,并使用PreparedStatement进行处理。而${}则进行的是字符串的拼接。
2.使用#{}可以预防SQL注入,而${}无法防止SQL注入。
3.${}一般用于在SQL中拼接数据库表名、视图或关键字,例如动态使用order by 进行排序时,就需要使用${}来拼接排序字段名称和排序规则。