什么是MyBatis?
MyBatis是一个半自动的ORM框架,其本质是对JDBC的封装。使用MyBatis不需要写JDBC代码,但需要程序员编写SQL语句。之前是apache的一个开源项目iBatis,2010年改名为MyBatis。
补充:
Hibernate也是一款持久层ORM框架,多年前的市场占有率很高,但近年来市场占有率越来越低。
MyBatis与Hibernate的比较:
- MyBatis是一个半自动的ORM框架,需要手写SQL语句。
- Hibernate是一个全自动的ORM框架,不需要手写SQL语句。
- 使用MyBatis的开发量要大于Hibernate。
为什么Hibernate市场占有率越来越低:
- 对于新手学习Hibernate时间成本比MyBatis大很多,MyBatis上手很快。
- Hibernate不需要写SQL语句是因为框架来生成SQL语句。对于复杂查询,开发者很难控制生成的SQL语句,这就导致SQL调优很难进行。
- 之前的项目功能简单,数据量小,所以使用Hibernate可以快速完成开发。而近年来项目的数据量越来越大,而互联网项目对查询速度要求也很高,这就要求我们一定要精细化的调整SQL语句。此时灵活性更强,手动编写SQL语句的MyBatis慢慢代替了Hibernate使用。
- 在高并发、大数据、高性能、高响应的互联网项目中,MyBatis是首选的持久框架。而对于对性能要求不高的比如内部管理系统等可以使用Hibernate。
MyBatis入门
环境搭建
-
将SQL文件导入数据库
-
创建maven工程,引入依赖
<dependencies> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- mysql驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> </dependencies>
-
创建mybatis核心配置文件SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 配置环境 --> <environments default="mysql"> <environment id="mysql"> <!-- 事务类型 --> <transactionManager type="JDBC"></transactionManager> <!-- 数据源 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>
-
将log4j.properties文件放入resources中,让控制台打印SQL语句。
-
创建实体类
public class User { private int id; private String username; private String sex; private String address; // 省略getter/setter/构造方法/toString方法 }
创建持久层接口和映射文件
-
在java目录创建持久层接口
public interface UserMapper { List<User> findAll(); }
-
在resource目录创建映射文件
<?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"> <mapper namespace="com.java.mapper.UserMapper"> <select id="findAll" resultType="com.java.pojo.User"> select * from user </select> </mapper>
-
将映射文件配置到mybatis核心配置文件中
<!-- 注册映射文件 --> <mappers> <mapper resource="com/java/mapper/UserMapper.xml"> </mapper> </mappers>
映射文件注意事项:
映射文件要和接口名称相同。
映射文件要和接口的目录结构相同。
映射文件中
namespace
属性要写接口的全名。映射文件中标签的
id
属性是接口方法的方法名。映射文件中标签的
resultType
属性是接口方法的返回值类型。映射文件中标签的
parameterType
属性是接口方法的参数类型。映射文件中
resultType
、parameterType
属性要写全类名,如果是集合类型,则写其泛型的全类名。
测试持久层接口方法
@Test
public void testFindAll() throws Exception {
// (1)读取核心配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// (2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
// (4)SqlSessionFactory对象获取SqlSession对象
SqlSession session = factory.openSession();
// (5)SqlSession对象获取代理对象
UserMapper userMapper = session.getMapper(UserMapper.class);
// (6)代理对象执行方法
List<User> all = userMapper.findAll();
all.forEach(System.out::println);
// (7)释放资源
session.close();
is.close();
}
MyBatis核心对象及工作流程
MyBatis核心对象
-
SqlSessionFactoryBuilder
SqlSession 工厂构建者对象,使用构造者模式创建SqlSession工厂对象。
-
SqlSessionFactory
SqlSession工厂,使用工厂模式创建SqlSession对象。
-
SqlSession
该对象可以操作数据库,也可以使用动态代理模式创建持久层接口的代理对象操作数据库。
-
Mapper
持久层接口的代理对象,他具体实现了持久层接口,用来操作数据库。
MyBatis工作流程
- 创建SqlSessionFactoryBuilder对象
- SqlSessionFactoryBuilder对象构建了SqlSessionFactory对象:构造者模式
- SqlSessionFactory对象生产了SqlSession对象:工厂模式
- SqlSession对象创建了持久层接口的代理对象:动态代理模式
- 代理对象操作数据库
使用SqlSession操作数据库
除了代理对象能够操作数据库,SqlSession也能操作数据库。只是这种方式在开发中使用的较少,接下来我们使用SqlSession操作数据库:
@Test
public void testFindAll2() throws Exception {
// (1)读取核心配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// (2)创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// (3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
SqlSessionFactory factory = builder.build(is);
// (4)SqlSessionFactory对象获取SqlSession对象
SqlSession session = factory.openSession();
// (5)SqlSession直接操作数据库
List<User> users = session.selectList("com.java.mapper.UserMapper.findAll");
users.forEach(System.out::println);
// (6)关闭资源
session.close();
is.close();
}
Mapper动态代理原理
Mapper动态代理:
- SqlSession的getMapper方法,最终是调用的是JDK动态代理方法,生成一个代理对象,类型就是传入的接口类型。
- MapperProxy对象通过调用MapperMethod的execute方法定义了代理方式,该方法的底层调用的是SqlSession的方法。