手写mybatis(适合初学者)

近期学习了如何手写简易的mybatis,网上的博客的代码多多少少有些问题,运行不起来,本篇博文保证你百分百能运行和理解mybaits。
首先我觉得这张图用来理解mybatis很易懂。
手写mybatis(适合初学者)_第1张图片
然后是本次demo的流程图
手写mybatis(适合初学者)_第2张图片
demo运行环境
IntelliJ IDEA,jdk1.8,mysql
运行代码步骤
1.创建user数据库(主键id,name属性)
2.修改SimpleExcutor中JDBC的URL和用户名和密码
然后从我的github (git clone)下来这个项目就可以运行了。
代码分析
首先看流程图,我们从执行器入手。
Excutor接口

public interface Excutor {
    public  T query(String statement,Object parameter);
}

然后用SimpleExcutor实现它

public class SimpleExcutor implements Excutor{

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

    private Connection getConnection(){
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://120.78.149.145:3306/springbootdb?useUnicode=true&characterEncoding=utf8&useSSL=false";
        String username = "root";
        String password = "cui8135130";
        try{
            Class.forName(driver);
            Connection connection = DriverManager.getConnection(url,username,password);
            System.out.println("连接成功");
            return connection;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

这样一来数据源的连接我们就做好了。
然后创建实体类:

public class User {
    private String name;

    public String getName(){
        return name;
    }

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

创建mybaits的dao层接口和映射文件(这里用Java文件模拟)

UserMapper接口

public interface UserMapper {
    public User getUserById(String id);
}

UserMapperXml(映射文件)


public class UserMapperXml {
    //类xml的命名空间
    public static final String namespate = "com.example.writemybaits.service.UserMapper";

    public static final Map map = new HashMap();

    static{
        //模拟xml中的id与sql语句
        map.put("getUserById","select * from user where id = ?");
    }
}

接下来是核心内容了
动态代理实现sqlsession的装配
手写mybatis(适合初学者)_第3张图片
首先我们看看sqlsession的代码

public class Sqlsession {
    private Excutor excutor = new SimpleExcutor();

    public  T selectOne(String statement,Object parameter){
        return excutor.query(statement,parameter);
    }

    public  T getMapper(Class tClass){
        return (T) Proxy.newProxyInstance(tClass.getClassLoader(),new Class[]{tClass},new MyMapperHandler<>(this));
    }
}

有三部分组成
1>创建一个执行器
2>调用执行器查询
3>通过动态代理来dao层接口和映射文件的装配查询。
(关于动态代理可以看我的这篇博文https://blog.csdn.net/Jet_Green/article/details/81198691)

MyMapperHandler

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

最后写一个测试类测试下就行
TestMybatis

public class TestMybatis {
    public static void main(String [] args){
        Sqlsession sqlsession = new Sqlsession();
        UserMapper mapper = sqlsession.getMapper(UserMapper.class);
        User userById = mapper.getUserById("1");
        System.out.println(userById.getName());
    }
}

运行结果:

运行invoke方法
com.example.writemybaits.service.UserMapper
args 1
select * from user where id = ?
连接成功
jack

根据代码和我输出的变量和流程图理解mybaits原理基本上应该不难吧
最后附上源码

https://github.com/jet0605/-mybatis

你可能感兴趣的:(Java,spring)