1. 程式人生 > >淺入mybatis(2)(手寫簡單的mybatis)

淺入mybatis(2)(手寫簡單的mybatis)

淺入mybatis(1)中 我們已經完整的配置了mybatis過程。可以實現通過簡單的xml檔案就實現了資料庫的增刪改查,那麼神奇之處

在哪裡呢?這一章我們簡單的實現下mybatis的實現原理,不足之處 敬請諒解  

首先我個人手寫的一個流程圖如下 (我們可以先敲程式碼  再反過來看這個圖)

 我寫的demo流程如下:

一:建立User實體類

二:按照流程圖所示 建立userMapperXml 將id和 sql存起來(這裡將xml寫成java檔案 其實原始的也是將xml檔案解析為map  id作為key sql作為value的方式儲存起來的 這裡就不做詳細介紹)

三:mapper介面  改介面對應我們xml對應的id的方法

四:建立自己的sqlSession工廠  這裡使用動態代理  將我們所有的mapper傳進來 但是我們用代理類去完成所有的操作

(這裡體現動態代理的優越性)

五:建立資料庫的連線 並使用sqlSession 的工廠類物件實現資料庫的增刪查詢

完整的demo目錄結構如下:

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的實現  其中最主要的還是動態代理的設計思想。