建立你的第一个Mybatis程序(一)| 青训营笔记

106 阅读6分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记

一、数据库中准备工作

首先需要一张数据库的表

新建数据库:Mydatabase

新建表:tbl_employee

表中新建四个字段:id,lastName,email,age

插入一条记录:1,tom,Tom@ee.com,18

二、连接数据库并查询一条记录

1. 写一个与数据库中表对应的类

Employee.Class

public class Employee {
​
    private int id;
    private String lastName;
    private String email;
    private int age;
​
    public int getId() {
        return id;
    }
​
    public void setId(int id) {
        this.id = id;
    }
​
    public String getLastName() {
        return lastName;
    }
​
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
​
    public String getEmail() {
        return email;
    }
​
    public void setEmail(String email) {
        this.email = email;
    }
    
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
}

2. 导入 jar 包(Maven 方式)

在 POM.xml 中插入以下这段:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

版本号可去官网查看

3. 创建一个Mybatis的全局配置文件

这个全局配置文件的作用是连接数据库

一般起名为:mybatis-config.xml

主要改 dataSource 标签和 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">
                <!-- 下面一般只改value值 -->
                <!-- 这一行为了说明数据库框架,postgresql的话就写下面这个 -->
                <property name="driver" value="org.postgresql.Driver" />
                <!-- 这一行为了说明连接的哪个数据库,默认的端口就是5432,数据库是自己创建的Mydatabase -->
                <property name="url" value="jdbc:postgresql://localhost:5432/Mydatabase" />
                <!-- 这一行为了说明连接的哪个数据库的用户名,一般默认就是postgres -->
                <property name="username" value="postgres" />
                <!-- 这一行为了说明连接数据库所需要的密码 -->
                <property name="password" value="Zhou1104" />
            </dataSource>
            
        </environment>
    </environments>
    
    <!-- 
         <mappers>
         这个SQL映射文件后面会讲到;
         将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中;
         注册的方法就是使用<mappers>标签;
    -->
    <mappers>
        <mapper resource="EmployeeMapper.xml" />
    </mappers>
</configuration>

4. 在 Main 函数中引入配置文件

在 Main 函数中需要创建一个 SqlSessionFactory 的对象来引入全局配置文件(mybatis-config.xml)

//获取全局配置文件中的字符
String resource = "mybatis-config.xml";
//根据字符形成数据流
InputStream inputStream = Resources.getResourceAsStream(resource);
//根据数据流产生SqlSession工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//根据SqlSession工厂创建SqlSession对象,这个实例能执行已经映射的Sql语句
SqlSession openSession = sqlSessionFactory.openSession();

5. 创建 xml 映射文件(与全局配置文件不同)

映射文件作用主要是为了连接相应的类和方法

这个映射文件的名称为 Employee.xml

<?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">
<!-- namespace: 这个映射文件的名称空间 -->
<mapper namespace="abc">
    <!-- id:这个映射文件的唯一标识符   resultType:查询结果的返回值,即将查询结果返回到一个类中 -->
    <select id="selectEmp" resultType="com.Joe.Bean.Employee">
        <!-- 从表tbl_employee中选择id值为#{id}的lastName -->
        <!-- id写成这样:#{id},是为了将所需要的id值传进来 -->
        select lastName from tbl_employee where id = #{id}
    </select>
</mapper>

这个映射文件需要在全局配置文件中进行注册

在上面的全局配置文件(mybatis-config.xml)代码中,标签就是为了注册映射文件

6. 在 Main 函数中进行数据库中数据的查询,并将查询的结果放入 Employee 类中

/*
    openSession.selectOne()方法是为了查询表中的一条记录
    参数1:指明写Sql查询语句的xml映射文件
          abc.selectEmp是指的这个xml映射文件的唯一名称(不是文件名,可以理解为这个xml文件自己的名字)
          其中abc是名称空间(namespace)的值
          selectEmp是唯一标识(id)的值
    参数2:传入Sql语句中所需要的值
          这个例子中就是将id为1传了进去
*/
Employee employee = openSession.selectOne("abc.selectEmp", 1);
​
System.out.println(employee.getLastName());

7. 主函数代码

package com.Joe.Main;
​
import com.Joe.Bean.Employee;
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 Main {
    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 openSession = sqlSessionFactory.openSession();
​
        try {
            Employee employee = openSession.selectOne("abc.selectEmp", 1);
            System.out.println(employee.getLastName());
        }
        finally {
            openSession.close();
        }
    }
}

输出结果:

Tom

8. 以上方法的缺点

按照以上方法查询数据库时,使用的是 Mybatis 封装好的方法 selectOne ( ),代码如下

/*
    openSession.selectOne()方法是为了查询表中的一条记录
    参数1:指明写Sql查询语句的xml映射文件
          abc.selectEmp是指的这个xml映射文件的唯一名称(不是文件名,可以理解为这个xml文件自己的名字)
          其中abc是名称空间(namespace)的值
          selectEmp是唯一标识(id)的值
    参数2:传入Sql语句中所需要的值
          这个例子中就是将id为1传了进去
*/
Employee employee = openSession.selectOne("abc.selectEmp", 1);

在这个方法中,能够实现条件查询的参数只有一个,也就是第二个参数

完全可以通过这个方法进行单一条件的查询,就比如例子中查询 id 值为 1 的记录,这是一个单一条件

但假如想要进行组合条件查询的话,这个方法就无能为力了

比如要查询 id 值小于 10 并且 age 值小于 20 的记录,那这个方法很显然做不到

那可不可以用 Mybatis 封装好的其它方法?

我不知道,或许可以,或许 Mybatis 将所有可能使用的查询条件组合方式都考虑到了,但我没去查,也没必要查

因为各式各样的查询(包括插入、更新)数据库的方法完全可以由我们自己去定义,自己去写

三、通过接口来自定义数据库的操作方法

1. 声明方法的接口

与上面不同的是,现在我们要使用自己的方法去查询、插入和更新数据库

这就需要有一个接口专门声明这些方法

EmployeeMapper.Interface

public interface EmployeeMapper {
    
    //根据id来查询数据库中记录的方法
    public Employee getEmpById(int id);
    //向数据库中插入记录的方法
    public void setEmp(int id, String lastName, String email, int age);
}

接口中的这两个方法各有特点:

  • getEmpById ( ) 方法:返回值是 Employee,而 Employee 类中的属性正是数据库中表 tbl_employee 的所有字段

    也就是说,这个方法的目的是将数据库中查询到的结果放在一个 Employee 对象中进行存储,而并不是直接显示给用户

    那 Employee 类中可以创建一个方法,来显示 Employee 对象中的属性值,这个属性值就是从数据库中查询到的表记录

    Employee 相当于做了一次中间商

  • setEmp ( ) 方法:返回值为空,意思是只需要将参数设置好,这个方法就能直接把参数的值写到数据库中,不需要任何中间商

2. 修改 xml 映射文件

之前的映射文件是这么写的

Employee.xml

<?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">
<!-- namespace: 这个映射文件的名称空间 -->
<mapper namespace="abc">
    <!-- id:这个映射文件的唯一标识符   resultType:查询结果的返回值,即将查询结果返回到一个类中 -->
    <select id="selectEmp" resultType="com.Joe.Bean.Employee">
        select lastName from tbl_employee where id = #{id}
    </select>
</mapper>

现在需要修改名称空间(namespace)和唯一标识符(id)

名称空间:改为接口的全路径

唯一标识符:改为接口中的方法名

代码如下:

<?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">
<!-- namespace: 名称空间改为接口的全路径 -->
<mapper namespace="com.Joe.Service.EmployeeMapper">
    
    <!-- select方法 -->
    <!-- id:唯一标识符改为接口中方法名 -->
    <select id="getEmpById" resultType="com.Joe.Bean.Employee">
        select id, lastName, email, age from tbl_employee where id = #{id};
    </select>
    
    <!-- insert方法 -->
    <insert id="setEmp">
        insert into tbl_employee (id, lastName, email, age) values (#{id}, #{lastName}, #{email}, #{age});
    </insert></mapper><!-- 
    说明:
    (id, lastName, email, age) 中的值对应的是数据库中表的字段
    (#{id}, #{lastName}, #{email}, #{age}) 中的值对应的是接口中函数的参数
-->

3. Main 函数实现

Main.Class

public class Main {
    public static void main(String[] args) throws IOException {
​
        //创建openSession(必不可少)
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = sqlSessionFactory.openSession();
​
        try {
​
            //创建接口的代理对象emploeeMapper,所有方法都是代理对象去实现
            EmployeeMapper employeeMapper = openSession.getMapper(EmployeeMapper.class);
​
            //向数据库中执行插入(不需要返回值)
            employeeMapper.setEmp(2, "Tom", "Tom@ee.com", 23);
            //提交插入结果(insert和update必不可少)
            openSession.commit();
​
            //获取id值为2的记录,并储存在类Employee的对象employee中(需要返回值)
            Employee employee = employeeMapper.getEmpById(2);
​
            //输出对象employee中的属性值
            System.out.println(employee.getId() + " " + employee.getLastName() + " " + 
                               employee.getEmail() + " " + employee.getAge());
​
        }
        finally {
            openSession.close();
        }
    }
}

输出结果:

2 Tom Tom@ee.com 23

四、其它知识点

1. SqlSession

  • 代表和数据库的一次会话,用完必须关闭

  • SqlSession 是个非线程安全

    即不能直接在 Main 方法里这么定义:

    private SqlSession sqlSession;
    

    因为如果这么定义之后,可能会被别的线程拿去使用

    所以必须要即用即定义

    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    ​
    //即用即定义
    SqlSession openSession = sqlSessionFactory.openSession();
    

2. Mapper接口

Mapper 接口没有实现类,但Mybatis会为这个接口创建一个代理对象

通过代理对象绑定 xml 文件和 Mapper 接口

3. 两个配置文件

  • mybatis-config.xml:

    数据库连接池信息,事务管理信息

  • Mapper.xml:

    保存了每一个 sql 语句的映射信息