第一个Mybatis程序

使用Mybatis连接Mysql数据库

开发环境:

  • JDK 17
  • Maven 3.8.4
  • MySQL 5.7
  • IDEA 2020.3

一、创建新项目

​ 首先配置好我们项目,新建一个项目mybatis_Test,作为所有mybatis项目的根项目。这样做的好处是整合了所有项目,并且在根项目pom.xml中添加的依赖会自动的添加到其子项目中,避免了后续新建项目的重复工作。

​ 其次要添加依赖,用到的依赖一共有三个:mysql mybatis junit,在pom.xml中添加以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
注意每次更改pom.xml要点击右上角'加载Maven变更',改变才会生效

​ 随后在主项目中创建一个新项目test1作为此次实验项目,点击IDEA右侧Maven侧边栏查看项目中的依赖项,确认所有依赖已经导入。

二、编写mybatisUtil.java

​ 在新项目test1/src/java中添加新软件包top.hellogjs.utils,在包中添加java类mybatisUtil.java

引用官方文档

从 XML 中构建 SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。

1
2
3
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

从 SqlSessionFactory 中获取 SqlSession

既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:

1
2
3
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}

诚然,这种方式能够正常工作,对使用旧版本 MyBatis 的用户来说也比较熟悉。但现在有了一种更简洁的方式——使用和指定语句的参数和返回值相匹配的接口(比如 BlogMapper.class),现在你的代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。

例如:
1
2
3
4
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
}

简单解释一下,SqlSession对象像其他数据库框架中的会话指针作用一样,用于对数据库进行操作。获取SqlSession需要从SqlSessionFactory“工厂”中制造,而工厂又需要使用SqlSessionFactoryBuilder进行”建造”。所以开启SqlSession步骤一共有三步:

  • 首先加载配置文件mybatis-config.xml
  • 将加载的输入流InputStream传入SqlSessionFactoryBuilder中的build方法进行工厂的建造
  • 使用建造好的SqlSessionFactoryopenSession方法开启SqlSession

这就是创建mybatisUtil.java的全部流程,我们一步一步来:smiley:

1. 创建mybatis-config.xml并加载

java文件夹同级目录下的resources文件夹下建立mybatis-config.xml文件,复制以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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="${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>

XML文件的头部我们忽略,从<environments>标签开始,其后default属性表示使用的是哪一个环境,因为在程序中可能配置多种环境,每一种环境都在<environments>标签下的<environment>标签中配置,default属性的值就是使用的<environment>标签的ID,此处为development因为我们只有一个id为development的环境。

在环境中可以配置参数,用于连接数据库,示例如下

1
2
3
4
5
6
7
8
9
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSl=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123123123"/>
</dataSource>
</environment>

注意url中的参数,useSSL为使用安全连接,useUnicode为使用Unicode编码,characterEncoding为设置字符集,serverTimezone为设置时区,其中参数和参数之间使用&分隔,但是在XML中,符号&需要使用&amp;进行转义才能正常使用

最后的mappers标签,为程序中所有映射文件的位置,稍后进行介绍

创建好配置的XML文件后,在mybatisUtil.java中编写代码加载到InputStream输入流

1
2
String Resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(Resource);

resouces文件夹下的配置文件我们可以输入文件名,通过Resouces类就可以索引到并转换成输入流

2. 创建SqlSessionFactory并创建SqlSession

将上一步生成的文件输入流传入SqlSessionFactoryBuilderbuild方法中就可以生成SqlSessionFactory工厂类

1
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

在使用SqlSessionFactory工厂类的openSession方法就可以开启SqlSession

1
SqlSession sqlSession = sqlSessionFactory.openSession();

所以完整的mybatisUtil.java代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package top.hellogjs.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;

public class mybatisUtil {

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();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}

三、编写数据库表的实体类

实验数据:

在MySQL中建立mybatis数据库,数据库中建立user表,user表中有三列:id name psw

建立一个新包top.hellogjs.pojo在其中建立实体类user.javapojoPlant Old Java Object),代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package top.hellogjs.pojo;

public class user {
private int id;
private String name;
private String psw;

public user() {
}

public user(int id, String name, String psw) {
this.id = id;
this.name = name;
this.psw = psw;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPsw() {
return psw;
}

public void setPsw(String psw) {
this.psw = psw;
}

@Override
public String toString() {
return "user{" +
"id=" + id +
", name='" + name + '\'' +
", psw='" + psw + '\'' +
'}';
}
}
小技巧:在IDEA中使用ALT+INS可快速插入构造方法、Get、Set方法等
## 四、编写Mapper接口和Mapper配置文件

根据上文引用的官方文档可以知道,如果想获得查询的实体实例,首先要获得表的映射,从调用映射的方法获得实体实例,而获得表的映射需要传入该表的映射接口以及知道接口是怎么映射数据库的,这就分别对应了下面要编写的Mapper接口以及Mapper配置文件。

再明确一下:Mapper接口文件是用于创建Mapper的“模板”,Mapper配置文件是Mapper执行方法时的过程。可以简单的理解成配置文件中就是接口中方法的代码,但是实际上,在配置文件中写的要比原本的代码简单清晰许多。


首先新建包top.hellogjs.mapping用于存放所有mapper接口和配置文件

创建接口文件UserMapper.java编写以下代码

1
2
3
4
5
6
7
8
package top.hellogjs.mapping;

import top.hellogjs.pojo.user;
import java.util.List;

public interface UserMapper {
List<user> getUserList();
}

接口中getUserList方法用于返回查询的结果集

其次再编写Mapper映射器文件,如下所示

1
2
3
4
5
6
7
8
9
10
<?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="top.hellogjs.mapping.UserMapper">
<select id="getUserList" resultType="top.hellogjs.pojo.user">
select * from mybatis.user
</select>
</mapper>

mapper标签中,namespace属性是用来连接配置文件和接口文件的,所以其值需要指向接口文件。其中的select标签中,id即引用下面语句的方法名,resultType属性是确定返回结果的类型,此处我们传入的实体类就是应返回的类型。mapper标签下就是执行的SQL语句

注意在mybatis-config.xml(mybatis配置文件)中,还有一个之前没有介绍的mappers标签
1
2
3
4
5
...
<mappers>
<mapper resource="top/hellogjs/mapping/UserMapper.xml"/>
</mappers>
...

此处的mappers标签下的每一个mapper标签,都是在项目中创建的mapper配置文件,其resource属性的值就是配置文件的路径,这是为了让mabatis找到这些配置文件。

五、使用JUnit测试

JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试。他是用于单元测试框架体系xUnit的一个实例(用于java语言)。它包括以下特性:

1、用于测试期望结果的断言(Assertion)

2、用于共享共同测试数据的测试工具

3、用于方便的组织和运行测试的测试套件

4、图形和文本的测试运行器

取自百度百科

在项目src文件夹下的test/java中创建包,包的路径最好和在main中的路径相同,创建包top/hellogjs.mapping,在包中创建UserMappingTest.java类,编写以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package top.hellogjs.mapping;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import top.hellogjs.pojo.user;
import top.hellogjs.utils.mybatisUtil;
import java.util.List;

public class UserMapperTest {
@Test
public void Test(){
SqlSession sqlSession = mybatisUtil.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<user> userList = mapper.getUserList();
for (user item : userList) {
System.out.println(item);
}
sqlSession.close();
}
}

首先通过第二步编写的mybatisUtil中获取数据库的sqlSession,使用其getMapper方法并传入第四步编写的Mapper接口类生成映射器Mapper,生成的映射器可以当作实现了UserMapper接口的一个类,只不过这个类我们没有编写代码,是通过接口和配置文件生成的。在调用映射器的getUserList就可以获得之前编写sql语句的查询结果了,最后要关闭对话sqlSession

六、添加资源路径

当你好不容易按照步骤编写好了第一个Mabatis程序,可是当右键点击运行的时候,突然发现他居然报错了

1
2
3
4
5
6
7
8
9
java.lang.ExceptionInInitializerError
at top.hellogjs.mapping.UserMapperTest.Test(UserMapperTest.java:12)
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in top/hellogjs/mapping/UserMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource top/hellogjs/mapping/UserMapper.xml
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
...

没关系,(这是故意让你出错的)我来帮你解决

阅读一下这个错误,Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource top/hellogjs/mapping/UserMapper.xml很明显,是Mapper配置文件出了问题,程序提示说没有找到UserMapper.xml,这个错误是很常见的,我们需要在test1项目中的pom.xml添加资源文件路径,这样在构建时才可以找到,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

添加至pom.xml中,很明显,它的作用是指出路径,让程序在这些路径下寻找后辍为.properties.xml的文件并且关闭最后的过滤器。注意要点击右上角加载maven变更

此时再运行程序就应该可以看到查询的结果了,这样,第一个MyBatis程序就编写完成了。大致的流程以及各个类和配置文件的关系可以总结成图表

1
2
graph TD;
A[SqlSessionFactoryBuilder]-->|Mybatis-config.xml|B[SqlSessionFactory]-->C[SqlSession]-->|Mapper Interface & Mapper Config.xml|D[Mapper]-->E[Do Something]-->|close|C

七、下一步

Mybatis程序大致流程已经介绍,下一步请移步至官方文档,下面将简单介绍一些其他事项

1、增删改查传参

  1. 直接传参

    直接在接口函数中传入参数,在SQL语句中直接调用

    1
    2
    3
    public interface UserMapper {
    user getUser(int i)
    }
    1
    select * from user where id = #{id};

    这样写的好处是传参和使用参数都很方便,但是当传入参数大于一个的时候,在SQL语句中调用要使用param1``param2…否则会提示变量名未找到。因为实际上这样传入的参数是匿名参数,在接口中定义的参数名并没有在mybatis中命名,只有一个参数时没有二义性,但两个参数及以上时就无法辨别是哪个参数。

  2. 使用@Param注解

    在接口函数中参数前使用@Param注解,如下所示

    1
    void setUserName(@Param("id") int id, @Param("name") String name);

    这样在SQL中就可以用@Param中参数名去引用

  3. 使用Map传参

    在实际生产中经常使用,使用HashMap传入参数,在SQL可以直接用变量名获取

    1
    void setUserName(Map params);
    1
    2
    3
    <update id="setUserName" parameterType="map">
    update user set name = #{name} where id = #{id};
    </update>

    在调用时传入参数

    1
    2
    3
    4
    Map params = new HashMap<>();
    params.put("id",6);
    params.put("name","gjss");
    mapper.setUserName(params);