程序员社区

2. 初识MyBatis

初识MyBatis

      • 1. MyBatis 简介
      • 2. MyBatis 快速入门
      • 3. 使用 MyBatis 的注意事项
      • 4. 自定义接口

1. MyBatis 简介

什么是 MyBatis?

  1. MyBatis 是 Apache 的一个开源项目 iBatis,2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,由谷歌公司负责维护,并且改名为 MyBatis;2013 年 11 月迁移到 Github。

  2. MyBatis 是一个企业级数据持久化的开发框架,支持三种语言的实现,如Java、.NET 和 Ruby,可以理解为一个底层是 JDBC 的封装框架。

目前常用的企业级数据持久化框架:Hibernate、MyBatis、Spring Data JPA、MyBatis Plus

ORM:Object Relationship Mapping,即对象关系映射,把面向对象的 JavaBean 和关系型数据表进行字段与属性之间的逐一映射。

2. 初识MyBatis插图

MyBatis 是目前主流的 ORM 框架,MyBatis 消除了几乎所有的 JDBC 代码和参数的手动配置以及对结果集的遍历与封装,可以使用简单的 XML 或注解用于配置和原始映射,通过接口将 JavaBean 映射成数据库中的记录。

MyBatis 的优点:

  • 极大地简化了底层 JDBC 代码的开发;
  • 简单易于上手、具有很强的灵活性;
  • SQL 写入 XML 配置文件,实现和 Java 代码的解耦合;
  • 支持动态 SQL,可以根据具体业务灵活实现需求;

MyBatis 的缺点:

  1. 相比于 Hibernate,开发者需要完成更多的工作,比如:定义 SQL、完成结果集与实体类的匹配;
  2. 要求开发人员具备一定的 SQL 编写能力;
  3. 数据库移植性较差,因为 SQL 依赖底层的数据库,如果要进行数据库迁移,部分 SQL 需要重新编写。

2. MyBatis 快速入门

Step1:首先创建 Maven 工程,在工程目录下的 pom.xml 添加相关依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.training</groupId>
    <artifactId>mavenPro</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--添加 jar 包的依赖-->
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>

</project>

Step2:创建数据表与对应的实体类 User
2. 初识MyBatis插图1

create table test.user
(
    id int auto_increment primary key,
    name varchar(225) null,
    score double null
);
package com.training.entity;

import lombok.Data;

//使用这个插件后,默认生成属性的Getter与Setter方法以及无参构造方法
@Data
public class User {
    private Integer id;
    private String name;
    private Double score;
}

Step3:创建 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">
            <!--配置JDBC事务管理-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- POOLED配置JDBC数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>
</configuration>

4、调用API完成操作(使用原生接口)

MyBatis 框架需要开发者自定义 SQL 语句,写在 XxxMapper.xml 文件中。实际开发中,会为每个实体类创建对应的 XxxMapper.xml,定义管理该对象数据的 SQL。

创建 Mapper 文件 UserMapper.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="com.training.mapper.UserMapper">
    <select id="get" parameterType="int" resultType="com.training.entity.User">
        select * from user where id=#{id}
    </select>
    
    <insert id="increase" parameterType="com.training.entity.User">
        insert into user (id,name,score) values (#{id},#{name},#{score});
    </insert>
</mapper>
  • namespace 通常为所在包 + 文件名的形式;
  • insert 标签表示执行添加操作;
  • select 标签表示执行查询操作;
  • update 标签表示执行更新操作;
  • delete 标签表示执行删除操作
  • id 是实际调用 MyBatis 方法时需要用到的参数;
  • parameterType 是调用对应方法时参数的数据类型;
  • resultType 是调用方法返回结果集的类型;

在全局配置文件 config.xml 中注册 UserMapper.xml

<!-- 注册UserMapper.xml -->
<mappers>
    <mapper resource="com/training/mapper/UserMapper.xml"></mapper>
</mappers>

调用原生接口执行 SQL,获取结果集

import com.training.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class Test {
    public static void main(String[] args) {
        //加载MyBatis配置信息
        InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
        //构建SQLSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new
                SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        //获取SqlSession
        SqlSession sqlSession = factory.openSession();

        //查询操作
        String statement1 = "com.training.mapper.UserMapper.get";
        User user = (User)sqlSession.selectOne(statement1, 1);
        System.out.println(user);
        //增加操作
        String statement2 = "com.training.mapper.UserMapper.increase";
        User user1 = new User(4,"赵六",89.5);
        sqlSession.insert(statement2,user1);
        sqlSession.commit();
    }
}

如果控制台报错:Cause: java.io.IOException: Could not find resource com/training/mapper/UserMapper.xml,需要在 pom.xml 中增加以下配置信息,以便让src/main/java路径下的 XML 文件可以被读取到。

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

修改之后,程序正常运行。控制台的输出结果如下:
2. 初识MyBatis插图2


3. 使用 MyBatis 的注意事项

  1. Mapper.xml 必须要在 config.xml (全局环境配置)中进行注册,才可以使用,否则会抛出异常;

    在这里插入图片描述

    <!-- 注册UserMapper.xml -->
    <mappers>
        <mapper resource="com/training/mapper/UserMapper.xml"></mapper>
    </mappers>
    
  2. statement 执行字符串必须是 Mapper 接口的命名空间 + 方法 id;

    在这里插入图片描述

  3. 需要修改 pom.xml,让 src/main/java 路径下的 XML 文件可以被读取到,默认只能读取到 src/main/resources 下的配置信息,所以需要手动设置,否则会抛出如下异常;

    在这里插入图片描述

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
    

4. 自定义接口

通过 Mapper 代理实现自定义接口,解决原生接口所带来的弊端,由于原生方式每次调用业务方法,都需要拼接字符串 String statement = "com.training.mapper.UserMapper.increase",使得调用方法比较繁琐,且易于出错。因此,在实际项目开发中,通常推荐使用自定义接口:

  1. 自定义接口,定义相关的业务方法;
  2. 编写与方法对应的 Mapper.xml;

Step1:自定义接口

package com.training.mapper;

import com.training.entity.User;

import java.util.List;

public interface UserMapper {
    public User findById(Integer id);
    public List<User> findAll();
    public int add(User user);
    public int deleteById(Integer id);
    public int update(User user);
}

Step2:创建接口对应的 UserMapper.xml,定义接口方法对应的 SQL 语句

MyBatis 框架会根据规则(接口与XML配置)自动创建接口实现类的代理对象

规则:statement 标签可根据 SQL 执行的业务选择 insert、delete、update、select

  1. UserMapper.xml 中 namespace 为接口的全类名;
  2. UserMapper.xml 中 statement 的 id 为接口中对应的方法名;
  3. UserMapper.xml 中 statement 的 parameterType 和接口中定义方法的参数类型一致;
  4. UserMapper.xml 中 statement 的 resultType 和接口中对应方法的返回值类型一致;
<?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.training.mapper.UserMapper">
    <insert id="add" parameterType="com.training.entity.User">
        insert into user(name,score) values(#{name},#{score})
    </insert>

    <delete id="deleteById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>

    <update id="update" parameterType="com.training.entity.User">
      update user set name=#{name},score=#{score} where id=#{id}
    </update>
    
    <select id="findById" parameterType="java.lang.Integer" resultType="com.training.entity.User">
        select * from user where id=#{id};
    </select>

    <select id="findAll" resultType="com.training.entity.User">
        select * from user;
    </select>

</mapper>

Step3:在全局配置文件 config.xml 中注册 UserMapper.xml

<mappers>
    <mapper resource="com/training/mapper/UserMapper.xml"></mapper>
</mappers>

Step4:调用接口的代理对象完成相关的业务操作

package com.training.test;

import com.training.entity.User;
import com.training.mapper.UserMapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //加载MyBatis配置信息
        InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
        //构建SQLSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new
                SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        //获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //获取实现接口的代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //查询id为2的用户对象
        System.out.println(mapper.findById(2));
        //查询全部对象
        List<User> users = mapper.findAll();
        System.out.println(users);
        //增加用户对象
        User user1 = new User();
        user1.setName("小明");
        user1.setScore(86.5);
        int add = mapper.add(user1);
        System.out.println(add);
        //增删改需要提交事务,查询不需要
        sqlSession.commit();
    }
}

注意:修改对象时,先通过查询方法查找指定 id 的用户对象,再调用该用户的 set 方法对字段信息进行修改,最后将修改后的用户对象传入更新方法完成修改操作。

如果数据表的字段名与实体类的属性名不同时,则需要在 UserMapper.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="com.training.mapper.UserMapper">
    <insert id="add" parameterType="com.training.entity.User">
        insert into user(name,score) values(#{stuName},#{stuScore})
    </insert>

    <delete id="deleteById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>

    <update id="update" parameterType="com.training.entity.User">
      update user set name=#{stuName},score=#{stuScore} where id=#{stuId}
    </update>

    <resultMap id="userMap" type="com.training.entity.User">
        <id property="stuId" column="id"></id>
        <result property="stuName" column="name"></result>
        <result property="stuScore" column="score"></result>
    </resultMap>

    <select id="findById" parameterType="java.lang.Integer" resultMap="userMap">
        select * from user where id=#{id};
    </select>

    <select id="findAll" resultMap="userMap">
        select * from user;
    </select>

</mapper>

注意:

  1. 如果数据表字段名与 JavaBean 属性名不一致时,执行查询业务获取结果集时,要对字段名与属性名进行逐一映射;
  2. parameterType 参数是全类名时,比如:com.training.entity.User,传入的 #{stuName} 是对象的属性名,底层会通过反射机制调用 get 方法,即会调用 getStuName() 方法完成数据的注入,如果误写成数据表的字段 #{name},则会报错找不到 getName() 方法。

测试类 Test

public class Test {
    public static void main(String[] args) {
        //加载MyBatis配置信息
        InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
        //构建SQLSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new
                SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(inputStream);
        //获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //获取实现接口的代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //查询id为2的用户对象
        System.out.println(mapper.findById(2));
        //修改用户信息
        User user1 = mapper.findById(2);
        user1.setStuName("李力");
        user1.setStuScore(96.5);
        int update = mapper.update(user1);
        System.out.println(update);
        //删除用户
        int delete = mapper.deleteById(5);
        System.out.println(delete);
        //查询全部对象
        List<User> users = mapper.findAll();
        System.out.println(users);
    }
}

控制台的打印结果如下:

在这里插入图片描述

赞(0) 打赏
未经允许不得转载:IDEA激活码 » 2. 初识MyBatis

一个分享Java & Python知识的社区