首页
登录 | 注册

Mybatis的简单模仿实现

通过网上的各种资源,结合自身,模仿出Mybatis的简单实现,下面是主要代码:项目是一个普通Java项目,只要导入数据库的Jar包就行(我使用的是Mysql) 其实也就是底层jdbc的实现,底层查询数据库基本就是通过给一个查询语句,使用原生的jdbc实现来查询出结果,其中主要的五个步骤是:

Mybatis的简单模仿实现

不多说,直接上代码:

项目结构:

Mybatis的简单模仿实现

package com.lyh;

import java.io.Serializable;
import java.util.Date;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 实体类
 * @create 2018-11-02 10:39
 * @since 1.7
 */
public class User implements Serializable{


    private Long id;

    private String userName;

    private String userPassword;

    private Date gmt_create;

    private Date gmt_modified;

    private Integer is_status;


    public Long getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public Date getGmt_create() {
        return gmt_create;
    }

    public void setGmt_create(Date gmt_create) {
        this.gmt_create = gmt_create;
    }

    public Date getGmt_modified() {
        return gmt_modified;
    }

    public void setGmt_modified(Date gmt_modified) {
        this.gmt_modified = gmt_modified;
    }

    public Integer getIs_status() {
        return is_status;
    }

    public void setIs_status(Integer is_status) {
        this.is_status = is_status;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", userPassword='" + userPassword + '\'' +
                ", gmt_create=" + gmt_create +
                ", gmt_modified=" + gmt_modified +
                ", is_status=" + is_status +
                '}';
    }
}
package com.lyh;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 执行器
 * @create 2018-11-02 9:49
 * @since 1.7
 */
public interface MyExecutor {
    <T> T query(String statement);
}
package com.lyh;

import java.lang.reflect.Field;
import java.sql.*;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 执行器的实现
 * @create 2018-11-02 9:51
 * @since 1.7
 */
public class MyBaseExecutor implements MyExecutor {
    private static final String URL = "jdbc:mysql://localhost:3306/springboot";
    private static final String USER = "root";
    private static final String PASS = "";


    @Override
    public <T> T query(String statement) {

        Connection conn =null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(URL,USER,PASS);
            String sql = statement;
            ps = conn.prepareStatement(sql);
            resultSet = ps.executeQuery();

            Class<?> clazz = User.class;
            Object instance = null;
            if (resultSet.next()){
                instance = clazz.newInstance();
                //使用反射进行填充属性
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields){
                    field.setAccessible(true);
                    field.set(instance,resultSet.getObject(field.getName()));
                }
            }
            return (T) instance;
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
package com.lyh;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 对类的描述
 * @create 2018-11-02 13:53
 * @since 1.7
 */
public interface MySqlSession {
    <T> T selectOne(String param);
    <T> T getMapper(Class<T> clazz);
}
package com.lyh;

import java.lang.reflect.Proxy;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 对类的描述
 * @create 2018-11-02 13:56
 * @since 1.7
 */
public class MyDefaultSqlSession implements MySqlSession {

    private MyExecutor myExecutor = new MyBaseExecutor();
    @Override
    public <T> T selectOne(String param) {
        return myExecutor.query(param);
    }

    @Override
    public <T> T getMapper(Class<T> clazz) {
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},new MyMapperProxy(this));
    }
}
package com.lyh;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 对类的描述
 * @create 2018-11-02 11:12
 * @since 1.7
 */
public interface UserMapper {

     // User findUserById(Integer id);
      void insert(User user);
      User findUserById(int id);
}
package com.lyh;

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

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 对类的描述
 * @create 2018-11-02 11:14
 * @since 1.7
 */
public class UserMapperXML {
    //相当于xml的命名空间
    public static final String namespace = "com.lyh.UserMapper";
    //相当于select标签
    private static Map<String, String> methodSqlMap = new HashMap<>();

    static {
        methodSqlMap.put("findUserById", "select * from user where id = %s");
    }
    public static String getMethodSql(String method) {
        return methodSqlMap.get(method);
    }
}
package com.lyh;

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

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 获取mapper,JDK的动态代理
 * @create 2018-11-02 14:01
 * @since 1.7
 */
public class MyMapperProxy implements InvocationHandler{
    private MySqlSession sqlSession;
    public MyMapperProxy(){}
    public MyMapperProxy(MySqlSession sqlSession){
        this.sqlSession = sqlSession;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String mapperClass = method.getDeclaringClass().getName();
        System.out.println("mapperClass"+mapperClass);
        if (UserMapperXML.namespace.equals(mapperClass)){
            String methodName = method.getName();
            String originsql = UserMapperXML.getMethodSql(methodName);
            String formatSql = String.format(originsql,String.valueOf(args[0]));
            return sqlSession.selectOne(formatSql);
        }
        return null;
    }
}
package com.lyh;

/**
 * @author 633805 LYH
 * @version V1.0
 * @description 首先根据命名空间,找出与mapper接口方法名相同的sql语句,然后交给sqlSession来执行。
 * @create 2018-11-02 14:15
 * @since 1.7
 */
public class Test {
    public static void main(String[] args) {
        MySqlSession sqlSession = new MyDefaultSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findUserById(1);
        System.out.println(user);
    }
}

 测试结果:

Mybatis的简单模仿实现

 下面是我的数据库表结构:

Mybatis的简单模仿实现

 

 

 参考:https://www.jianshu.com/p/73ee8caddc68?open_source=weibo_search

 

 

 

 

 

 



2020 jeepxie.net webmaster#jeepxie.net
10 q. 0.009 s.
京ICP备10005923号