MyBatis原理总结(手写实现类)

我们在实际开发中,越简单越好,所以都是采用不写Dao实现类的方式。不管是使用xml还是直接配置。

但是MyBatis是支持写Dao实现类的

注意sqlSession是这里面的一个灵魂,有很多执行api

目录结构:

方法:

/**
 * 用户的持久层接口
 */
public interface IUserDao {
    List<User> findAll();
}

实现类:

public class UserDaoImpl implements IUserDao {

    private SqlSessionFactory factory;
    //覆盖掉默认构造函数,这样就有了工厂,可以进一步创建对象
    public UserDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }
    @Override
    public List<User> findAll() {
        //1.使用工厂创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //2.使用sqlSession执行查询所有方法(此处需要的参数:(String statement)从配置文件中获取) namespace + id
        List<User> userList = sqlSession.selectList("com.toov5.dao.IUserDao.findAll");
        //使用完后关闭掉
        sqlSession.close();
        return userList;
    }
}

实体类:

public class User implements Serializable {
  private Integer id;
  private String username;
  private Date birthday;
  private String sex;
  private String 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;
    }

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

全局配置文件:

<?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">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(也叫连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
    <mappers>
        <!--resource目录下 对应要创建相应的包 -->
        <mapper resource="com/toov5/dao/IUserDao.xml"/>
    </mappers>
</configuration>

映射文件:

<?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.toov5.dao.IUserDao">
<!--查询所有-->
<select id="findAll" resultType="com.toov5.entity.User">
        select * from  user;
    </select>
</mapper>

测试类:

/**
 * MyBatis测试类
 */
public class MyBatisTest {
    public static void main(String[] args) throws IOException {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2. 创建SqlSessonFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //如何解析,如何封装已经底层帮助实现了。细节封装了。
        SqlSessionFactory factory = builder.build(in);
       // SqlSessionFactory 是个接口,需要找实现。这个工厂是用来创建对象的,创建过程省略了
        //3. 使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //不需要代理类了,SqlSession 是有查询方法的.使用工厂创建Dao对象,传入工厂
        IUserDao userDao = new UserDaoImpl(factory);
        //5.使用代理对象执行方法
        List<User> userList = userDao.findAll();
        userList.stream().forEach(
                user ->{
                    System.out.println(user);
                }
        );
        //6.释放资源
        in.close();
    }
}

Mybatis在用动态代理dao方式时候,也是找到对应的sql语句的。

执行结果,一模一样。

引申



补充,对于绝对路径和相对路径,绝对路径不准确,采用相对路径。

相对路径有两种方案可以获得。 1. 类加载器,只能读取类路径的配置文件     2. 使用ServletContext对象的getRealPath()

创建工厂,采用了构建这模式。隐藏了创建细节。使用户直接调用方法就可以拿到对象了

使用工厂模式生产SqlSession。降低类间的依赖,解耦合。

创建dao接口实现类使用了代理模式。不修改源码基础上对已有的方法增强。

MyBatis原理分析:

MyBatis在使用代理Dao的方式实现增删改查时候,做的什么事呢?

两件事:

一: 创建对象

二: 在代理对象中调用selectList

从一开始就需要解析配置文件,

进而做如下操作:

1. 根据配置文件的信息创建Connection对象,注册驱动,获取连接

2. 获取愈合粗粒对象PreparedStatement,此时需要SQL语句。 com.prepareStatement(sql)

3. 执行查询 ResultSet resultSet = preparedStatement.executeQuery();

4.遍历结果用于封装

List<E> list = new ArrayList();

while(resultSet.next()){

E element = xxx;   // 可以通过反射后去 class.forName("配置的全限定类名").newInstance();   使用反射封装

//  进行封装。把每个rs的内容都添加到element中,把element加入到list中

list.add(element);

}

于是我们就可以把表的列名看成是实体类的属性名称,就可以使用反射的方式来根据名称获取每个属性。

5.返回结果

综上所述: 需要提供方法两个信息

1. 连接信息

2. 映射信息,包含两部分:  执行的sql语句; 封装结果的实体类全限定类名。这两个信息作为属性定义对象。

     String  key  : nameSpace+id

     Mapper value :  String的sql语句    方法的全类名

通过方法:

session.getMapper(IUserDao.class) 实现了代理对象的创建

根据dao接口的字节码创建到的代理对象

public <T> getMapper(Class<T> daoInterfaceClass){

}

使用的的参数是 : 类加载器(与被代理对象使用相同的类加载器), Class数组:代理对象要实现接口的字节码数组, 如何代理(Handler)

Proxy.newProxyInstance()

此方法的封装:

s1.类加载器: 它使用的和被代理对象是相同的类加载器

s2.代理对象要实现的接口: 和被代理对象实现相同的接口

s3.如何代理: 它就是增强的方法,我们需要自己来提供

此处是一个InvocationHandler的接口,我们需要写一个该接口的实现类

调用该类的selectList方法

自定义MyBatis能通过入门案例看到的类:

class Resources

class SqlSessionFactoryBuilder

interface SqlSessionFactory

此时的pom:

<?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.test</groupId>
    <artifactId>mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--<dependency>-->
            <!--<groupId>org.mybatis</groupId>-->
            <!--<artifactId>mybatis</artifactId>-->
            <!--<version>3.4.5</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

构建者构建工厂,工厂生产SqlSession。SqlSession可以做的事情很多。

总结:读取配置文件io流,解析出我们要的信息,交给构建者,构建者使用工具类,构建了工厂对象,工厂的openSession方法提供了sqlSession对象,sqlSession去干活。

原文地址:https://www.cnblogs.com/toov5/p/11186569.html

时间: 2024-10-12 15:53:55

MyBatis原理总结(手写实现类)的相关文章

了解mybatis源码手写mybatis

一:mybatis概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录. 二:手写mybatis 实现思路:: 1创建SqlSessionFactory实例 2:实例化过程中,加载配置

(二)springMvc原理和手写springMvc框架

我们从两个方面了解springmvc执行原理,首先我们去熟悉springmvc执行的过程,然后知道原理后通过手写springmvc去深入了解代码中执行过程. (一)SpringMVC流程图 (二)SpringMVC流程 1.  用户发送请求至前端控制器DispatcherServlet. 2.  DispatcherServlet收到请求调用HandlerMapping处理器映射器. 3.  处理器映射器找到具体的处理器(可以根据xml配置.注解进行查找),生成处理器对象及处理器拦截器(如果有则

理解数据库连接池底层原理之手写实现

第一,数据库连接池中存放的就是数据库操作管道,不仅仅是存放,而且应该是管理这些管道: 第二,应该提供外部配置文件去初始化数据库连接池: 第三,如果一个数据库操作管道已经被占用,那么其他请求是否应该得到这个管道,也就是说我们要考虑多线程并发下,管道的分配问题: 第四,如果做到管道的复用?放回池子中,标示可用,并不是真正的关闭管道: IMyPool是一个接口,对外提供数据库连接池的基本服务,比如得到一个数据库操作管道. MyDefaultPool是IMyPool的实现. MyPooledConnec

手写分数类

struct Frac { ll u, v; Frac() : u(0), v(1) {} Frac(ll x) : u(x), v(1) {} Frac(ll _u, ll _v) { if (!_v) throw; ll g = gcd(abs(_u),abs(_v)); _u /= g, _v /= g; if (_v<0) _u = -_u; u = _u, v = _v; } Frac &operator = (int x) { u = x, v = 1; return *this

mybatis的基本配置:实体类、配置文件、映射文件、工具类 、mapper接口

搭建项目 一:lib(关于框架的jar包和数据库驱动的jar包) 1,第一步:先把mybatis的核心类库放进lib里 2,第二步:导入第三方类库(在lib里).mybatis的核心类库在运行时还依赖一些第三方类库 3,第三步:导入连接数据库驱动jar包 二:创建mybatis的配置文件 1,第一步:先创建实体包,对照着表结构把实体类写出来.封装好就是写get,set方法------不像hibernate,可以自动的将表名字段名与实体类相对应,不用自己手写实体类与映射文件 2,第二步:创建xml

手写数字识别的k-近邻算法实现

(本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的kNN实现.测试. kNN算法原理 kNN算法是一种分类算法,即如何判定一组输入数据属于哪一类别的算法.kNN属于监督学习算法,必须给定训练样本,样本包括输入样本和输出样本.而无监督学习则不需要训练样本. 那么最简单的分类方法就是将输入数据与样本一一比对,并将相似性最强的前k个样本选出,这k个样本中的

手写MyBatis,纯手工打造开源框架(第四篇:决胜千里)- 第272篇

说明 MyBatis版本:3.5.1 相关历史文章(阅读本文之前,您可能需要先看下之前的系列) Spring Boot MyBatis最全教程:你值得拥有MyBatis能脱离Spring吗一图纵览MyBatis的工作原理从源码看MyBatis,竟如此简单MyBatis的Mapper是什么`垃圾` 手写MyBatis,纯手工打造开源框架(第一篇:风云再起) 手写MyBatis,纯手工打造开源框架(第二篇:君临天下) 手写MyBatis,纯手工打造开源框架(第三篇:运筹帷幄) 前言        运

手写Mybatis,彻底搞懂框架原理

mybatis的前身是iBatis,其源于"Internet"和"abatis"的组合,是一款优秀的持久层框架,它支持定制化SQL.存储过程以及高级映射.mybatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集,它可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJO映射成数据库中的记录. Mybatis的架构设计Mybatis的功能架构分为三层: 接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库.接口层接

手写MyBatis ORM框架实践

一.实现手写Mybatis三个难点 1.接口既然不能被实例化?那么我们是怎么实现能够调用的? 2.参数如何和sql绑定 3.返回结果 下面是Mybatis接口 二.Demo实现 1.创建Maven工程(开发工具Eclipse) 下一步 下一步 然后点击“完成” 2.配置pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema