前言
从今天开始学习 Mybatis, 冲鸭.
参考资料
环境
- jdk 1.8
- mysql 8.0+
- maven 4.0
- IDEA
Mybatis 简介
什么是 MyBatis?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
三层架构
- 表现层: 展示数据
- 业务层: 处理业务需求
- 持久层: 与数据库交互
所以 MyBatis 是与数据库打交道的框架.
为什么要学 Mybatis?
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
入门程序
0. 准备工作
0.1 目录结构
0.2 建立数据库
1. 创建一个 maven 项目
1.1 引入 pom.xml 依赖
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2. 写工具类 MybatisUtils.java
2.1 从 XML 中构建 SqlSessionFactory
因为这些代码都是固定的,所以将其封装为工具类.
2.1.1 使用 mybatis 获取 sqlSessionFactory 对象
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。
com.waciao.utils.MybatisUtils
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
2.1.2 从 SqlSessionFactory 中获取 SqlSession
既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
com.waciao.utils.MybatisUtils
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
2.1.3 完整的 MybatisUtils
package com.waciao.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @Author: Waciao
* @Date: 2020/3/17 11:20
* @Version: 1.0
* @Github: https://github.com/byojiaoxianz7
*/
// 工具类 sqlSessionFactory --> sqlSession
// 这一段代码属于固定格式, 所以封装成工具类
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
/**
* 1. 使用mybatis获取sqlSessionFactory对象
*/
String resource = "mybatis-config.xml"; // resource下的mybatis-config.xml
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 2. 从 SqlSessionFactory 中获取 SqlSession
* 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
* SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
*
* @return
*/
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
3. 写 mybatis-config.xml, 配置数据库连接信息
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
<?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>
<!--环境 默认选择development环境-->
<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/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="12345678"/>
</dataSource>
</environment>
</environments>
</configuration>
4. 写实体类 User.java
构造
- 有参
- 无参
- Getter and Setter
- toString
package com.waciao.pojo;
/**
* @Author: Waciao
* @Date: 2020/3/17 11:32
* @Version: 1.0
* @Github: https://github.com/byojiaoxianz7
*/
// 实体类
public class User {
private Integer id;
private String name;
private String pwd;
public User() {
}
public User(Integer id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
5. 写接口 UserMapper.java
package com.waciao.dao;
import com.waciao.pojo.User;
import java.util.List;
/**
* @Author: Waciao
* @Date: 2020/3/17 11:33
* @Version: 1.0
* @Github: https://github.com/byojiaoxianz7
*/
public interface UserMapper {
/**
* 获取所有用户
* @return
*/
List<User> getUserList();
}
6. 写实现类 Usermapper.xml
在 namespace
com.waciao.dao.UserMapper
中定义了一个名为getUserList
的映射语句,这样就可以用全限定名com.waciao.dao.UserMapper.getUserList
来调用 sql 语句了.
id 对应 UserMapper 里的方法名 resultType 里填执行 sql 语句之后返回的结果集,在 UserMapper 中可以看到, getUserList 方法返回的是一个 List<User> ,所以填集合里泛型的东西,就是 User.
<?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.waciao.dao.UserMapper">
<select id="getUserList" resultType="com.waciao.pojo.User">
SELECT * FROM mybatis.user;
</select>
</mapper>
到目前为止,所有的文件都写完了,接下来就是测试一下能不能成功跑起来
7. 写测试类
7.1 获得 sqlSession 对象
调用工具类即可
SqlSession sqlSession = MybatisUtils.getSqlSession();
7.2 执行 sql
存在几个问题
怎么执行 sql?
首先需要拿到 sql
怎么拿到 sql?
要么从 UserMapper 里拿,要么从 xml 里拿,因为是面向接口编程,所以直接从UserMapper 拿就行了
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
get到接口之后返回,就可以使用接口里的方法了
List<User> userList = mapper.getUserList();
返回结果
for (User user : userList) {
System.out.println(user);
}
7.3 关闭 sqlSession
sqlSession.close();
7.4 完整的测试类代码
package com.waciao.dao;
import com.waciao.pojo.User;
import com.waciao.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
/**
* @Author: Waciao
* @Date: 2020/3/17 11:45
* @Version: 1.0
* @Github: https://github.com/byojiaoxianz7
*/
public class UserMapperTest {
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
8. 错误排查
运行程序之后会报两个错误
8.1 org.apache.ibatis.binding.BindingException: Type interface com.waciao.dao.UserMapper is not known to the MapperRegistry.
报这个错误是因为在写 mybatis-config.xml 的时候没有注册 mapper
需要配置才行
<mappers>
<mapper resource="com/waciao/dao/UserMapper.xml" />
</mappers>
8.1.1 完整的mybatis-config.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>
<!--环境 默认选择development环境-->
<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/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="12345678"/>
</dataSource>
</environment>
</environments>
<!--每一个Mapper.xml都需要在mybatis核心-->
<mappers>
<mapper resource="com/waciao/dao/UserMapper.xml" />
</mappers>
</configuration>
8.2 java.lang.ExceptionInInitializerError,Caused by: org.apache.ibatis.exceptions.PersistenceException
第二个错误: 在 target/test-classes/com/waciao/dao
里没有找到 UserMapper.xml
原因在 maven 中, 因为它的约定大于配置, 写文件配置时可能无法被导出或生效
maven 中配置文件应该放在 resources 目录下,但是这个程序放在了 java 文件下,所以没有找到 xml 配置文件
所以需要在build中配置resources,来防止资源导出失败的问题
解决方案:
在 ```pom.xml```文件中引入即可
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
配置之后可能还是会报错, 那么可以这也解决:
- 把 filtering 改为 false
- 在
mybatis-config.xml
中的 url 把 useSSL 改为 false
总结
跟着狂神老师思路一步一步走下来,基本上没遇到什么问题,结果还是比较令我满意.
多看官方文档
_