MyBatis快速入门(一) 搭建环境和单表映射

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MyBatis简介一说起对象关系映射框架,大家第一时间想到的肯定是Hibernate。Hibernate作为一个著名的框架,功能十分强大。我们只需要配置好实体类和数据表之间的关系,Hibernate就会自动帮我们完成生成并执行SQL语句,映射结果集这样的工作。

MyBatis简介

一说起对象关系映射框架,大家第一时间想到的肯定是Hibernate。Hibernate作为一个著名的框架,功能十分强大。我们只需要配置好实体类和数据表之间的关系,Hibernate就会自动帮我们完成生成并执行SQL语句,映射结果集这样的工作。但是也正是由于Hibernate如此强大的功能,导致了它的缺点:一是非常笨重,启动Hibernate的SessionFactory非常耗时,开销巨大;二是配置复杂,学习成本较高,系统调优也不容易;三是自定义查询功能较弱,查询结果如果不是映射的实体类,查询起来就比较麻烦。因此另一个ORM框架MyBatis,越来越流行。

前面说到的几个Hibernate的缺点,反过来正好就是MyBatis的优点:一是非常轻量,系统开销小;二是配置简单,易于学习,官方文档我直觉上感觉比Log4j2的文档还少;三正好就是MyBatis的特点,映射查询结果非常灵活。另外MyBatis还有一个优点就是自带中文文档,可能有些地方感觉不太通顺,但是完全足够我们学习和使用了。

配置环境

依赖引入

添加MyBatis最简单的办法就是使用Maven或Gradle这样的构建工具。在这里我使用Gradle。在项目中添加如下几行即可。如果确定不使用新的Java 8 时间API,那么第二行的依赖还可以去掉。这里我用的数据库是MySQL,因此还需要添加MySQL的JDBC驱动。

compile group: 'org.mybatis', name: 'mybatis', version: '3.4.2'
compile group: 'org.mybatis', name: 'mybatis-typehandlers-jsr310', version: '1.0.2'
compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.40'

配置文件

然后我们需要编写MyBatis的配置和映射文件。所有这些配置文件最好放在类路径上,对于Gradle项目来说就是src/main/resources文件夹下。我们先来编写一个配置文件。配置文件每个部分的详细作用请参见官方文档,这里只简单说明一下。

  • 属性部分。在这里定义MyBatis需要的属性,可以用在下面的多个地方。另外属性也可以从外部properties文件中导入。
  • 系统设置。在这里指定MyBatis的全局配置。详细的配置参加文档。
  • 简写名。在映射文件中需要指定Java实体类的全名,我们可以在这里指定简写名简化配置。
  • 环境。在这里我们要指定数据库连接、事务管理器等配置。还可以指定测试环境、生产环境等多个环境对应不同的数据库配置。
  • 映射文件。在这里指定映射文件,或者也可以添加使用注解配置的类。
<?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>
    <!--指定属性-->
    <properties>
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="12345678"/>
        <property name="driver.useSSL" value="false"/>
    </properties>
    <!--系统设置-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <!--指定简写名-->
    <typeAliases>
        <package name="yitian.study.entity"/>
    </typeAliases>
    <!--配置环境,可以配置多个环境用于测试、调试和生产-->
    <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="BaseEntityMapper.xml"/>
    </mappers>

</configuration>

创建SqlSessionFactory

有了配置文件,我们就可以开始使用MyBatis了。首先要做的事情是创建MyBatis的SqlSessionFactory,它和Hibernate的SessionFactory类似,是主要的工厂类,一个应用程序中只需要创建一个即可。

下面是一个工具类,用双检锁简单的实现了一个线程安全的工具类。核心代码在最内层的if判断中。由于配置文件在类路径上,所以我们只需要指定文件名即可。这里用到了MyBatis提供的Resources工具类,创建一个输入流,然后交给SqlSessionFactoryBuilder来创建一个SqlSessionFactory

public abstract class MyBatisUtils {
    private static volatile SqlSessionFactory sqlSessionFactory;

    public static final String MyBatisConfigLocation = "configuration.xml";

    public static SqlSessionFactory getSqlSessionFactory() throws IOException {
        if (sqlSessionFactory == null) {
            synchronized (MyBatisUtils.class) {
                if (sqlSessionFactory == null) {
                    InputStream input = Resources.getResourceAsStream(MyBatisConfigLocation);
                    sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
                    input.close();
                }
            }
        }
        return sqlSessionFactory;
    }
}

创建好SqlSessionFactory之后,我们就可以开始使用MyBatis了。这里先回过头看看如何创建MyBatis映射文件。然后我们在继续使用MyBatis。

单表映射

数据表和实体类

在配置文件最后的mapper部分定义的就是映射文件。映射文件也是我们需要重点学习的地方。在映射文件中我们需要定义各种SQL语句,并建立它们和Java实体类之间的关系。这里我们使用最简单的单表映射:数据表和实体类之间属性名相同,一一对应。

首先先来添加一个实体类。

public class Person {
    private int id;
    private String username;
    private LocalDate birthday;

}

对应的数据库表如下。

CREATE TABLE person (
  id       INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(255) NOT NULL UNIQUE,
  birthday DATE
);

映射文件

然后我们来编写映射文件。映射文件包含5条SQL语句,分别是增删查改以及按名称查找。每一条语句都需要一个标识符,将会在后面再代码中用到。如果是查询语句还需要resultType,指定返回类型。MyBatis会将数据表列明和这里指定的类型属性按名称自动映射起来。如果需要在语句中传入参数,可以使用 parameterType属性,指定Java实体类的全名或简写,然后就可以在SQL语句中使用#{}来访问参数的属性了。如果是简单的映射,那么parameterType属性还可以省略,MyBatis会自动从传入的Java对象中获取相应的属性。对于某些数据库(例如MySQL),还可以在插入的时候指定useGeneratedKeys="true",让数据库自动生成主键。

<?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="yitian.study.dao.mapper">
    <select id="selectPerson"
            resultType="Person" parameterType="Person">
        SELECT *
        FROM Person
        WHERE id = #{id}
    </select>
    <select id="selectPersonByName"
            resultType="Person">
        SELECT *
        FROM Person
        WHERE username = #{username}
    </select>
    <insert id="insertPerson"
            useGeneratedKeys="true">
        INSERT INTO Person (username, birthday) VALUES (#{username}, #{birthday})
    </insert>
    <update id="updatePerson">
        UPDATE Person
        SET birthday = #{birthday}
        WHERE id = #{id}
    </update>
    <delete id="deletePerson">
        DELETE FROM Person
        WHERE id = #{id}
    </delete>
</mapper>

使用MyBatis

以上这些都配置好之后,我们就可以来使用MyBatis了。这里我们使用一个单元测试来查看MyBatis的功能。在创建SQLSessionFactory之后,我们需要获取MyBatis最核心的对象SqlSession,所有操作都需要SqlSession来进行。另外它是非线程安全的对象,不能放在类的静态字段上,最好也不要作为实例字段。我们要在需要的时候创建它,不用的时候及时释放。

常用的方法有增删查改这几个方法。这些方法的第一个参数是前面我们在映射文件中定义的语句ID,第二个参数是要传入的参数。对于查询来说有selectOne和selectList方法,它们的区别主要在于返回个数,如果确定只返回一个对象就使用selectOne方法。

import static org.assertj.core.api.Assertions.*;

public class MyBatisTest {
    private static SqlSessionFactory sqlSessionFactory;
    private SqlSession sqlSession;

    @BeforeClass
    public static void init() throws IOException {
        sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
    }


    @Before
    public void before() {
        sqlSession = sqlSessionFactory.openSession(true);//自动提交
    }

    @After
    public void after() {
        sqlSession.close();
    }

    @Test
    public void testMyBatisUtils() {
        assertThat(sqlSessionFactory).isNotNull();
    }

    @Test
    public void testInsert() {
        Person p = new Person(0, "yitian", LocalDate.of(1993, 5, 6));
        sqlSession.insert("insertPerson", p);

        Person s = sqlSession.selectOne("selectPersonByName", p.getUsername());
        assertThat(s).isNotNull();
        System.out.println(s);

        sqlSession.delete("deletePerson", s);
    }

    @Test
    public void testUpdate() {
        Person p = new Person(1, "leo", LocalDate.of(1993, 5, 6));
        sqlSession.insert("insertPerson", p);

        p = sqlSession.selectOne("selectPersonByName", p.getUsername());
        LocalDate b = LocalDate.of(1987, 7, 8);
        p.setBirthday(b);
        sqlSession.update("updatePerson", p);
        Person s = sqlSession.selectOne("selectPersonByName", p.getUsername());
        assertThat(s.getBirthday()).isEqualTo(b);
        System.out.println(s);

        sqlSession.delete("deletePerson", s);
    }
}

另外默认情况下MyBatis的事务管理是开启的,意味着我们必须显式使用commit()方法才能提交事务。这里在打开SqlSession的时候指定了自动提交,这样我们的所有更改都会立即反映到数据库中。

使用映射类

在前面的例子中,使用的都是字符串来指定要使用的查询。但是这样做非常不方便,字符串容易发生错误,而且无法获得IDE的智能补全。所以MyBatis提供了另一种方式来执行SQL语句,这就是使用映射类。

映射类其实就是一个简单的接口。该接口中的方法和映射文件中定义的语句一一对应。接口方法的名称必须和语句id完全相同,接口方法的返回值和参数和相应的语句相对应。

public interface PersonMapper {
    Person selectPerson(int id);

    Person selectPersonByName(String name);

    void insertPerson(Person person);

    void updatePerson(Person person);

    void deletePerson(Person person);
}

仅仅增加映射类还不够,我们需要修改映射文件,以便让MyBatis能找到这个映射类。做法就是将映射文件的命名空间改为对应的映射文件的类名。

<mapper namespace="yitian.study.mapper.PersonMapper">

映射类定义和配置好之后,我们就可以使用了。使用方法很简单,在SqlSession上调用getMapper方法,并传入要获取的Mapper类即可。

PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);

Person p = new Person(0, "yitian", LocalDate.of(1993, 5, 6));
mapper.insertPerson(p);

Person s = mapper.selectPersonByName(p.getUsername());
assertThat(s).isNotNull();
System.out.println(s);

mapper.deletePerson(p);

有了映射对象,我们就可以以类型安全的方式来存取对象了,同时还可以获得IDE的补全功能。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL Java 数据库连接
MyBatis-Plus快速入门:从安装到第一个Demo
本文将带你从零开始,快速入门 MyBatis-Plus。我们将首先介绍如何安装和配置 MyBatis-Plus,然后通过一个简单的示例演示如何使用它进行数据操作。无论你是 MyBatis 的新手还是希望提升开发效率的老手,本文都将为你提供清晰的指导和实用的技巧。
491 0
MyBatis-Plus快速入门:从安装到第一个Demo
|
3月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
4月前
|
XML Java 数据库连接
mybatis源码研究、搭建mybatis源码运行的环境
这篇文章详细介绍了如何搭建MyBatis源码运行的环境,包括创建Maven项目、导入源码、添加代码、Debug运行研究源码,并提供了解决常见问题的方法和链接到搭建好的环境。
mybatis源码研究、搭建mybatis源码运行的环境
|
5月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
120 3
|
6月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
79 3
|
6月前
|
Java 数据库连接 API
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
70 3
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
若依修改,集成mybatisplus报错,若依集成mybatisplus,总是找不到映射是怎么回事只要是用mp的方法就找报,改成mybatisPlus配置一定要改
|
5月前
|
Java 数据库连接 mybatis
mybatis包扫描环境分析,最简单的环境准备
mybatis包扫描环境分析,最简单的环境准备
|
7月前
|
算法 BI 数据库
MyBatisPlus查询条件设置、映射匹配兼容性、id生成策略、多数据操作
MyBatisPlus查询条件设置、映射匹配兼容性、id生成策略、多数据操作
432 3