如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
准备
1.pom文件
<dependencies> <!--mybatis坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!--mysql驱动坐标--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> <scope>runtime</scope> </dependency> <!--单元测试坐标--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--日志坐标--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <scope>provided</scope> </dependency> </dependencies>
2.user类-数据库
3.实体类
@Getter@Setter@ToString@NoArgsConstructorpublic class user { private int id; private String username; private String password;}
4.dao 层
public interface userDao { List<user> findAll();}
5.Mapper 文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="dao.userDao"> <select id="findAll" resultType="mode.user"> select * from user </select></mapper>
核心配置文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <!--通过properties标签加载外部properties文件--> <properties resource="jdbc.properties"></properties> <!--自定义别名--> <typeAliases> <typeAlias type="mode.user" alias="user"></typeAlias> </typeAliases> <!--数据源环境--> <environments default="developement"> <environment id="developement"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--加载映射文件--> <mappers> <mapper resource="userMapper.xml"></mapper> </mappers></configuration>
核心代码
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<user> 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<T> implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; private final SqlSession sqlSession; private final Class<T> mapperInterface; private final Map<Method, MapperMethod> methodCache; public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> 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<Lookup> 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
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网行业资讯频道,感谢您对编程网的支持。