MyBatis 入门

什么是MyBatis

MyBatis 是当前主流的 ORM 框架,是由 Apache 提供的一个开源项目,之前的名字叫做 iBatis,2010 年迁移到了 Google Code,并且将名字改为我们现在所熟知的 MyBatis,又于 2013 年 11 月迁移到了 Github。MyBatis 是一个帮助开发者实现数据持久化工作的框架,它同时支持 Java、.NET、Ruby 三种语言的实现,当然我们这里讲的是在 Java Application 中的使用,初学者可以将 MyBatis 简单理解为一个对 JDBC 进行封装的框架。

说到 ORM 框架就不得不提 Hibernate,Hibernate 是实现了 JPA 规范的 ORM 框架,使用非常广泛,Spring Data JPA 底层就是采用 Hibernate 技术支持。同为 ORM 框架,MyBatis 与 Hibernate 的区别是什么呢?

Hibernate 是一个“全自动化”的 ORM 框架,而 MyBatis 则是一个“半自动化”的 ORM 框架。

什么是“全自动化”?意为开发者只需要调用相关接口就可以完成操作,整个流程框架都已经封装好了,开发者无需关注。具体来讲 Hibernate 实现了 POJO 和数据库表之间的映射,同时可以自动生成 SQL 语句并完成执行。

“半自动化”指的是框架只提供了一部分功能,剩下的工作仍需要开发者手动完成,MyBatis 框架没有实现 POJO 与数据库表的映射,它只实现了 POJO 与 SQL 之间的映射关系,同时需要开发者手动定义 SQL 语句,以及数据与 POJO 的装配关系。

虽然功能上没有 Hibernate 更加方便,但是这种“半自动化”的方式提高了框架的灵活性,MyBatis 对所有的 JDBC 代码实现了封装,包括参数设置、SQL 执行、结果集解析等,通过 XML 配置的方式完成 POJO 与数据的映射。

MyBatis 的优点

  • 极大地简化了 JDBC 代码的开发
  • 简单好用、容易上手,具有更好的灵活性
  • 通过将 SQL 定义在 XML 文件中的方式降低呈现的耦合度
  • 支持动态 SQL,可根据具体业务灵活实现需求

MyBatis 的缺点

  • 相比于 Hibernate,开发者需要完成更多工作,如定义 SQL、设置 POJO 与数据的映射关系等
  • 要求开发人员具备一定的 SQL 编写能力,在一些特定场景下工作量较大
  • 数据库移植性较差,因为 SQL 依赖于底层数据库,如果要进行数据库迁移,部分 SQL 需要重新编写

整体来说,MyBatis 是一个非常不错的持久层解决方案,它专注于 SQL 本身,非常灵活,适用于需求变化较多的互联网项目,也是当前主流的 ORM 框架。

MyBatis 快速入门

(1)创建 Maven 工程,pom.xml 添加相关依赖,我们使用 MySQL 数据库,因此需要额外引入 MySQL 驱动依赖。为了在控制台上显示SQL语句,还需要引入log4j依赖。

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.11</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

在resources目录下新建log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
    <!-- 将日志信息输出到控制台 -->
    <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
        <!-- 设置日志输出的样式 -->
        <layout class="org.apache.log4j.PatternLayout">
            <!-- 设置日志输出的格式 -->
            <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss:SSS}] %m%n" />
        </layout>
        <!--过滤器设置输出的级别-->
        <filter class="org.apache.log4j.varia.LevelRangeFilter">
            <!-- 设置日志输出的最小级别 -->
            <param name="levelMin" value="DEBUG" />
            <!-- 设置日志输出的最大级别 -->
            <param name="levelMax" value="ERROR" />
            <!-- 设置日志输出的xxx,默认是false -->
            <param name="AcceptOnMatch" value="true" />
        </filter>
    </appender>
    <!-- 根logger的设置-->
    <root>
        <appender-ref ref="ConsoleAppender"/>
    </root>
</log4j:configuration>

(2)新建数据表

CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(255) DEFAULT NULL,
    user_email varchar(255) DEFAULT NULL,
    user_city varchar(255) DEFAULT NULL,
    age int(11) DEFAULT NULL,
  PRIMARY KEY (id)
)

(3)创建user表对应的实体类

public class User {
    private Integer id;
    private String username;
    private String userEmail;
    private String userCity;
    private Integer age;
    // 省略get、set方法
}

(4)在 resources 路径下创建 MyBatis 配置文件mybatis- config.xml(文件名可自定义),配置数据源信息。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <!-- 配置 MyBatis 运行环境 -->
        <environment id="development">
            <!-- 配置 JDBC 事务管理 -->
            <transactionManager type="JDBC"/>
            <!-- POOLED 配置 JDBC 数据源连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

(5)MyBatis 开发有两种方式:

  • 使用原生接口
  • Mapper 代理实现自定义接口

先来说第一种使用原生接口的开发方式。

第一步,在resources目录下创建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">
<!--
namespace: 命名空间, 如果有对应的接口,需要指定为对应接口的全类名, 如果使用原生接口, 则可以随便填写
id: 唯一标识
parameterType: 为参数数据类型,可以省略
resultType: 为返回值数据类型
#{username}是获取传递过来的参数中获取 username 的值
-->
<mapper namespace="com.example.mybatis.mapper.UserMapper">
    <select id="getUserByUserName"
            parameterType="java.util.String"
            resultType="com.example.mybatis.entity.User">
        select
        id,
        username,
        user_email userEmail,
        user_city userCity,
        age
        from user
        where username = #{username}
    </select>
</mapper>

第二步,在全局配置文件 mybatis-config.xml 中注册 UseMapper.xml。

<configuration>
    <environments default="development">
        <!-- 配置 MyBatis 运行环境 -->
        <environment id="development">
            <!-- 配置 JDBC 事务管理 -->
            <transactionManager type="JDBC"/>
            <!-- POOLED 配置 JDBC 数据源连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 注册UserMapper.xml -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

第三步,在测试类中调用原生接口执行 SQL 语句获取结果。

public class App1 {
    public static void main( String[] args ) {
        // 加载 MyBatis 配置文件
        InputStream is = App1.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        // 获取 SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 调用 MyBatis 原生接口执行 SQL
        // statement 为 UserMapper.xml 的 namespace 值+"."+select 标签的 id 值
        String statement = "com.example.mybatis.mapper.UserMapper.getUserByUserName";
        User user = sqlSession.selectOne(statement , "zhangsan");
        // SqlSession的selectOne(String var1, Object var2)方法
        // 可以发现第二个参数是Object类型的,
        // 例子中我们只传递了一个参数, 如果想传入多个参数的话, 可以传递一个Map或者是一个实体类对象
        System.out.println(user);
    }
}

我们在实际开发中,推荐使用第二种方式:自定义接口,但是开发者不需要实现该接口,只需要定义即可,具体的实现工作由 Mapper 代理结合配置文件完成,实现逻辑或者说要执行的 SQL 语句配置在 Mapper.xml 中。

第一步,自定义接口

public interface UserMapper {
    public User getUserByUserName(String userName);
    public List<User> getUserList();
    public int addUser(User user);
    public int deleteUser(Integer id);
    public int updateUser(User user);
}

第二步, 将UserMapper.xml中的namespace设置为UserMapper的全类名

<?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">
<!--
namespace: 命名空间, 如果有对应的接口,需要指定为对应接口的全类名, 如果使用原生接口, 则可以随便填写
id: 唯一标识
parameterType: 为参数数据类型,可以省略
resultType: 为返回值数据类型
#{username}是获取传递过来的参数中获取 username 的值
-->
<mapper namespace="com.example.mybatis.mapper.UserMapper">
    <select id="getUserByUserName"
            parameterType="String"
            resultType="com.example.mybatis.entity.User">
        select
        id, username, user_email userEmail, user_city userCity, age
        from user
        where username = #{username}
    </select>
    <select id="getUserList"
            resultType="com.example.mybatis.entity.User">
        select
        id, username, user_email userEmail, user_city userCity, age
        from user
    </select>
    <insert id="addUser"
            parameterType="com.example.mybatis.entity.User">
        insert into user
        (username, user_email, user_city, age)
        values (#{username}, #{userEmail}, #{userCity}, #{age})
    </insert>
    <delete id="deleteUser" parameterType="java.lang.Integer">
       delete from user where id = #{id}
    </delete>
    <update id="updateUser" parameterType="com.example.mybatis.entity.User">
       update user
       set username=#{username}, user_email=#{userEmail}, user_city=#{userCity}, age=#{age}
       where id=#{id}
    </update>
</mapper>
  • UserMapper.xml 中 namespace 为接口的全类名

  • UserMapper.xml 中的 id 为接口中对应的方法名

  • UserMapper.xml 中的 parameterType 和接口中对应方法的参数类型一致

  • UserMapper.xml 中的 resultType 和接口中对应方法的返回值类型一致

    第四步,测试。

public class App2 {
    public static void main( String[] args ) {
        // 加载 MyBatis 配置文件
        InputStream is = App2.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        // 获取 SqlSession, 代表和数据库的一次会话, 用完需要关闭
        // SqlSession 和Connection, 都是非线程安全的, 每次使用都应该去获取新的对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 获取实现接口的代理对象
        // UserMapper 并没有实现类, 但是mybatis会为这个接口生成一个代理对象(将接口和xml绑定)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 1. 查询
        User user = userMapper.getUserByUserName("zhangsan");
        System.out.println(user.toString());

        List<User> userList = userMapper.getUserList();
        userList.stream().forEach(obj -> System.out.println(obj.toString()));
        /*-------------------------------------------------------------------*/
        // 2. 新增
        User addUser = new User();
        addUser.setUsername("lzc");
        addUser.setUserEmail("lzc@qq.com");
        addUser.setUserCity("深圳");
        addUser.setAge(18);
        userMapper.addUser(addUser);
        sqlSession.commit(); // 提交事务
        /*-------------------------------------------------------------------*/
        // 3. 删除
        userMapper.deleteUser(1);
        sqlSession.commit(); // 提交事务
        /*-------------------------------------------------------------------*/
        // 4. 修改
        User updateUser = new User();
        updateUser.setId(4);
        updateUser.setUsername("lizhencheng");
        updateUser.setUserEmail("lizhencheng@qq.com");
        updateUser.setUserCity("桂林");
        updateUser.setAge(16);
        userMapper.updateUser(updateUser);
        sqlSession.commit(); // 提交事务
        /*-------------------------------------------------------------------*/
        sqlSession.close();
    }
}

代码链接:https://github.com/923226145/MyBatis-learn...

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!