MyBatis 属于 SSM 框架的持久层部分,是业务开展进行的基础。本文对 MyBatis 框架的内容及使用进行了分析介绍,重点分析了如何通过 MyBatis 的注解开发,实现数据持久化。
代码部分已经上传至 GitHub:
1. MyBatis 入门
1.1 MyBatis 概述
首先要清楚,什么是框架:
- 框架是软件开发中的一套解决方法,封装细节,提高开发效率。
- 三层架构:表现层、业务层、持久层。
- 表现层:展示数据。
- 业务层:处理业务需求。
- 持久层:与数据库交互。
目前最常用的框架:
- SSM 框架体系。包括 Spring, SpringMVC 和 MyBatis。
- Spring 用于技术整合。SpringMVC 用于 Web 层表现。MyBatis 用于数据持久化。
那么,MyBatis 是怎样的框架呢:
- MyBatis 是一个基于 Java 的持久层框架,封装了 JDBC,开发者不需要关注加载驱动、创建连接、创建 statement 等操作。
- 也是采用
XML 或注解
的方式,完成各种配置,并通过 Java 对象和 statement 中 sql 的动态参数进行映射,最终生成 SQL 语句。最后,MyBatis 框架执行 SQL 并将结果映射为 Java 对象返回。 - 使用
ORM 思想
实现结果集封装。ORM 是 Object Relational Mapping 对象关系映射,就是将数据库表和实体类和实体类的属性对应起来,通过操纵实体类就实现操纵数据库表。
回顾 JDBC,下面是一个例子:
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","ro ot", "root");
//定义sql 语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while(resultSet.next()) {
System.out.println(resultSet.getString("id")+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
那么 JDBC 存在的问题有哪些呢:
-
数据库连接创建、释放会造成资源浪费。
-
SQL 语句在代码中硬编码,造成代码不易维护,修改 SQL 还需要修改 Java 代码。
-
使用 PreparedStatement 向占位符 ? 传递参数存在硬编码,修改 SQL 还需要修改 Java 代码。
-
结果集解析也存在硬编码,SQL 变化导致代码变化,不易维护。如果将数据库记录封装为 POJO 对象解析更加方便。
1.2 MyBatis 环境搭建
MyBatis 环境搭建主要包括四步:
- 创建 Maven 工程并导入坐标。
- 创建实体类和 DAO 的接口。
- 创建 MyBatis 的主配置文件 SqlMapConfig.xml。
- 创建映射配置文件 IUserDao.xml。
环境搭建的时候要注意的内容:
- Mapper 和 DAO 其实是一个意思,命名的时候应该保持一致。
- MyBatis 映射配置文件位置必须和 DAO 接口的包结构相同。同时,mapper 标签的 namespace 属性取值必须是 DAO 接口的全类名。id 属性取值必须是 DAO 接口的方法名。按照这个要求写,所有功能就由 MyBatis 自动实现。
下面是编写测试类文件:
public class MybatisTest {
public static void main(String[] args)throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建 SqlSessionFactory 的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建工厂对象
SqlSessionFactory SqlSessionFactory factory = builder.build(in);
//4.使用 SqlSessionFactory 生产SqlSession 对象
SqlSession session = factory.openSession();
//5.使用 SqlSession 创建 dao 接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//6.使用代理对象执行查询所有方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//7.释放资源
session.close();
in.close();
}
}
可以学习到,MyBatis 需要的步骤包括:
- 读取配置文件。
- 创建 SqlSessionFactory 的构建者对象,并创建工厂对象。
- 创建 dao 接口代理对象。
- 使用代理对象执行 SQL。
2. MyBatis 注解开发
实际上,注解开发才是 MyBatis 最常用的部分。因此,学习 MyBatis 注解开发是最重要的部分。通过注解开发,可以减少编写 Mapper 映射文件。实际工作中,注解开发和映射开发(配置 xml)需要共同使用。例如样例工程就是,SqlMapConfig.xml 需要保存,而 IUserDaoConfig.xml 则不再需要,直接将 IUserDao 接口替换为注解开发版本。
2.1 常用注解
常用注解包括:
- @Insert:新增。
- @Update:更新。
- @Delete:删除。
- @Select:查询。
- @Result:结果集封装。
- @Results:与 @Result 共同使用,封装多个结果集。
- @ResultMap:引用 @Results 定义的封装。
- @One:一对一结果集封装。
- @Many:一对多结果集封装。
- @SelectProvidor:动态 SQL 映射。
- @CacheNamespace:注解二级缓存使用。
2.2 环境构建
首先构建坐标:
随后创建实体类:com.bluestragglers.domain.User.class
- 包括 Set、Get、toSring 方法。
- 继承、实现序列化接口 Serializable。
随后编写 DAO 接口:com.bluestragglers.dao.IUserDao.class
- 不需要编写对应的 daoconfig.xml 文件了,因为这个采用了注解开发。
最后编写 SqlMapConfig.xml 文件,实现与 MySQL 的连接。
最后,写一个测试类测试一下:
测试结果:
2.3 单表 CRUD
单表 CRUD 是最基本的操作。
首先在 IUserDao 中加入单表添加操作:
然后在 test 文件夹新建测试类 AnnotationCRUDTest:
最后,运行测试:
进行模糊查询:两种写法都可以。一个是字符串拼接,一个是参数占位符。
另一种测试:将属性全部改名,与数据库不一致,从而进行 CRUD 测试。
可以发现,直接测试的话,结果与属性不能相互对应。
使用 @Results 标签,配合内部的 @Result,就可以实现多表 CRUD 的返回值设置,从而可以将查询得到的值与属性值相匹配。
再次进行测试,可以发现查询与属性相匹配了。
为了重复使用 @Result 的配置,我们可以加入 id 属性。这样,其他地方就可以通过 @ResultMap(value={}) 实现重复使用了。
通过测试,可以看到可以重复使用。
2.4 多表 CRUD
为了实现多表查询,构建另一个表:账户 Account
在 @Result 标签内,可以看到,有 One 和 Many 属性,也就是多对一和多对多属性:
其中,还可以配置 fetchType,一般,对一的时候设置为 EAGER(立即加载),对多时设置为 LAZY(延迟加载):
重新完成编写,加入了 user 的多表查询,并采用了 @One 标签实现了多对一(MyBatis 也叫一对一)查询:
完成了多对一关系映射,再来尝试多对多关系映射(MyBatis 也叫一对多关系映射):
多表查询,无论是一对多,还是一对一,都只要关注两个属性:select 和 fetchType。select 是方法名,fetchType 是加载时机。
2.5 缓存配置
MyBatis 自动配置一级缓存,所以不用管理一级缓存。
二级缓存,可以保证后续一样的查询操作不会真正操作两次,而是会检查缓存,直接调用缓存的信息进行返回。
开启二级缓存,需要在 SqlMapConfig.xml 的
随后,在 IUserDao 类前加入 @CacheNamespace(blocking = true)
最后,编写测试类进行测试:
通过二级缓存,实现了一次查询,关闭后再重启,依旧能够获取答案:
参考内容
本文参考了以下内容:
Comments | NOTHING