千家信息网

如何进行Java Mybatis中的Mapper原理分析

发表于:2024-12-05 作者:千家信息网编辑
千家信息网最后更新 2024年12月05日,如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。准备1.pom文件
千家信息网最后更新 2024年12月05日如何进行Java Mybatis中的Mapper原理分析

如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

    准备

    1.pom文件

                                 org.mybatis            mybatis            3.4.5                                    mysql            mysql-connector-java            5.1.6            runtime                                    junit            junit            4.12            test                                    log4j            log4j            1.2.12                            org.projectlombok            lombok            1.18.2            provided            

    2.user类-数据库

    3.实体类

    @Getter@Setter@ToString@NoArgsConstructorpublic class user {    private int id;    private String username;    private String password;}

    4.dao 层

    public interface userDao {    List findAll();}

    5.Mapper 文件

        

    核心配置文件

                                                                                                                                                                                    

    核心代码

    import dao.userDao;import mode.user;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;import java.util.List;public class TestMapper {    public static void main(String[] args) throws IOException {        //加载核心配置文件        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");        //获得sqlSession工厂对象        SqlSessionFactory sqlSessionFactory = new                SqlSessionFactoryBuilder().build(resourceAsStream);        //获得sqlSession对象        SqlSession sqlSession = sqlSessionFactory.openSession();        //执行sql语句        userDao mapper = sqlSession.getMapper(userDao.class);        List userList = mapper.findAll();        //打印结果        System.out.println(userList);        //释放资源        sqlSession.close();    }}

    源码分析

    1.断点

    2.查看源码

    DefaultSqlSession:

    Configuration:

    这是Configuration 类。我们主要看getMapper()方法

    MapperRegistry:

    关键代码:mapperProxyFactory.newInstance(sqlSession);

    MapperProxyFactory:

    返回的是MapperProxy 对象

    MapperProxy:

    源码:

    // Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//package org.apache.ibatis.binding;import java.io.Serializable;import java.lang.invoke.MethodHandles.Lookup;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.util.Map;import org.apache.ibatis.lang.UsesJava7;import org.apache.ibatis.reflection.ExceptionUtil;import org.apache.ibatis.session.SqlSession;public class MapperProxy implements InvocationHandler, Serializable {    private static final long serialVersionUID = -6424540398559729838L;    private final SqlSession sqlSession;    private final Class mapperInterface;    private final Map methodCache;    public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {        this.sqlSession = sqlSession;        this.mapperInterface = mapperInterface;        this.methodCache = methodCache;    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        try {            if (Object.class.equals(method.getDeclaringClass())) {                return method.invoke(this, args);            }            if (this.isDefaultMethod(method)) {                return this.invokeDefaultMethod(proxy, method, args);            }        } catch (Throwable var5) {            throw ExceptionUtil.unwrapThrowable(var5);        }        MapperMethod mapperMethod = this.cachedMapperMethod(method);        return mapperMethod.execute(this.sqlSession, args);    }    private MapperMethod cachedMapperMethod(Method method) {        MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method);        if (mapperMethod == null) {            mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());            this.methodCache.put(method, mapperMethod);        }        return mapperMethod;    }    @UsesJava7    private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {        Constructor constructor = Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);        if (!constructor.isAccessible()) {            constructor.setAccessible(true);        }        Class declaringClass = method.getDeclaringClass();        return ((Lookup)constructor.newInstance(declaringClass, 15)).unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);    }    private boolean isDefaultMethod(Method method) {        return (method.getModifiers() & 1033) == 1 && method.getDeclaringClass().isInterface();    }}

    在invoke方法中可以看到,如果我们调用的是Object中的方法,不做任何处理,直接调用,否则执行:

    mapperMethod.execute(this.sqlSession, args);

    MapperMethod:

    在MapperMethod 中对SQL语句进行分类反射

    • MapperProxyFactory中,使用JDK的动态代理生成Mapper接口的代理代理类

    • 由动态处理器MapperProxy中调用MapperMethod中的方法处理执行SQL

    • 最后,在MapperMethod中根据执行的方法返回值决定调用SqlSession中的对应方法执行SQL

    看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

    0