欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis框架(1) —— 入门案例

程序员文章站 2022-05-23 19:51:12
...

内容简介

本文是对MyBatis的基础操作方式进行的演示,包括MyBatis环境搭建,以及一些细节知识点。
我们会发现其实各种操作方式的步骤大同小异,因为究其根源它们实现的都是相同的功能。
为了让大家能更好的理解,我们来试着分析一下MyBatis究竟帮我们实现了什么样的功能。

  • 连接MySQL数据库的功能
  • 连接持久层接口的功能
    • 通过映射配置文件的方式
    • 通过注解的方式
  • 实现持久层接口的功能
    • 创建持久层接口实现类
    • 使用代理的持久层接口实现类

思维导图

MyBatis框架(1) —— 入门案例

搭建环境

创建Maven工程

  • GroupID
    • 项目组织唯一的标识符
    • 实际对应Java的包的结构,main/Java目录下的目录结构。
    • GroupID分为多段,第一段为域,第二段为公司名称等。
      • 域:org(非盈利组织)、com(商业公司)、cn(中国组织)
  • ArtifactID
    • 项目的唯一的标识符
    • 实际对应项目的名称,项目根目录的名称。

举例:Apache公司的Tomcat项目
GroupID:org.apache
ArtigactID:tomcat

添加MyBatis坐标

  • Maven坐标
    • Maven拥有数量非常巨大的构件(jar/war),而任何一个构件都可以使用Maven坐标来获取。maven坐标的元素包括groupId,artifactId,version,package,classifier。
  • 引入依赖
    • 一旦我们在pom.xml文件中配置好 dependancy标签 中的 groupId标签,artifact标签,verison标签 和classifier标签,maven就会从仓库中寻找相应的构件供我们使用。
  • 在pom.xml 文件中,引入4个依赖:
    • mybatis(MyBatis框架)
    • mysql-connector-java(数据库连接)
    • junit (单元测试)
    • log4j(日志文件)
    <dependencies>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
    </dependencies>

创建数据库

#创建数据库
CREATE DATABASE mybatis;
USE mybatis;

#创建表
CREATE TABLE USER(
	id INT(11) PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(32) NOT NULL COMMENT '用户名称',
	birthday DATETIME DEFAULT NULL COMMENT '生日',
	sex CHAR(1) DEFAULT NULL COMMENT '性别',
	address VARCHAR(256) DEFAULT NULL COMMENT '地址'	
) ENGINE = INNODB DEFAULT CHARSET = utf8;

#插入数据
INSERT INTO USER VALUES 
	(41,'老王','2018-02-27 17:47:08','男','北京'),
    (42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),
    (43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),
    (45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),
    (46,'老王','2018-03-07 17:37:26','男','北京'),
    (48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');

方法一:映射配置文件

目录结构

  • src/main
    • java
      • cn/water/dao
        • UserDao.java(持久层接口)
      • cn/water/domain
        • User.java(实体类)
    • resources
      • cn/water/dao
        • UserDao.xml(持久层接口的映射配置文件)
      • SqlMapConfig.xml(MyBatis主配置文件)
  • src/tese
    • java
      • cn/water/test
        • UserTest.java(测试文件)

实体类

  • 实体类要实现Serializable接口,因为在封装MySQL数据库数据时,运用了代理对象。
  • 实体类中的成员变量和MySQL数据库中的列属性保持一致。

User.java

package cn.water.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {

    /* 成员变量 */
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

持久层接口

  • 编写一个操作数据库的抽象方法,但是具体的SQL语句会由持久层接口的映射文件来编写

UserDao.java

package cn.water.dao;

import cn.water.domain.User;

import java.util.List;

public interface UserDao {

    /** 查询所有用户 */
    public abstract List<User> findAll();

}

映射配置文件

  • 映射配置文件:专注于编写SQL语法,一个持久层接口对应一个映射配置文件
    • 创建位置:映射配置文件必须和持久层接口在相同的包中。
      • 持久层接口:src/main/java/cn/water/dao/
      • 映射配置文件:src/main/resources/cn/water/dao/
    • 名称:映射配置文件必须以持久层接口名称命名文件名,扩展名是.xml。
      • 持久层接口:UserDao.java
      • 映射配置文件:UserDao.xml

UserDao.xml

  • 语法
    • mapper
      • namespace:持久层接口的全类名
    • select
      • id:方法名称
      • resultType:返回值类型
      • SQL语句
  • 含义
    • findAll方法的位置:cn.water.do.UserDao
    • findAll方法的SQL语句:SELECT * FROM user;
    • findAll方法的返回值类型:cn.water.domain.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="cn.water.dao.UserDao">
        <select id="findAll" resultType="cn.water.domain.User">
            SELECT * FROM user;
        </select>
    </mapper>

</mapper>

MyBatis主配置文件

  • MyBatis主配置文件:专注于连接数据库,一个映射配置文件对应一个mapper标签。

SqlMapConfig.xml

  • configuration
    • environments default=“mysql” :环境
      • environment id=“mysql” :MySQL环境
        • transactionManager type=“JDBC” :事务类型
        • dataSource type=“POOLED” :数据库连接池
          • property name="" value="" :连接数据库的4个基本信息
    • mappers
      • mapper resource="" :指定映射配置文件的项目路径
<?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="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"></transactionManager>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="cn/water/dao/UserDao.xml"/>
        </mappers>
    </configuration>

测试类

  1. 加载 MyBatis主配置文件(Resources.getResourceAsStream),获取IO流(InputStream)
  2. **通过 工厂建造者类(SqlSessionFactoryBuilder),创建 工厂类(build())
  3. 通过 工厂类(SqlSessionFactory),生产 SqlSession对象(openSession())
  4. 通过 Session对象(SqlSession),创建 持久层接口的代理对象(getMapper(UserDao.class))
  5. 通过 代理对象,执行方法
  6. 释放资源(SqlSession)(InputStream)

UserTest.java

package cn.water.test;

import cn.water.dao.UserDao;
import cn.water.domain.User;
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;
import java.util.List;

public class UserTest {

    public static void main(String[] args) throws IOException {

        /* 读取 MyBatis主配置文件 */
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        /* 通过 工厂建造者类,创建 工厂类 */
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        /* 通过 工厂类,生产 SqlSession对象 */
        SqlSession sqlSession = factory.openSession();
        /* 通过 SqlSession对象,创建 持久层接口的代理对象 */
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        /* 通过 代理对象,执行方法 */
        List<User> all = userDao.findAll();
        /* 遍历 */
        for (User user : all) {
            System.out.println(user);
        }
        /* 释放资源 */
        sqlSession.close();
        inputStream.close();
        
    }

}

运行结果

User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}

设计模式

构建者模式

  • 定义:
    • 指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。
  • 举例
    • 计算机是由 OPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将不同计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。
  • 优点
    • 各个具体的建造者相互独立,有利于系统的扩展。
    • 客户端不必知道产品内部组成的细节,便于控制细节风险。
  • 缺点
    • 产品的组成部分必须相同,这限制了其使用范围。
    • 如果产品的内部变化复杂,该模式会增加很多的建造者类。
InputeStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder;
SqlSessionFactory factory = builder.build(in);

工厂模式

  • 定义
    • 定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。
  • 举例
    • 各种产品有专门的工厂生产。在苹果工厂,我们可以拿到iPhone、iPad和macbook;在华为工厂,我们可以拿到p30,mate20,Matebook。我们不关心产品是如何做的,甚至可以不关心产品的名字(拿到工厂你就拿到了产品)。
  • 优点
    • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
    • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
  • 缺点
    • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
  • 区别
    • 建造者模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
SqlSession sqlSession = factory.openSession();

代理模式

  • 定义
    • 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
  • 举例
    • 购买火车票不一定要去火车站买,可以通过 12306 网站或者去火车票代售点买。
  • 优点
    • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
    • 代理对象可以扩展目标对象的功能;
    • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;
  • 缺点
    • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
    • 增加了系统的复杂度;
List<User> list = dao.findAll();

方法二:注解

  • 注解可以代替映射配置文件。

目录结构

  • src/main
    • java
      • cn/water/dao
        • AnnoUserDao.java(持久层接口)
      • cn/water/domain
        • AnnoUser.java(持久层)
    • resources
      • SqlMapConfig.xml(MyBatis主配置文件)
  • src/tese
    • java
      • cn/water/test
        • AnnoUserTest.java(测试文件)

实体类

AnnoUser.java

package cn.water.domain;

import java.io.Serializable;
import java.util.Date;

public class AnnoUser implements Serializable {

    /* 成员变量 */
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

持久层接口(注解)

  • 在持久层接口的抽象方法上添加 @Select注解并编写SQL语句

AnnoUserDao.java

package cn.water.dao;

import cn.water.domain.User;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface AnnoUserDao {

    /** 查询所有用户 */
    @Select("SELECT * FORM user;")
    public abstract List<User> findAll();

}

映射配置文件(删除)

MyBatis主配置文件(映射)

  • environments 标签中的内容用于连接MySQL数据库无需更改。
  • 在 mappers 标签中添加映射
    • 方法一:使用class属性,指定被注解的持久层接口的全类名。
    • 方法二:使用package标签,指定被注解的持久层接口的包。

SqlMapConfig.xml

<mappers>
    <mapper class="cn.water.dao.AnnoUserDao"></mapper>
</mappers>
<mappers>
	<package name="cn.water.dao"/>
</mappers>

测试类

AnnoUserTest.java

package cn.water.test;

import cn.water.dao.AnnoUserDao;
import cn.water.dao.UserDao;
import cn.water.domain.AnnoUser;
import cn.water.domain.User;
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;
import java.util.List;

public class AnnoUserTest {

    public static void main(String[] args) throws IOException {

        /* 读取 MyBatis主配置文件 */
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        /* 通过 工厂建造者类,创建 工厂类 */
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        /* 通过 工厂类,生产 SqlSession对象 */
        SqlSession sqlSession = factory.openSession();
        /* 通过 SqlSession对象,创建 持久层接口的代理对象 */
        AnnoUserDao annoUserDao = sqlSession.getMapper(AnnoUserDao.class);
        /* 通过 代理对象,执行方法 */
        List<AnnoUser> all = annoUserDao.findAll();
        /* 遍历 */
        for (AnnoUser user : all) {
            System.out.println(user);
        }
        /* 释放资源 */
        sqlSession.close();
        inputStream.close();

    }

}

运行结果

User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}

方法三:创建持久层接口实现类

目录结构

  • src/main
    • java
      • cn/water/dao
        • ImpUserDao.java(持久层接口)
        • ImpUserDaoImp.java(持久层接口的实现类)
      • cn/water/domain
        • ImpUser.java(持久层)
    • resources
      - cn/water/dao
      - ImpUserDao.xml(持久层接口的映射配置文件)
      - SqlMapConfig.xml(MyBatis主配置文件)
  • src/tese
    • java
      • cn/water/test
        • ImpUserTest.java(测试文件)

实体类

ImpUser.java

package cn.water.domain;

import java.io.Serializable;
import java.util.Date;

public class ImpUser implements Serializable {

    /* 成员变量 */
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

持久层接口

ImpUserDao.java

package cn.water.dao;

import cn.water.domain.ImpUser;
import cn.water.domain.User;
import java.util.List;

public interface ImpUserDao {

    /** 查询所有用户 */
    public abstract List<ImpUser> findAll();

}

持久层接口实现类(新增)

ImpUserDaoImp.java

package cn.water.dao.imp;

import cn.water.dao.ImpUserDao;
import cn.water.domain.ImpUser;
import cn.water.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;


public class ImpUserDaoImp implements ImpUserDao {

    /* 成员变量:工厂类 */
    private SqlSessionFactory factory;

    /* 构造方法(工厂类) */
    public ImpUserDaoImp(SqlSessionFactory factory) {
        this.factory = factory;
    }

    /* 实现的接口的方法 */
    public List<ImpUser> findAll() {
        /* Session对象 */
        SqlSession sqlSession = factory.openSession();
        /* 获取代理对象 */
        ImpUserDao impUserDao = sqlSession.getMapper(ImpUserDao.class);
        /* 使用SqlSession对象 执行查询所有方法 */
             /* 参数Statement:映射配置文件的namespace属性值+id属性值 */
        List<ImpUser> list = sqlSession.selectList("cn.water.dao.ImpUserDao.findAll");
        /* 释放资源 */
        sqlSession.close();
        /* 返回 */
        return list;
    }

}

映射配置文件(修改)

ImpUserDao.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">

    <!-- 配置映射 -->
    <mapper namespace="cn.water.dao.ImpUserDao">  
        <select id="findAll" resultType="cn.water.domain.ImpUser">   
            SELECT * FROM user;    
        </select>
    </mapper>

MyBatis主配置文件(映射)

SqlMapConfig.xml

<mappers>
	<mapper resource="cn/water/dao/ImpUserDao.xml"></mapper>
</mappers>

测试类(更改)

ImpUserTest.java

package cn.water.test;

import cn.water.dao.ImpUserDao;
import cn.water.dao.UserDao;
import cn.water.dao.imp.ImpUserDaoImp;
import cn.water.domain.ImpUser;
import cn.water.domain.User;
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;
import java.util.List;


public class ImpUserTest {

    public static void main(String[] args) throws IOException {
        /* 读取 MyBatis主配置文件 */
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        /* 通过 工厂建造者类,创建 工厂类 */
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        /* --创建 持久层接口实现类,传递 工厂类-- */
        ImpUserDao impUserDao = new ImpUserDaoImp(factory);
        /* --执行 持久层实现类的方法-- */
        List<ImpUser> all = impUserDao.findAll();
        /* 遍历 */
        for (ImpUser user : all) {
            System.out.println(user);
        }
        /* 释放资源 */
        inputStream.close();
    }

}

运行结果

User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}

区别

SQL语句

映射配置文件

  • 持久层接口
List<UserAnno> findAll();
  • 映射配置文件
<!-- 配置映射 -->
<mapper namespace="cn.water.dao.UserDao">   
    <select id="findAll" resultType="cn.water.domain.User">   
        SELECT * FROM user;     
    </select>
</mapper>

持久层接口实现类

  • 持久层接口
List<UserAnno> findAll();
  • 映射配置文件
<!-- 配置映射 -->
<mapper namespace="cn.water.dao.ImpUserDao">
    <select id="findAll" resultType="cn.water.domain.ImpUser">
        SELECT * FROM user;
    </select>
</mapper>

注解

  • 持久层接口
@Select("SELECT * FROM user;")
List<UserAnno> findAll();

mappers标签

  • MyBatis主配置文件
<mappers>

    <!-- 映射配置文件:使用resource属性,指定映射配置文件的项目路径。 -->
    <mapper resource="cn/water/dao/UserDao.xml"></mapper>
    
    <!-- 持久层实现类:使用resource属性,指定映射配置文件的项目路径。 -->
    <mapper resource="cn/water/dao/ImpUserDao.xml"></mapper>
    
    <!-- 注解:使用class属性,指定被注解的持久层接口的全类名。 -->
    <mapper class="cn.water.dao.AnnoUserDao"></mapper>
    
    <!-- 注解:使用package标签,指定被注解的持久层接口的包。 -->
    <package name="cn.water.dao"/>
    
</mappers>

执行

映射配置文件

  • 测试类
/* 1.读取 MyBatis主配置文件 */
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 2.通过 工厂建造者类,创建 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
/* 3.通过 工厂类,生产 SqlSession对象 */
SqlSession sqlSession = factory.openSession();

/* 4.通过 SqlSession对象,创建 持久层接口的代理对象 */
UserDao userDao = sqlSession.getMapper(UserDao.class);
/* 5.通过 代理对象,执行方法 */
List<User> all = userDao.findAll();
/* 6.遍历 */
for (User user : all) {
    System.out.println(user);
}
/* 7.释放资源 */
sqlSession.close();
inputStream.close();

持久层接口实现类

  • 持久层接口实现类
/* 4.Session对象 */
SqlSession sqlSession = factory.openSession();
/* 5.获取代理对象 */
ImpUserDao impUserDao = sqlSession.getMapper(ImpUserDao.class);
/* 6.调用方法 */
List<ImpUser> users = impUserDao.findAll();
/* 7.释放资源 */
sqlSession.close();
  • 测试类
/* 1.读取 MyBatis主配置文件 */
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 2.通过 工厂建造者类,创建 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

/* 3.创建 持久层接口实现类,传递 工厂类 */
ImpUserDao impUserDao = new ImpUserDaoImp(factory);

/* 8.执行 持久层实现类的方法 */
List<ImpUser> all = impUserDao.findAll();
/* 9.遍历 */
for (ImpUser user : all) {
    System.out.println(user);
}
/* 10.释放资源 */
inputStream.close();

注解

/* 1.读取 MyBatis主配置文件 */
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/* 2.通过 工厂建造者类,创建 工厂类 */
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
/* 3.通过 工厂类,生产 SqlSession对象 */
SqlSession sqlSession = factory.openSession();

/* 4.通过 SqlSession对象,创建 持久层接口的代理对象 */
AnnoUserDao annoUserDao = sqlSession.getMapper(AnnoUserDao.class);
/* 5.通过 代理对象,执行方法 */
List<AnnoUser> all = annoUserDao.findAll();
/* 6.遍历 */
for (AnnoUser user : all) {
    System.out.println(user);
}
/* 7.释放资源 */
sqlSession.close();
inputStream.close();

报错

错误一:IllegalArgumentException

错误代码

Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for cn.water.dao.UserImpDao

错误原因一:SqlSession调用selectList方法的参数错误

<!-- 持久层接口的映射配置文件 -->

<mapper namespace="cn.water.dao.UserImpDao">
    <select id="findAll" resultType="cn.water.domain.UserImp">
        SELECT * FROM user;
    </select>

/* 持久层接口的实现类*/

public class UserImpDaoImpl implements UserImpDao {
	public List<UserImp> findAll() {
       
    	/* 错误参数:持久层接口的映射配置文件的namespace属性值 */
        List<UserImp> list = sqlSession.selectList("cn.water.dao.UserImpDao");
     	
        /* 正确参数:持久层接口的映射配置文件的namespace属性值+id属性 */
        List<UserImp> list = sqlSession.selectList("cn.water.dao.UserImpDao.findAll");
        
	}
}

错误原因二:MyBatis主配置文件中没有设置mapper标签

<!-- 映射配置文件:使用resource属性指定映射配置文件的位置。 -->
<mappers>
	<mapper resource="cn/water/dao/UserImpDao.xml"></mapper>
</mappers>