官网文档:https://mybatis.org/mybatis-3/zh/getting-started.html
一、ORM
1、什么是ORM
ORM,Object Relational Mapping,对象和关系的映射(Object 对象,Mapping 映射,Relation 关系型数据库),ORM框架要解决的是程序对象和关系型数据库互相映射的问题。
2、ORM框架有那些
Hibernate
- 优点
- 全自动
- 缺点
- 使用get、save、update方法操作是所有字段,没有办法使用部分字段。
- 自动生成SQL语句,优化比较难
- 不支持动态SQL
Mybatis
“半自动化”的ORM 框架MyBatis 就解决了这几个问题。“半自动化”是相对于Hibernate 的全自动化来说的,也就是说它的封装程度没有Hibernate 那么高,不会自动生成全部的SQL 语句,主要解决的是SQL 和对象的映射问题。在MyBatis 里面,SQL 和代码是分离的,所以会写SQL 基本上就会用MyBatis,没有额外的学习成本。
核心特性
- 使用连接池对连接进行管理
- SQL 和代码分离,集中管理
- 结果集映射
- 参数映射和动态SQL
- 重复SQL 的提取
- 缓存管理
- 插件机制
后续将介绍Mybatis-Plus 整合应用将快速的提高开发效率,让开发人员更加的关注业务的开发。
二、Mybatis核心对象及生命周期
官方文档:https://mybatis.org/mybatis-3/zh/configuration.html
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。
SqlSessionFactory
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
Session
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
Mapper
映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。 也就是说,映射器实例应该在调用它们的方法中被获取,使用完毕之后即可丢弃。 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,在这个作用域上管理太多像 SqlSession 的资源会让你忙不过来。
三、Mybatis 入门案例
github:git@github.com:stopping5/orm-guide.git
1. 引入mybatis相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>stopping-orm</artifactId>
<groupId>com.stopping</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mybatis-base</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!-- 8.0.13版本需要使用cj Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
</project>
2. mybatis-config配置文件
配置文件节点结构
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
配置文件说明
在这个案例中,只用到了environments和mappers两个配置信息。
environments
environments主要是配置事务管理和数据源的,我们这里只有配置了一个数据源,当我们业务系统的数据库是不同业务不同库时,需要采取多数据源配置,后续会介绍到。
mappers
mappers是映射到我们的mapper文件告诉mybatis从哪里找到SQL语句。一共有四种方式:
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
案例配置文件
<?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="development">
<environment id="development">
<!-- 事务配置 -->
<transactionManager type="JDBC"/>
<!-- 数据源 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value='jdbc:mysql://localhost:3306/test?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC'/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- mapper -->
<mappers>
<mapper resource="mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
3. 实体类
以简单的用户信息为例
数据库表结构user
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`avatar` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `UK_ob8kqyqqgmefl0aco34akdtpe` (`email`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
对应的实体类
@Data
@Accessors(chain = true)
public class User implements Serializable {
/**
* id
* */
private Integer id;
/**
* 头像
* */
private String avatar;
/**
* 邮箱
* */
private String email;
/**
* 账号
* */
private String name;
/**
* 密码
* */
private String password;
/**
* 用户名
* */
private String username;
}
4. mapper
UserMapper.java 需要通过UserMapper.xml进行绑定,通过UserMapper.xml中的namespace命名空间绑定到UserMapper.java。
UserMapper.java
@Mapper
public interface UserMapper {
/**
* 查询用户信息
* */
List<User> selectUser();
/**
* 新增用户
* */
void insertUser(@Param("user")User user);
}
UserMapper.xml
在UserMapper.xml中就编写sql的位置,除了select、insert等curd的标签之外,还有动态的sql例如if、choose、trim、foreach,后续将对这些标签进行详细的介绍。
<?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.stopping.mapper.UserMapper">
<insert id="insertUser" parameterType="com.stopping.model.User">
insert into user(name,email,username,password) value(
#{user.name},
#{user.email},
#{user.username},
#{user.password});
</insert>
<select id="selectUser" resultType="com.stopping.model.User">
select * from user order by id;
</select>
</mapper>
到目前为止,我们已经有了数据源、事务管理、Mapper映射、实体类。
5. 测试
class UserMapperTest {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//通过调用sqlSession封装的方法获取
User user = new User();
user.setName("tom").setUsername("tom").setEmail("1111@cc.com").setPassword("123456");
userMapper.insertUser(user);
List<User> users = userMapper.selectUser();
for (User u : users) {
System.out.println("获取姓名:"+u.getName());
}
}
}
输出结构
获取姓名:stopping
获取姓名:tom
获取姓名:job