Mybatis-01-入门

前言

从今天开始学习 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?

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&amp;useUnicode=true&amp;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&amp;useUnicode=true&amp;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>

配置之后可能还是会报错, 那么可以这也解决:

  1. 把 filtering 改为 false
  2. mybatis-config.xml中的 url 把 useSSL 改为 false

总结

  1. 跟着狂神老师思路一步一步走下来,基本上没遇到什么问题,结果还是比较令我满意.

  2. 多看官方文档

_

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,423评论 0 4
  • 1. Mybatis的介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由ap...
    itzhouq的笔记阅读 650评论 0 5
  • MyBatis主要组成部分 1. SqlSessionFactoryBuilder(构造器) 根据配置信息或代码生...
    onlyHalfSoul阅读 1,189评论 1 3
  • mybatis 不会直接和数据库进行打交道,mybatis 其实是对 jdbc api 的进一步封装,最终和数据库...
    小毛1221阅读 501评论 0 0
  • 之前在面试工作的时候,我当时用的是hibernate,但是现在互联网项目并发量大,一般都会选择使用Mybatis,...
    唐伟耀阅读 548评论 1 0