MyBatis入门(一)MyBatis介绍和入门案例

目录

一.MyBatis介绍

1.什么是框架?

2.什么是ORM框架?

3.什么是MyBatis?

二.MyBatis入门案例

1.环境搭建

2.创建持久层接口和映射文件

3.测试持久层接口方法

4.MyBatis核心对象及工作流程

5.使用SqlSession操作数据库

6.Mapper动态代理原理


一.MyBatis介绍

1.什么是框架?

框架即一个半成品软件。开发者从头开发一个软件需要花费大量精力,于是有一些项目组开发出半成品软件,开发者在这些软件的基 础上进行开发,这样的软件就称之为框架。
如果将开发完成的软件比作是一套已经装修完毕的新房,框架就好比是一套已经修建好的毛坯房。用户直接购买毛坯房,保证建筑质 量和户型合理的同时可以进行风格的自由装修。
使用框架开发的好处:
  • 省去大量的代码编写、减少开发时间、降低开发难度。
  • 限制程序员必须使用框架规范开发,增强代码的规范性,降低程序员之间沟通及日后维护的 成本。
  • 将程序员的注意力从技术中抽离出来,更集中在业务层面。
使用框架就好比和世界上最优秀的软件工程师共同完成一个项目,并且他们完成的还是基础、全局的工作。

2.什么是ORM框架?

ORM Object Relationl Mapping ),对象关系映射,即在数据库和对象之间作映射处理。
之前我们使用 JDBC 操作数据库,必须手动进行数据库和对象间的数据转换。

 如下代码:

// 新增方法,将对象转为sql语句字段
public void AddUser(User user) throwsException {
    Class.forName("com.mysql.jdbc.Driver");
    Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306     /mybatis?characterEncoding=utf8","root", "root");
    String sql = "INSERT INTO user values(null,?,?,?,?)"; 
    PreparedStatement preparedStatement =connection.prepareStatement(sql);
    preparedStatement.setString(1,user.getName());
    preparedStatement.setInt(2,user.getAge());
    preparedStatement.setString(3,user.getAddress());
    preparedStatement.setString(4,user.getSex());
    preparedStatement.executeUpdate();
    // 省略资源关闭...
}

 // 查询方法,将数据库结果集转为对象
 public List<User> findAllUser() throws Exception {
    Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306      /mybatis?characterEncoding=utf-8", "root", "root");
    PreparedStatement preparedStatement =connection.prepareStatement("select * from
    user");
    ResultSet resultSet =preparedStatement.executeQuery();

    //遍历查询结果集
    List<User> users = new ArrayList<>();
    while(resultSet.next()){
        // 拿到每一列数据
        int id = resultSet.getInt("id");
        String name =resultSet.getString("name");
        int age = resultSet.getInt("age");
        String address =resultSet.getString("address");
        String sex =resultSet.getString("sex");
        // 将数据封装到对象中
        User user = new User();
        user.setId(id);
        user.setName(name);
        user.setAge(age);
        user.setAddress(address);
        user.setSex(sex);
        users.add(user);
   }
   // 省略资源关闭...
   return users; 
}
这段代码中,数据库数据与对象数据的转换代码繁琐、无技术含量。而使用 ORM 框架代替 JDBC 后,框架可以帮助程序员自动进行转 换,只要像平时一样操作对象, ORM 框架就会根据映射完成对数据 库的操作,极大的增强了开发效率。

3.什么是MyBatis?

MyBatis 是一个 半自动的ORM框架 ,其本质是对 JDBC 的封装。使用MyBatis 不需要写 JDBC 代码,但需要程序员编写 SQL 语句。之前是 apache 的一个开源项目 iBatis 2010 年改名为 MyBatis

补充:
Hibernate 也是一款持久层 ORM 框架,多年前的市场占有率很高,但近年来市场占有率越来越低。
MyBatis Hibernate 的比较:
  • MyBatis是一个半自动的ORM框架,需要手写SQL语句。
  • Hibernate是一个全自动的ORM框架,不需要手写SQL语句。
  • 使用MyBatis的开发量要大于Hibernate
为什么 Hibernate 市场占有率越来越低:
  • 对于新手学习Hibernate时间成本比MyBatis大很多,MyBatis上手很快。
  • Hibernate不需要写SQL语句是因为框架来生成SQL语句。对于复杂查询,开发者很难控制生 成的SQL语句,这就导致SQL调优很难进行。
  • 之前的项目功能简单,数据量小,所以使用Hibernate可以快速完成开发。而近年来项目的 数据量越来越大,而互联网项目对查询速度要求也很高,这就要求我们一定要精细化的调整 SQL语句。此时灵活性更强,手动编写SQL语句的MyBatis慢慢代替了Hibernate使用。
  • 在高并发、大数据、高性能、高响应的互联网项目中,MyBatis是首选的持久框架。而对于对性能要求不高的比如内部管理系统等可以使用Hibernate

二.MyBatis入门案例

1.环境搭建

1
(1)将SQL文件导入数据库
打开Navicat,右键locahost,新建数据库,

双击mybatis数据库,使其连接,然后右键-->运行SQL文件,选择已有的数据库sql文件导入

可以看见导入成功!右键刷新之后可以看见导入的表。

2
(2)创建maven工程,引入依赖 

创建一个空项目

再在此空项目下创建一个不设置Archetype的maven项目,

在 mybatisDemo1工程中的pom.xml文件中配置依赖<dependencies>如下:

<?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>org.example</groupId>
    <artifactId>mybatisDemo1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--必须引入的包-->
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</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>

</project>
(3)创建mybatis核心配置文件SqlMapConfig.xml

主要配置如何连接数据库

放在mybatisDemo1的src/main/resources中

如果"http://mybatis.org/dtd/mybatis-3-config.dtd"url地址报红色,那么就如下解决:

File-->Setting-->搜索DTD,找到Schemas and DTDs,点击加号,将路径添加到其中即可。

SqlMapConfig.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="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:///mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
(4)将log4j.properties文件放入src/main/resources中,让控制台打印SQL句。

log4j.properties文件内容:

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
#log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%d{MM/dd HH:mm:ss}] %-6r [%15.15t] %-5p %30.30c %x - %m\n
5
(5)创建实体类  

 User.java:

package com.first.pojo;

public class User {
    private int id;
    private String username;
    private String sex;
    private String address;

    public User() {
    }

    public User(int id, String username, String sex, String address) {
        this.id = id;
        this.username = username;
        this.sex = sex;
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    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;
    }

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

项目结构:

2.创建持久层接口和映射文件

项目结构:

1
(1)在 java 目录创建持久层 接口
package com.first.mapper;

import com.first.pojo.User;

import java.util.List;

public interface UserMapper {
    //每一个方法对应一个sql语句
    //接口函数由映射文件实现
    List<User> findAll();
}
(2)在 resource目录创建UserMapper的 映射文件,注意目录要和对应接口一致,也是com/first/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>后:

<?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设置映射的文件-->
<mapper namespace="com.first.mapper.UserMapper">
<!--
    id是方法名;
    resultType表示结果的对象,即列表的泛型;
    查找用select标签 -->
    <select id="findAll" resultType="com.first.pojo.User">
        select * from user
    </select>
</mapper>

(3)将映射文件配置到mybatis核心配置文件SqlMapConfig.xml中 ,因为项目启动时,先加载核心配置文件SqlMapConfig.xml,只有注册到核心配置文件SqlMapConfig.xml中的配置文件才可以加载到。

在SqlMapConfig.xml的<configuration>标签中添加如下代码注册映射文件

<!--    注册映射文件-->
    <mappers>
        <mapper resource="com/first/mapper/UserMapper.xml"></mapper>
    </mappers>
映射文件注意事项:
  • 映射文件要和接口名称相同。
  • 映射文件要和接口的目录结构相同。
  • 映射文件中namespace属性要写接口的全名。
  • 映射文件中标签的id属性是接口方法的方法名。
  • 映射文件中标签的resultType属性是接口方法的返回值类型。
  • 映射文件中标签的parameterType属性是接口方法的参数类型。
  • 映射文件中resultTypeparameterType属性要写全类名,如果是集合类型,则写其泛型的全类名。

3.测试持久层接口方法

如第二节配置之后,mybatis自己就利用代理对象帮我们实现了接口方法,所以接下来直接测试就行了!

package com.first.mapper;

import com.first.pojo.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 org.junit.Test;


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

public class TestUserMapper {
    @Test
    public void testFinaAll() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象获取代理代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //(6)代理对象执行方法
        List<User> all=userMapper.findAll();

        //(7)释放资源
        session.close();
        is.close();
    }
}

点击左侧绿色按钮开始测试:

遇到一个异常:

Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration
java.io.IOException: Could not find resource com/first/mapper/UserMapper.xml

找了找发现我之前测试类命名错误了(命名成UserMapper),所以我修改了名称为TestUserMapper,但是idea自动帮我把UserMapper.xml里的UserMapper也改成了TestUserMapper,但是发现还是不行,于是参考了下面的文章解决了bug!

解决mybatis中:Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration_水巷石子的博客-CSDN博客

运行结果:

4.MyBatis核心对象及工作流程

MyBatis 核心对象
SqlSessionFactoryBuilder
SqlSession 工厂构建者对象,使用构造者模式创建 SqlSession 工厂对象。
SqlSessionFactory
SqlSession 工厂,使用工厂模式创建 SqlSession 对象。
SqlSession
该对象可以操作数据库,也可以使用动态代理模式创建持久层接口的代理对象操作数据库。
Mapper
持久层接口的代理对象,他具体实现了持久层接口,用来操作数据库。

MyBatis 工作流程
1
  1. 创建SqlSessionFactoryBuilder对象
  2. SqlSessionFactoryBuilder对象构建了SqlSessionFactory对象:构造者模式
  3. SqlSessionFactory对象生产了SqlSession对象:工厂模式
  4. SqlSession对象创建了持久层接口的代理对象:动态代理模式
  5. 代理对象操作数据库

5.使用SqlSession操作数据库

除了代理对象能够操作数据库, SqlSession 也能操作数据库。只是这种方式在开发中使用的较少(了解即可),接下来我们使用 SqlSession 操作数 据库:
在TestUserMapper中添加一个测试函数testFinaAll2(),如下:
package com.first.mapper;

import com.first.mapper.UserMapper;
import com.first.pojo.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 org.junit.Test;


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

public class TestUserMapper {
    @Test
    public void testFinaAll() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象获取代理代理对象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //(6)代理对象执行方法
        List<User> all=userMapper.findAll();
        all.forEach(System.out::println);

        //(7)释放资源
        session.close();
        is.close();
    }
    @Test
    public void testFinaAll2() throws Exception{
        //(1)读取核心配置文件
        InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
        //(2)创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //(3)SqlSessionFactoryBuilder对象获取SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(is);
        //(4)SqlSessionFactory对象获取SqlSession对象
        SqlSession session = factory.openSession();
        //(5)SqlSession对象直接操作数据库
        //参数是持久层接口全类名+方法名
        List<User> users=session.selectList("com.first.mapper.UserMapper.findAll");
        users.forEach(System.out::println);

        //(6)释放资源
        session.close();
        is.close();
    }
}

输出和上节一样。

6.Mapper动态代理原理

接下来我们通过源码,了解 MyBatis Mapper 对象究竟是怎么生成的,他又是如何代理接口的方法。
获取代理对象
点开测试类的 getMapper 方法,查看该方法最终调用了什么方法。
当看到 Proxy.newProxyInstance 时,可以确定 getMapper 方法最终调用的是 JDK动态代理方法,且使用 MapperProxy 类定义代理方式
查看代理方式
点开 MapperProxy 类,查看 invoke 方法,查看代理对象是如何工作 的。

 

可以看到, MapperProxy 调用了 MapperMethod execute 方法定义了代理方式,且底层调用的是 SqlSession 的方法,根据映射文件 标签不同调用不同的 SqlSession 方法。
结论:
  • SqlSessiongetMapper方法,最终是调用的是JDK动态代理方法,生成一个代理对象,类型就是传入的接口类型。
  • MapperProxy对象通过调用MapperMethodexecute方法定义了代理方式,该方法的底层调用的是SqlSession的方法。

 

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深海鱼肝油ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值