浅入mybatis(2)(手写简单的mybatis)

浅入mybatis(1)中 我们已经完整的配置了mybatis过程。可以实现通过简单的xml文件就实现了数据库的增删改查,那么神奇之处

在哪里呢?这一章我们简单的实现下mybatis的实现原理,不足之处 敬请谅解  

首先我个人手写的一个流程图如下 (我们可以先敲代码  再反过来看这个图)

浅入mybatis(2)(手写简单的mybatis)

 我写的demo流程如下:

一:建立User实体类

二:按照流程图所示 创建userMapperXml 将id和 sql存起来(这里将xml写成java文件 其实原始的也是将xml文件解析为map  id作为key sql作为value的方式存储起来的 这里就不做详细介绍)

三:mapper接口  改接口对应我们xml对应的id的方法

四:创建自己的sqlSession工厂  这里使用动态代理  将我们所有的mapper传进来 但是我们用代理类去完成所有的操作

(这里体现动态代理的优越性)

五:建立数据库的连接 并使用sqlSession 的工厂类对象实现数据库的增删查找

完整的demo目录结构如下:

浅入mybatis(2)(手写简单的mybatis)

1.user 类:

package com.mybatis.handWriteMybatis;

public class User {
  private int id;
  private String name;
  private Integer age;

  public int getId() {
    return id;
  }

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

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }
}

2.xml文件的代替类(我们模拟将id 和class存入map中)

package com.mybatis.handWriteMybatis;

import java.util.HashMap;
import java.util.Map;

public class UserMapperXml {

  // 类xml的命名空间

  public static final String namespate = "com.mybatis.handWriteMybatis.UserMapper";

  public static final Map<String, String> map = new HashMap<String, String>();

  static {
    // 模拟xml中的id与sql语句 实际中是xml文件 被解析之后放入map中  通过id去找那个对应的sql
    map.put("getUserById", "select * from user where id = ?");
  }
}

3 操作数据库接口类

package com.mybatis.handWriteMybatis;

public interface UserMapper {

  public User getUserById(int id);
}
 
4.这里是重点 创建自己的sqlsession
package com.mybatis.handWriteMybatis;

import java.lang.reflect.Proxy;

public class Sqlsession {
  private ExcutorImp excutorImp = new ExcutorImp();

//查询数据库操作
  public <T> T selectOne(String statement, Object parameter) {
    return excutorImp.query(statement, parameter);
  }

//用动态代理完成传入的Mapper接口要完成的操作
  public <T> T getMapper(Class<T> tClass) {
    return (T)
        Proxy.newProxyInstance(
            tClass.getClassLoader(), new Class[] {tClass}, new MyMapperHandler<T>(this));
  }
}

代理类MyMapperHandler如下:

package com.mybatis.handWriteMybatis;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyMapperHandler<T> implements InvocationHandler {

  Sqlsession sqlsession = null;

  public MyMapperHandler(Sqlsession sqlsession) {
    this.sqlsession = sqlsession;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("运行invoke方法");
    System.out.println(method.getDeclaringClass().getName());
    System.out.println("args " + args[0]);
    if (method.getDeclaringClass().getName().equals(UserMapperXml.namespate)) {
      String sql = UserMapperXml.map.get(method.getName());
      System.out.println(sql);
      return sqlsession.selectOne(sql, String.valueOf(args[0]));
    }
    return null;
  }
}

5.建立连接 进行测试

<1>增删查找的总接口

package com.mybatis.handWriteMybatis;

public interface ConnectionExcutor {

  public <T> T query(String statement, Object parament);
}
<2>数据库的连接以及实现上面接口的操作
package com.mybatis.handWriteMybatis;

import org.junit.Test;

import java.sql.*;

public class ExcutorImp implements ConnectionExcutor {

  @Override
  public <T> T query(String statement, Object parament) {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    connection = getConnection();
    try {
      PreparedStatement pre = connection.prepareStatement(statement);
      String str = (String) parament;
      pre.setInt(1, Integer.parseInt(str));
      ResultSet set = pre.executeQuery();
      User user = new User();
      while (set.next()) {
        user.setName(set.getString(2));
      }
      return (T) user;
    } catch (SQLException e) {
      e.printStackTrace();
    }
    return null;
  }

  private static Connection getConnection() {
    String driver = "com.mysql.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/generator?characterEncoding=UTF-8";
    String username = "root";
    String password = "123456";
    try {
      Class.forName(driver);
      Connection connection = DriverManager.getConnection(url, username, password);
      System.out.println("连接成功");
      return connection;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @Test
  public void testCon() {
    Connection connection = ExcutorImp.getConnection();
    System.out.println(connection);
  }
}

 测试代码:

package com.mybatis.handWriteMybatis;

public class TestMybatis {

  public static void main(String[] args) {

    Sqlsession sqlsession = new Sqlsession();
    UserMapper mapper = sqlsession.getMapper(UserMapper.class);
    User userById = mapper.getUserById(6);
    System.out.println(userById.getName());
  }
}

 

测试结果如下:

浅入mybatis(2)(手写简单的mybatis)

以上就是简单的实现mybatis的实现  其中最主要的还是动态代理的设计思想。