一. 简介

1.1 什么是 MyBatis

  • MyBatis 是一款优秀的 持久层框架
  • 它支持定制化 SQL,存储过程以及高级映射
  • MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果
  • MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型,接口和 Java 的 POJO (普通老师 Java 对象)为数据库中的记录
  • MyBatis 本质是 Apache 的一个开源项目,原名是 itbais

1.2 持久化

数据持久化

  • 持久化就是将程序的数据在持久状态瞬时状态的过程
  • 内存:断电即失
  • 数据库(jdbc)、io 文件持久化

为什么持久化?

  • 一些对象不能丢掉
  • 内存比较贵

1.3 持久层

Dao 层,Service 层,Controller 层。。

  • 完成持久化工作的代码块
  • 层界限十分明显

1.4 为什么学习 MyBatis ?

  • 方便
  • 简化 JDBC 代码,使用框架完成持久层的操作
  • 不用 MyBatis 也可以,更容易上手
  • 优点:
    • 简单易学
    • 灵活
    • sql 代码的分离,提高可维护性
      • 提供标签映射,支持对象与数据库的 ORM, 字段关系映射
      • 提供映射标签,支持对象关系组建维护
      • 提供 xml 标签,支持动态 SQL

二 快速入门

2.1 搭建一个 maven 项目

并导入 如下依赖

  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis</artifactId>
  4. <version>3.5.5</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>mysql</groupId>
  8. <artifactId>mysql-connector-java</artifactId>
  9. <version>5.1.10</version>
  10. </dependency>

2.2 数据库创建

USE `test`;

/*Table structure for table `product` */

DROP TABLE IF EXISTS `product`;

CREATE TABLE `product` (
  `pid` int(5) NOT NULL AUTO_INCREMENT,
  `product_name` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  `price` float DEFAULT NULL,
  `introduce` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
  `address` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `product` */

insert  into `product`(`pid`,`product_name`,`price`,`introduce`,`address`) values (1,'冰箱',2400,'海尔牌冰箱','杭州'),(2,'小米手机',2199,'小米牌手机,性价比之王','武汉'),(3,'MAC 口红',399,'MAC 最新上市','美国 加利福尼亚'),(4,'旺仔牛奶',40,'旺仔牛奶,你的最爱','北京'),(5,'辣条',5,'最爱辣条','江苏 南京'),(6,'牛奶',39.9,'蒙牛牛奶','新疆'),(7,'tedt',20,'test','你猜'),(8,'华为手机',3999,'华为 mate40 pro','武汉'),(9,'小米巨能写笔',22.3,'可以连续写字一个月以上','中国 湖北 武汉'),(11,'红米 note9',999.9,'老人机专属','暂时保密');

2.3 类编写

数据库对应实体类

public class Product {
    private Integer id; // pid
    private String name; //product_name
    private Double price;
    private String introduce;
    private String address;

    // 构造方法,getter,setter 省略
}

mapper 接口创建

package cn.gorit.mapper;

import cn.gorit.entity.Product;

import java.util.List;

public interface ProductMapper {

    // 查询所有的数据
    List<Product> selectAllProduct();

    // 根据 id 查询
    Product selectProductById(int id);

    // 新增数据
    void insertProduct(Product product);

    // 修改数据,修改之前先查询数据
    void updateProduct(Product product);

    // 删除数据
    void deleteProductById(int id);
}

2.4 配置文件编写

在 Resources 目录下创建 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>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
<!-- 映射文件的路径配置 -->
    <mappers>
        <mapper resource="./productMapper.xml"/>
    </mappers>
</configuration>

在 Resources 目录下创建 productMapper.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.gorit.mapper.ProductMapper">
    <!-- 映射关系,当实体类字段和数据库字段不一致时,使用该字段解决数据库数据无法注入实体类中的情况 -->
    <resultMap id="proMap" type="cn.gorit.entity.Product">
        <id column="pid" property="id"/>
        <result column="product_name" property="name"/>
        <result column="price" property="price"/>
        <result column="introduce" property="introduce"/>
        <result column="address" property="address"/>
    </resultMap>
    <!-- 这里封装一些通用的 sql 语句 -->
    <sql id="s1">
        select  * from product
    </sql>

    <!-- 下面的标签对应着增删改查的方法
        id  就对应着 上面的 ProductMapper 中的一个具体的方法名
        resultMap 代表结果集使用 上面的映射
        parameterType  传入的参数类型
        parameterType  传入的参数为 Product 实体类
    -->
    <select id="selectAllProduct" resultMap="proMap">
        <include refid="s1"/>
    </select>
    <select id="selectProductById" parameterType="int" resultMap="proMap">
        <include refid="s1"/>
            where pid = #{id}
    </select>
    <insert id="insertProduct" parameterType="cn.gorit.entity.Product">
        insert into product(product_name,price,introduce,address) values (#{name},#{price},#{introduce},#{address})
    </insert>
    <update id="updateProduct" parameterType="cn.gorit.entity.Product">
        update product set product_name = #{name},price = #{price},introduce = #{introduce},address = #{address}
             where pid = #{id}
    </update>
    <delete id="deleteProductById" parameterType="int">
        delete from product where pid = #{id}
    </delete>
</mapper>

2.5 测试类

package cn.gorit.test;

import cn.gorit.entity.Product;
import cn.gorit.mapper.ProductMapper;
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.Reader;
import java.util.List;

public class Test {
    public static void main(String[] args) throws IOException {
        // 加载配置文件
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);

        // 创建能执行映射文件中的 SqlSession
        SqlSession session = sessionFactory.openSession();
        // 获取映射,自动创建 mapper 接口的实现,直接调用数据库的方法
        ProductMapper mapper = session.getMapper(ProductMapper.class);

        // 查询一条记录
//        Product product = mapper.selectProductById(1);
//        System.out.println(product.toString());

        // 查询多条记录
        List<Product> list = mapper.selectAllProduct();
        for (Product p:list) {
            System.out.println(p);
        }

        // 修改记录
//        product.setName("小米巨能写笔");
//        product.setIntroduce("可以连续写字一个月以上");
//        product.setAdress("中国 湖北 武汉");
//
//        mapper.updateProduct(product);
//        session.commit();

        // 添加记录
//        Product product1 = new Product("红米 note9",999.9,"老人机专属", "暂时保密");
//        mapper.insertProduct(product1);
//        session.commit();

        // 删除记录
//        mapper.deleteProductById(10);
//        session.commit();

    }
}

三、常用开发技巧 —— 使用 HashMap 映射

3.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>

    <!-- mybatis 的基础配置文件 -->
    <settings>
        <!-- 打印 SQL 信息 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!-- 使用主键 -->
        <setting name="useGeneratedKeys" value="true"/>
    </settings>

    <!-- 代码风格,是否为 驼峰命名法 -->    
    <typeAliases>
    <!--        <typeAlias type="cn.gorit.entity.Student" alias="student"></typeAlias>-->
        <package name="cn.gorit.entity"/> <!-- 默认的别名是首字母小写 -->
    </typeAliases>
    <!-- 环境配置 -->
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <!-- 项目 mapper 配置 -->
    <mappers>
        <mapper resource="./StudentMapper.xml"/>
    </mappers>
</configuration>

3.2 mapper.xml 配置

    <!-- 使用 hashmap 映射 -->
    <select id="selectStudentById" parameterType="int" resultType="hashmap">
        select * from student where id = #{id}
    </select>

3.3 实体类

public class Student {
    private Integer id;
    private String name;
    private String gender;
    private int age;

    // getter 和 setter 构造方法省略
}

3.4 接口

public interface StudentMapper {

    // 使用 map 获得数据
    public Map selectStudentById(int id);

}

3.5 测试

        Map<Object,Object> map = mapper.selectStudentById(1);
        System.out.println(map.toString());

四、常用开发技巧 —— 循环插入数据

4.1 mapper.xml 配置

     <!--        <sql id="s2">-->
<!--              insert into student(sname,gender,age) values-->
<!--        </sql>-->
    <!-- 使用循环插入多条数据,useGenerated 上面已经添加过了 -->
    <insert id="insertStudents" keyProperty="id">
        <!-- 使用 foreach 实现循环遍历 -->
        <include refid="s2"/>
            <foreach collection="slist" item="stu" separator=",">
                (#{stu.name},#{stu.gender},#{stu.age})
            </foreach>
    </insert>

4.2 接口

    // 在 xml 中使用 foreach 循环插入数据
    public void insertStudents(Map<String,List<Student>> map);

4.3 测试

        List<Student> list = new ArrayList<>();
        list.add(new Student("a1","男",14));
        list.add(new Student("a2","女",16));
        list.add(new Student("a3","男",18));

        Map<String,List<Student>> map = new HashMap<>();
        map.put("slist",list);
        mapper.insertStudents(map);
        session.commit();