MyBatis 知识点总结
Hibernate 与 MyBatis 的区别
- Hibernate 可以做到数据库无关性,而 MyBatis 不行。
- Hibernate 完全面向对象,Hibernate 由于是自动生成 SQL 语句,所以在性能优化上更加困难,MyBatis 由于是手动编写 SQL 语句,在 SQL 优化上面更加容易。
MyBatis 配置文件
SqlMapConfig.xml(核心配置文件)
在这个配置文件中需要配置数据库四要素(用户名、密码、URL、驱动的全限定类名)
xxxMapper.xml(映射文件)
MyBatis 核心类
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder 用于创建 SqlSessionFacoty,SqlSessionFacoty 一旦创建完成就不需要 SqlSessionFactoryBuilder 了,因为 SqlSession 是通过 SqlSessionFactory 创建的。所以可以将 SqlSessionFactoryBuilder 当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
SqlSessionFactory
SqlSessionFactory 是一个接口,接口中定义了 openSession 的不同重载方法,SqlSessionFactory 的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理 SqlSessionFactory
SqlSession
SqlSession 是一个面向用户的接口,sqlSession 中定义了数据库操作方法。每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将 SqlSession 实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。
示例:
开发中为什么通常使用 Mapper 动态代理开发
在不使用 Mapper 动态代理时,开发的代码:
弊端:
- 我们可以发现,在 UserDaoImpl 的方法中,sessionFactory.openSession() 显得很多余,因为如果该接口有多个方法,每个方法都需要写这句话,显得很麻烦。那此时 MyBatis 提供了一个 Mapper 动态代理的方式,帮我们实现这些方法。
- 通过字符串去调用标签定义的 SQL,这里存在硬编码。
Mapper 动态代理开发
Mapper 接口开发方法只需要程序员编写 Mapper 接口(相当于 Dao 接口),由 Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边 Dao 接口实现类方法。
Mapper 接口开发需要遵循以下规范:
- Mapper.xml 文件中的 namespace 与 mapper 接口的类路径相同。
- Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同。
- Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同。
- Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同。
配置文件的名称不一定必须要与对应的接口名相同,但为了方便我们都是这样做的。
具体步骤:
第一步:创建接口以及配置映射文件
第二步:在 sqlMapConfig.xml 中配置映射文件路径
测试:
通过 SqlSession 的 getMapper() 方法获取动态代理对象。
SqlMapConfig.xml 文件配置
properties 标签
用于加载外部配置文件,以及配置本地 property
typeAliases 标签
该属性用于自定义别名,在没有给 POJO 类起别名前,我们在配置文件必须使用全限定类名来描述这些类。如果给这些类起别名,那么我们就不需要使用全限定名称,直接写指定的别名即可。
注意:MyBatis 中所有别名大小写不明感(不管起的别名是大写还是小写,在使用别名时大小写都可以任意使用)
MyBatis 自带的别名
mappers 标签
<mapper resource="" />
使用相对于类路径的资源(现在的使用方式)
如: <mapper resource="sqlmap/User.xml" />
<mapper class="" />
使用 mapper 接口类路径
如: <mapper class="cn.itcast.mybatis.mapper.UserMapper"/>
注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。(Mapper 接口就是前面提到的 Dao 层接口)
<package name=""/>
注册指定包下的所有 mapper 接口
如: <package name="cn.itcast.mybatis.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。这样做是为了在程序运行时通过接口名,找到与自己同名的映射文件。
映射文件配置
- resultMap手动映射配置
手动配置的意义:在很多情况下,我们写的封装类并不是与数据库表中字段一一对应的,那么我们就需要使用手动映射这些没有对应的字段。
id 标签:
用于定义主键 ,非常重要。如果是多个字段,则定义多个 id。
- property:主键在 pojo 中的属性名
- column:主键在数据库中的列名
- result 标签:用于定义普通属性
我们不仅可以采用这种手动映射的方式,其实我们只需要在查询时给 userId 取一个别名,让别名与封装对象中属性的名称对应即可,即可使用传统的自动映射封装对象了。
${} 与 #{}
#{}:输入参数的占位符,相当于 jdbc 的?,该占位符可以防止 SQL 注入。
#{}:
select * from user where username like '%#{value}%'。
上述 MyBatis 中配置的语句,执行时会转换成 select * from user where username like '%'五'%' ,这样语句就执行失败(传入的参数是"五")。在使用#{}占位符时,大括号内部可以使用任何单词取到值。
${}:
select * from user where username like '%${value}%'
上述 MyBatis 中配置的语句,执行时会转换成 select * from user where username like '%五%' (传入的参数是"五")。在使用${}占位符时,大括号内部必须使用 value 才能取到参数的值
- 当参数为一个基本类型
当使用#{}占位符时,大括号内部填写任意字符,通常为 value 或者 v
当使用${}占位符时,大括号内部必须使用 value 取出参数值
- 当入参是一个封装类型
#{} 里面直接填写封装类型中的属性名即可,不需要使用 xxx.属性名获取值
- 传入多个参数
当使用Mapper 动态代理开发时,如果方法传入多个参数,那么我们通过#{index}的形式,依次取出参数值,index 从0 开始。
- 当入参是一个HashMap
parameterType 的配置规则
- 多个参数
Map 封装多个参数
- List 封装多个参数
- 通过注解传递多个参数
@Param 注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入 sql 语句中
resultType的配置规则
- 当返回值是一个List 集合时,resultType 只需要写集合的泛型即可。
- 当返回值是一个封装对象时,直接写封装对象的全限定类名即可,或者别名。
动态 SQL
if 标签
where 标签
where 标签可以自动添加 where,同时处理 where 关键字后面的第一个 and 关键字。所以我们在每一个条件子句前面加and 就行,where 标签会自动删除第一个 and
set 标签
Set 标签会自动删除最后的逗号,所以我们在每个子语句后面都加上逗号就行
- sql 标签
Sql 中可将重复的sql 提取出来,使用时用include 引用即可,最终达到sql 重用的目的。
如果要使用别的 Mapper.xml 配置的 sql 片段,可以在 refid 前面加上对应的 Mapper.xml 的 namespace
- foreach 标签
现在有这么一个需求:我们想传入多个 Id,然后查询这些Id 对应的User
foreach 标签属性:
- collection:需要遍历的集合名称
- item:每次遍历得到的Item 所保存的变量名
- open:在前面添加的sql 片段
- close:在结尾处添加的sql 片段
- separator:指定遍历的元素之间使用的分隔符
遍历封装在对象里的集合
遍历集合
遍历数组
与遍历集合一样,只不过在collection 属性中填array 即可。
多表关联
一对一映射
association 标签:用于配置一对一嵌套映射
注意:在单表查询中,我们可以使省略 POJO 对象中属性与表列名相同的映射,而在一对一关联对象的映射中不能省略,必须把每个属性都一 一对应起来。
一对多映射
- collection 标签:表示一对多映射;
- ofType 属性:表示在封装类一对多属性中集合泛型的类型。
MyBatis 与 Spring 整合的思路是什么
- SqlSessionFactory 对象应该放到 spring 容器中作为单例存在。
- 传统 dao 的开发方式中,应该从 spring 容器中获得 sqlsession 对象。
- Mapper 代理形式中,应该从 spring 容器中直接获得 mapper 的代理对象。
- 数据库的连接以及数据库连接池事务管理都交给 spring 容器来完成。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Java Spring 知识点总结
下一篇: 谈谈自己对于 AOP 的了解
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论