mybatis的本质和原理

    项目需要,我们需要自己做一套mybatis,或者使用大部分mybatis的原始内容。对其改造,以适应需要。这就要求我再次学习一下mybatis,对它有更深入的了解。

 

是什么
    MyBatis是一个持久层框架,用来处理对象关系映射。说白了就是以相对面向对象的方式来提交sql语句给jdbc。如果想找个简单、快速上手的例子,最好是和spring想结合的。直接用官网的吧,简单清晰也没谁了:

https://mybatis.org/mybatis-3/getting-started.html

 

为什么

    Java开发都是面向对象的思维,如果用传统下面自己去调用连接拼装sql的方式,维护成本高,代码可读性差。

public static void main(String[] args) {
//数据库连接对象
Connection conn = null;
//数据库操作对象
PreparedStatement stmt = null;
//1、加载驱动程序
try {
Class.forName(DBDRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2、连接数据库
//通过连接管理器连接数据库
try {
//在连接的时候直接输入用户名和密码才可以连接
conn = DriverManager.getConnection(DBURL, USERNAME, PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
//3、向数据库中插入一条数据
String sql = "INSERT INTO person(name,age) VALUES (?,?)";
try {
stmt = conn.prepareStatement(sql);
stmt.setString(1,"陈昆仑");
stmt.setInt(2,21);
stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
//4、执行语句
try {
ResultSet resultSet = stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
//5、关闭操作,步骤相反哈~
try {
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

 

怎么做

    我们来看一下底层是怎么处理和交互的。基本流程如下:

mybatis的本质和原理

 

 

    看着头大?没事,我们先从最简化的版本开始添枝加叶。MyBatis可以用配置文件或者注解形式注入sql。因为配置文件方式可以方便的处理动态SQL(动态SQL就是sql语句里有if else for这些的,可以根据参数的变化最终sql也跟着变化)等优点,用的更为普遍。

    假设现在是2000年,Clinton Begin还没有发起ibatis(mybatis的前身)项目。而apache基金会内部发起了讨论要设计这样一个产品,指派你作为项目负责人。现在思考,你的思路是什么?

    一般思路是先把架构搭建起来,做成一个MVP最小可行性版本,然后再做功能增强。

    从功能最简化方面来看,需要两步:第一步要将sql及所需要的元素以对象的形式输入,第二步是获取到这些信息转换成jdbc信息处理。

    这样拆解后的思路是将sql及所需要的元素拆解成类方法的参数形式,方法本身要做的事情就是将这些参数以jdbc编程需要的形式传给jdbc执行。这里方法内部做的事情是一样的,那就自然而然的想到不用每个类都有一个实现。只要定义好接口,把实现用代理或者上层切面的方式统一处理就可以了。

    根据这个思路,首先要用代理来获取参数。我设计使用方式是Insert、Select等注解里写sql元语句。通过方法参数注入参数。最终返回结果。如下

public interface UserMapper { @Insert("INSERT INTO person(name,age) VALUES (#{name},#{age})")
Integer insertUser(User user); }

    要实现接口的解析。先建立一个类,里面构造一个代理类,实现类似于SqlSession,所以起名叫YunaSession(yuna是我给经典java学习场景工程https://github.com/xiexiaojing/yuna 起的名字)

public class YunaSession {
public static Object dealSql(Class clazz) {
Class c[] = new Class[]{clazz};

return Proxy.newProxyInstance(YunaSession.class.getClassLoader(), c,

new YunaInvocationHandler());

}
}

    下面要实现的是代理中YunaInvocationHandler真正要实现的逻辑:将这些参数以jdbc编程需要的形式传给jdbc执行。也就是说把上面【为什么】部分一开始的那段执行jdbc的代码贴进去,将sql和参数的部分做替换。

     我们把关键再贴一遍便于说明问题

//3、向数据库中插入一条数据
String sql = "INSERT INTO person(name,age) VALUES (?,?)";
try {
stmt = conn.prepareStatement(sql);
stmt.setString(1,"陈昆仑");
stmt.setInt(2,21);
stmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwgwfp.html