完整代码GitHub地址:https://github.com/Sabot1203/mybatis_design
mybatis在使用代理dao的方式实现访问数据库是主要是创建代理对象,并在对象中调用具体的增删改查方法。
在自定义框架时,用到的知识包括但不限于:工厂模式(Factory 工厂模式)、构造者模式(Builder 模式)、代理模式,反射,自定义注解,注解的反射,xml 解析,数据库元数据,元数据的反射等。
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建 SqlSessionFactory 的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建工厂对象 SqlSessionFactory
SqlSessionFactory factory = builder.build(in);
//4.使用 SqlSessionFactory 生产 SqlSession 对象
SqlSession session = factory.openSession();
//5.使用 SqlSession 创建 dao 接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//6.使用代理对象执行查询所有方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//7.释放资源
session.close();
in.close();
仿照mybatis的实现流程,删去Maven中的mybatis依赖坐标,自己实现流程中需要使用的类。
读取配置文件 --> 使用工厂生产SQLSession --> 使用SqlSession创建代理对象 --> 使用代理对象访问数据库。
这里的核心结构为
以下为一次完整的查询操作流程图:
部分关键代码:
/**
* @param:Class<T> daoInterfaceClass
* @return: T
* @description:用于创建代理对象
*/
public <T> T getMapper(Class<T> daoInterfaceClass) {
//创建代理
return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),coon));
}
/**
* @param:Object proxy, Method method, Object[] args
* @return:
* @description:用于对方法进行增强
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//获取方法名
String methodName = method.getName();
//获取方法所在类名
String className = method.getDeclaringClass().getName();
//组合成key从Map中取出对应的Mapper
String key = className+"."+methodName;
Mapper mapper = mappers.get(key);
if (mapper == null){
throw new IllegalArgumentException("参数有误");
}
//调用工具类执行增删改查方法
return new Executor().selectList(mapper,coon);
}
/**
* @auther:sabot
* @date:2020/04/18
* @description:用于创建数据源的工具类
*/
public class DateSourceUtil {
public static Connection getConnection(Configuration cfg){
try {
Class.forName(cfg.getDriver());
return DriverManager.getConnection(cfg.getUrl(),cfg.getUsername(),cfg.getPassword());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}