文章目录
- 一、简介
- 二、HelloWord
- 2.1 环境搭建
- 2.2 创建全局配置文件
- 2.3 创建工具类
- 2.4 创建数据库表和对应的JavaBean
- 2.5 创建SQL映射文件
- 2.6 非接口式与接口式编程
- 2.6.1 非接口式编程
- 2.6.2 接口式编程⭐
- 2.7 简单总结
学习地址🔗
- https://www.bilibili.com/video/BV1mW411M737
- https://www.bilibili.com/video/BV1NE411Q7Nx
- 官网文档
一、简介
💬概述:MyBatis是一个半自动、轻量级的持久化层(ORM)框架,原是Apache的一个开源项目iBatis,后面该项目迁移到Google,iBatis(3.0之后的版本)也改名为MyBatis
❓ 关于MyBatis的介绍解释
- 半自动:MyBatis框架需要开发人员在xml文件或注解中手动创建SQL语句(或通过插件生成),才能将SQL执行结果与对应的JavaBean建立映射关系,然后通过JavaBean获取结果集(而全自动只需根据对应的JavaBean就能获取到SQL的执行结果集)
- 轻量级:MyBatis需要配置的依赖(jar包)较少,也不需要额外添加其他依赖,整体体积也较小,可以独立使用
- 持久化层框架:持久化简单理解就是将数据永久地存储到数据库中
- ORM框架:ORM是指Object Relational Mapping,即对象关系映射,ORM框架会根据xml映射文件(元数据)将JavaBean与数据库中对应的表建立映射关系,从而将对象持久化到数据库中
🔑优点(参考博文:MyBatis面试题(2020最新版))
- 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在xml映射文件里,解除SQL与Java代码的耦合,便于统一管理
- 提供xml标签,支持编写动态SQL语句,并可重用
- 与JDBC相比,减少了代码量,消除了大量冗余的代码,不需要手动开关连接
- 很好的与各种数据库兼容(MyBatis底层使用JDBC来连接数据库,只要JDBC支持的数据库MyBatis都支持)
- 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护
- 能够与Spring很好的集成
🔑其他与数据库交互的技术
-
工具类
- 常见:原生JDBC、DBUtils、Spring中的JdbcTemplate
- 缺点
① SQL语句夹杂在Java代码中,耦合度高导致硬编码内伤
② 实际开发中SQl语句会经常需要优化修改,后期维护困难
-
全自动ORM框架
-
常见:Hibernate是典型的全自动ORM框架
-
缺点(相对于MyBatis)
① 难以处理复杂的SQL语句
② SQL语句都是框架内自动生成的,开发人员无法对SQL语句进行优化或特殊化处理(HQL可以解决)
③ 基于全自动、全映射的特点,实现大量字段的JavaBean进行部分字段映射比较困难💡 全映射是指查询表记录时,只能把查询出全部字段,不能查询部分字段
-
二、HelloWord
2.1 环境搭建
① 在idea中创建普通的maven工程,然后在maven工程的pom.xml文件中添加插件标签,设置工程编译打包时的资源文件,该操作必须设置,如果不设置,会因为maven的资源过滤而找不到对应的映射文件
<build>
<!-- maven的资源过滤 -->
<resources>
<resource>
<!-- 工程进行编译打包时把src/main/java目录下的properties文件和xml文件也打包进去 -->
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
❓ 关于maven工程的编译打包文件
- 在maven工程进行编译打包时,默认会把src/main/resource目录下的所有文件(包括.properties和.xml文件)拷贝到target/classes目录下
- 而对于src/main/java目录下的文件,maven工程在编译打包时只会把.java文件拷贝到target/classes目录下,不会处理其他文件(maven的资源过滤)
❓ 关于
<resource>
标签中三个子标签(参考博文:Maven的pom.xml中resources标签的用法)
<directory>
:指定需要进行文件打包的目录,一般指定为src/main/java、src/main/resource<includes>
:指定需要进行打包的文件。在<includes>
中使用<include>
子标签指定打包的文件,可以指定多种不同类型的文件<filtering>
:指定在打包(拷贝)文件前是否需要对文件进行预编译(比如将.java文件编译成.class文件后再进行拷贝),默认值是false,即不进行预编译
② 导入相关jar包:mybatis.jar(MyBatis依赖)、mysql-connector-java.jar(MySQL连接驱动)、junit.jar(测试依赖)
③ 在src/main/java目录下创建包com.key.mybatis,再在mybatis包下创建dao、utils、entity三个包,分别用于存放持久层接口及其对应的映射文件、工具类、实体类,在src/test/java下同样建立com.key.mybatis
2.2 创建全局配置文件
在src/main/resource目录下创建一个mybatis-config.xml文件,然后将官方文档中关于MyBatis的全局配置文件内容复制过来
<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置环境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- 注册映射文件 -->
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
2.3 创建工具类
在utils包下创建一个工具类MyBatisUtil,类中使用静态代码块获取SqlSessionFactory
工厂对象,并创建方法,方法中通过工厂对象获取SqlSession
会话对象
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
/* 静态代码块中获取SqlSessionFactory对象 */
static {
// 先初始化输入流
InputStream in = null;
try {
// 1. 获取全局配置文件的资源路径
String resource = "mybatis-config.xml";
// 2. 根据全局配置文件的路径获取对应输入流
in = Resources.getResourceAsStream(resource);
// 3. 根据输入流获取SqlSessionFactory对象
sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4. 关闭输入流
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据SqlSessionFactory获取SqlSession对象
*/
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
2.4 创建数据库表和对应的JavaBean
🔑创建数据库表——用户表
use `mybatis`;
/* 创建用户表 */
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT UNSIGNED NOT NULL PRIMARY KEY UNIQUE AUTO_INCREMENT COMMENT '主键id',
`user_name` VARCHAR(20) NOT NULL COMMENT '用户名',
`password` VARCHAR(20) NOT NULL UNIQUE COMMENT '密码'
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT '用户表';
/* 插入几条数据 */
INSERT INTO `user`(`user_name`, `password`)
VALUES('周星驰', '12345');
INSERT INTO `user`(`user_name`, `password`)
VALUES('周慧敏', '12444');
INSERT INTO `user`(`user_name`, `password`)
VALUES('周润发', 'abcde');
INSERT INTO `user`(`user_name`, `password`)
VALUES('周华健', 'yyds');
🔑创建数据库表对应的JavaBean
public class User {
private Integer id;
private String username;
private String password;
public User() {
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
2.5 创建SQL映射文件
在src/main/java目录下的dao中创建一个UserMapper.xml文件,作为User类对应的SQL映射文件,然后将官方文档中的相关内容复制过去
<?xml version="1.0" encoding="utf8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
<!--
SQL标签编写
-->
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
2.6 非接口式与接口式编程
2.6.1 非接口式编程
① 在SQL映射文件UserMapper.xml中创建SQL语句,并修改相关参数
需要修改的参数 | 修改后的值 | 解释 |
---|---|---|
根标签<mapper> 中的名称空间namespace 属性值 | com.key.mybatis.dao.UserDao | 非接口式编程中该属性可设置任意值,但建议写成全类名的形式 |
<select> 标签的id 属性值 | selectUser | 非接口式编程中该属性可设置任意值 |
<select> 标签的resultType 属性值 | com.key.mybatis.entity.User | 设置结果集的类型 |
<select> 标签中的SQL语句 | select id ‘id’, user_name ‘username’, password ‘password’ from user where id = #{id} | SQL语句编写,其中#{id} 相当于一个占位符,用于获取传递过来的id值 |
<mapper namespace="com.key.mybatis.dao.UserDao">
<!--
SQL标签编写
-->
<!-- HelloWord测试SQL1.0,非接口式 -->
<select id="selectUser" resultType="com.key.mybatis.entity.User">
select `id` 'id', `user_name` 'username', `password` 'password'
from `user`
where `id` = #{id}
</select>
</mapper>
❓ 为什么SELECT语句中要给每一个字段取别名:因为user表中的user_name字段与
User
类中的成员变量username名称不一致,MyBatis无法为它们两个建立映射关系,也就无法将查询记录中user_name的值赋值给username,因此需要给每一个字段分别取一个与对应成员变量名一样的别名;如果不给每一个字段取别名,而是直接使用*
简单代表所有字段,查询出来的User
对象中username属性值为null
② 在全局配置文件中,修改数据源<dataSource>
的四个属性,通过<mapper>
标签注册SQL映射文件UserMapper.xml
<mappers>
<mapper resource="com/key/mybatis/dao/UserMapper.xml"/>
</mappers>
③ 在src/test/java目录下的mybatis包下创建测试类HelloWordTest
,测试类中添加测试方法testMtBatis01()
,方法中进行以下步骤
3.1 先通过MyBatis工具类获取SqlSession
会话对象
3.2 然后调用SqlSession
对象的selectOne()
方法,并返回一个结果集对象(User
对象),selectOne()
方法中需要设置两个参数,分别对应映射文件中<select>
标签的id
属性值、SQL语句中的id
值(即#{id}
需要获取的值)
❓ 关于
selectOne()
方法的两个参数
- 参数1 --> 对应映射文件中
<select>
标签的id
属性值(SQL语句的唯一标识),与映射文件进行绑定,因为有可能在不同的SQL映射文件中存在相同的id
属性值,所以在selectOne()
中只写上id
的值可能会引起歧义,因此建议在id
值前加上名称空间namespace
的值(映射文件的唯一标识)- 参数2 --> 对应SQL语句中的
id
值,这里的id
是指数据库表中的id
字段(主键)。该参数的作用相当于JDBC中的填充占位符(设置参数),而对应的占位符就是SQL语句中的#{id}
3.3 打印结果集对象
3.4 最后调用close()
方法关闭SqlSession
对象
@Test
public void testMyBatis01() {
// 1. 从MyBatis工具类中获取SqlSession对象
SqlSession sqlSession = MyBatisUtil.getSqlSession();
// 2. 根据sqlSession对象执行映射文件中对应的SQL语句,并获取结果集对象
User user = sqlSession.selectOne(
"com.key.mybatis.dao.UserDao.selectUser",
1);
// 3. 打印获取到的结果集对象
System.out.println(user);
// 4. 关闭sqlSession对象
sqlSession.close();
}
④ 测试结果
2.6.2 接口式编程⭐
① 创建SQL映射文件对应的持久层接口UserDao,接口中添加操作数据库的方法
public interface UserDao {
/**
* 查询所有用户信息
* @return 返回用户集合
*/
List<User> getAllUsers();
}
② 在SQL映射文件UserMapper.xml中创建SQL语句,并修改相关参数
需要修改的参数 | 修改后的值 | 解释 |
---|---|---|
根标签<mapper> 中的名称空间namespace 属性值 | com.key.mybatis.dao.UserDao | 设置与映射文件对应的持久层接口的全类名,将接口与SQL映射文件进行绑定 |
<select> 标签的id 属性值 | getAllUsers | 设置与SQL语句对应的持久层接口中的方法名,将接口方法与SQL语句进行绑定 |
<select> 标签的resultType 属性值 | com.key.mybatis.entity.User | 设置结果集的类型 |
<select> 标签中的SQL语句 | select id ‘id’, user_name ‘username’, password ‘password’ from user | SQL语句编写 |
<mapper namespace="com.key.mybatis.dao.UserDao">
<!--
SQL标签编写
-->
<!-- HelloWord测试SQL2.0,接口式 -->
<select id="getAllUsers" resultType="com.key.mybatis.entity.User">
select `id` 'id', `user_name` 'username', `password` 'password'
from `user`
</select>
</mapper>
③ 在全局配置文件中,修改数据源<dataSource>
的四个属性,通过<mapper>
标签注册SQL映射文件UserMapper.xml(与非接口式编程一样)
④ 在src/test/java目录下的mybatis包下创建测试类HelloWordTest
,测试类中添加测试方法testMtBatis02()
,方法中进行以下步骤
4.1 先通过MyBatis工具类获取SqlSession
会话对象
4.2 然后调用SqlSession
对象的getMapper()
方法,并返回UserDao
接口的一个实现类对象mapper
(映射对象)
4.3 通过mapper
对象调用接口中的getAllUsers()
方法,并获取结果集(List集合)
4.4 打印结果集
4.5 最后调用close()
方法关闭SqlSession
对象
@Test
public void testMyBatis02() {
// 1. 从工具类中获取SqlSession对象
SqlSession sqlSession = MyBatisUtil.getSqlSession();
// 2. 加载EmployDao接口获取接口对应映射器对象
UserDao mapper = sqlSession.getMapper(UserDao.class);
// 3. 通过mapper接口的方法,获取结果集对象
List<User> users = mapper.getAllUsers();
// 4. 打印结果
users.forEach(System.out :: println);
// 5. 关闭sqlSession对象
sqlSession.close();
}
④ 测试结果
2.7 简单总结
🔑关于接口式编程
- 使用原生API与MyBatis框架的区别
- 原生API:需要为持久层接口(XxxDao)手动创建一个实现类(XxxDaoImpl)
- MyBatis框架:无需为持久层接口创建实现类,只需将接口(XxxDao)与SQL映射文件(XxxMapper.xml)进行绑定以及将接口中的方法与映射文件中的SQL语句进行绑定
- mapper对象(映射对象):MyBatis在将接口与SQL映射文件进行绑定时,会为该接口创建一个代理对象,该代理对象就是
sqlSession.getMapper(XxxDao.class)
方法返回的mapper
对象(类型是还是XxxDao
),通过该代理对象就可以调用接口中的方法(具体怎么创建后续会分析源码解释)
🔑关于SqlSession对象
SqlSession
对象代表持久层与数据库进行的一次会话,类似于IO流对象,用完要及时关闭(释放资源),不然可能会引起内存泄漏、性能降低等问题SqlSession
对象底层中使用的还是Connection
数据库连接对象,因此它与Connection
对象一样都是非线程安全的,不能被共享(不能设置为全局变量),每次使用应该取获取新的对象
🔑两个重要的xml配置文件
① MyBatis全局配置文件:用于设置数据库连接池、数据源信息、事务管理以及注册映射文件等
> 💡 MyBatis全局配置可以不使用xml文件实现,可以直接创建配置类,类中设置各个属性,但比较麻烦
② SQL映射文件:是必须要有的文件,文件中创建并保存SQL语句以及设置每一个SQL语句的映射信息,将SQL语句抽取出来,与Java代码分隔开,既降低了代码的耦合度,也方便开发人员对SQL语句进行特殊处理和优化