当前位置: 首页 > news >正文

青海wap网站建设比较好中国域名网官网

青海wap网站建设比较好,中国域名网官网,网站高端定制,汽车网站网页设计mybatis是怎么拿sqlSession 在 上一篇的时候#xff0c;我们的SqlSessionFactoryBuilder已经从xml文件中解析出了Configuration并且返回了sessionFactory。 然后我们要从session;中拿到sqlSession public class DefaultSqlSessionFactory implements SqlSessionFactory {pr…mybatis是怎么拿sqlSession 在 上一篇的时候我们的SqlSessionFactoryBuilder已经从xml文件中解析出了Configuration并且返回了sessionFactory。 然后我们要从session;中拿到sqlSession public class DefaultSqlSessionFactory implements SqlSessionFactory {private final Configuration configuration;Overridepublic SqlSession openSession() {//默认情况下ExecutorType是ExecutorType.SIMPLE类型的return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx null;try {//获取配置的环境信息final Environment environment configuration.getEnvironment();//获取environment中的TransactionFactoryfinal TransactionFactory transactionFactory getTransactionFactoryFromEnvironment(environment);//生成Transactiontx transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//生成Executor重要之后的查询都得靠它final Executor executor configuration.newExecutor(tx, execType);//返回DefaultSqlSessionreturn new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException(Error opening session. Cause: e, e);} finally {ErrorContext.instance().reset();}} }//DefaultSqlSession类的组成其实新建的时候就只是把他的字段赋值而已 public class DefaultSqlSession implements SqlSession {private Configuration configuration;private Executor executor;private boolean autoCommit;private boolean dirty;private ListCursor? cursorList; }public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {this.configuration configuration;this.executor executor;this.dirty false;this.autoCommit autoCommit;}上面分析的是到拿到sqlSession为止重点其实不是在上面这里因为到上面为止其实主要的功能只是将配置的信息解析成我们要的类然后进行初始化赋值。 Mapper的实现原理 下面我们从SqlSession中拿到mapper并执行方法其实才是你感觉到mybatis框架开始帮我们做事的开始。 public static void main(String[] args) {//拿到SqlSessionSqlSession sqlsession MybatisUtil.getSqlsession();//拿mapperTDemoMapper mapper sqlsession.getMapper(TDemoMapper.class);//调用mapper的方法ListTDemo all mapper.getAll();for (TDemo item : all)System.out.println(item);}因为我们在项目中的TDemoMapper只是一个接口并没有实现这个接口方法但是为什么我们在调用这个接口方法的时候就可以得到返回结果呢mybatis究竟做了什么 首先我们回到之前解析Mapper的语句 mapperElement(root.evalNode(mappers));private void mapperElement(XNode parent) throws Exception {if (parent ! null) {for (XNode child : parent.getChildren()) {if (package.equals(child.getName())) {String mapperPackage child.getStringAttribute(name);configuration.addMappers(mapperPackage);} else {String resource child.getStringAttribute(resource);String url child.getStringAttribute(url);String mapperClass child.getStringAttribute(class);if (resource ! null url null mapperClass null) { //根据resource解析ErrorContext.instance().resource(resource);InputStream inputStream Resources.getResourceAsStream(resource);XMLMapperBuilder mapperParser new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());mapperParser.parse();} else if (resource null url ! null mapperClass null) {//根据url 解析ErrorContext.instance().resource(url);InputStream inputStream Resources.getUrlAsStream(url);XMLMapperBuilder mapperParser new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());mapperParser.parse();} else if (resource null url null mapperClass ! null) {//根据mapperClass解析//首先通过mapperClass的路径生成mapperClass的接口类Class? mapperInterface Resources.classForName(mapperClass);//降mapperClass加入到configuration中去configuration.addMapper(mapperInterface);} else {throw new BuilderException(A mapper element may only specify a url, resource or class, but not more than one.);}}}}}//Configuration类下public T void addMapper(ClassT type) {mapperRegistry.addMapper(type);}//MapperRegistry类下 public class MapperRegistry {private final Configuration config;private final MapClass?, MapperProxyFactory? knownMappers new HashMapClass?, MapperProxyFactory?();//最终调用这个方法public T void addMapper(ClassT type) {if (type.isInterface()) {if (hasMapper(type)) {throw new BindingException(Type type is already known to the MapperRegistry.);}boolean loadCompleted false;try {//将接口包装成MapperProxyFactory类放入knownMappers中knownMappers就是存放我们的mapper接口的knownMappers.put(type, new MapperProxyFactoryT(type));// Its important that the type is added before the parser is run// otherwise the binding may automatically be attempted by the// mapper parser. If the type is already known, it wont try.//通过这个builder来解析mapper的statement。把mapper和mapper.xml文件相关联方法名与xml中的id相关联为了之后调用的时候能找到的语句MapperAnnotationBuilder parser new MapperAnnotationBuilder(config, type);//开始解析parser.parse();loadCompleted true;} finally {if (!loadCompleted) {knownMappers.remove(type);}}}} }//MapperAnnotationBuilder类中public void parse() {String resource type.toString();if (!configuration.isResourceLoaded(resource)) {//通过xml文件解析loadXmlResource();configuration.addLoadedResource(resource);assistant.setCurrentNamespace(type.getName());parseCache();parseCacheRef();//获得接口的方法为了获取方法上的注解通过注解的方式来让方法于sql语句相关联Method[] methods type.getMethods();for (Method method : methods) {try {// issue #237if (!method.isBridge()) {//具体的解析过程parseStatement(method);}} catch (IncompleteElementException e) {configuration.addIncompleteMethod(new MethodResolver(this, method));}}}parsePendingMethods();}具体的调用过程就不细跟了无非就是获取节点获取属性值或者是获取方法然后获取注解信息巴拉巴拉……然后设置到configuration中。 上面要注意的点是若既配置xml又配置注解的情况下注解会覆盖xml原因非常简单源码中注解解析在xml解析后面然后覆盖的情况是他们有相同的namespaceid。 然后我们继续我们的主线任务就是mapper的设计架构。从上面我们可以知道configuration中有一个MapperRegistry类型的字段mapperRegistry其中有一个字段叫knownMappersknownMappers里面存着key为接口类型值为MapperProxyFactory的。 //我们在调用TDemoMapper mapper sqlsession.getMapper(TDemoMapper.class);的时候 //先调用DefaultSqlSession类下的Overridepublic T T getMapper(ClassT type) {return configuration.TgetMapper(type, this);} //然后调用Configuration类下的public T T getMapper(ClassT type, SqlSession sqlSession) {return mapperRegistry.getMapper(type, sqlSession);}//最后调用MapperRegistry类下的public T T getMapper(ClassT type, SqlSession sqlSession) {final MapperProxyFactoryT mapperProxyFactory (MapperProxyFactoryT) knownMappers.get(type);if (mapperProxyFactory null) {throw new BindingException(Type type is not known to the MapperRegistry.);}try {//实际生成是这段代码通过mapperProxyFactory来生成实例对象return mapperProxyFactory.newInstance(sqlSession);} catch (Exception e) {throw new BindingException(Error getting mapper instance. Cause: e, e);}}//实际调用类 public class MapperProxyFactoryT {private final ClassT mapperInterface;private final MapMethod, MapperMethod methodCache new ConcurrentHashMapMethod, MapperMethod();public T newInstance(SqlSession sqlSession) {//实例化一个代理类final MapperProxyT mapperProxy new MapperProxyT(sqlSession, mapperInterface, methodCache);//通过这个函数实例化return newInstance(mapperProxy);}protected T newInstance(MapperProxyT mapperProxy) {//动态代理的基本操作说明最终实现方式是动态代理return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);} }public class MapperProxyT implements InvocationHandler, Serializable {private static final long serialVersionUID -6424540398559729838L;private final SqlSession sqlSession;private final ClassT mapperInterface;private final MapMethod, MapperMethod methodCache;public MapperProxy(SqlSession sqlSession, ClassT mapperInterface, MapMethod, MapperMethod methodCache) {this.sqlSession sqlSession;this.mapperInterface mapperInterface;this.methodCache methodCache;}//动态代理中最重要的方法invokeOverridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (Object.class.equals(method.getDeclaringClass())) {//如果是Object中的方法就不走下面的代理了直接执行比如toStringhashCodereturn method.invoke(this, args);} else if (isDefaultMethod(method)) {//如果不是静态方法而且不是抽象方法则不增强方法return invokeDefaultMethod(proxy, method, args);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}//实际我们的mapper接口的方法走的逻辑就是下面这2条final MapperMethod mapperMethod cachedMapperMethod(method);return mapperMethod.execute(sqlSession, args);} }总结 我们通过sqlSession获得mapper方法而sqlSession从configuration中的mapperRegistry中获取MapperProxyFactory对象在通过MapperProxyFactory对象的newInstance方法得到MapperProxy的动态代理实例对象。 我们使用的mapper其实是通过MapperProxy动态代理在运行时候生成的一个新的对象进行方法增强的里面的接口方法都会通过下面2个语句进行数据库的操作以及后续对数据的处理 final MapperMethod mapperMethod cachedMapperMethod(method);return mapperMethod.execute(sqlSession, args);12这两条语句其实包含对访问数据库对象的创建访问数据库到得到数据库返回数据后的处理等内容非常复杂本篇就到此为止。
http://www.sadfv.cn/news/6813/

相关文章:

  • 公众号推广费用一般多少网站优化主要优化哪些地方
  • 网站如何做3d产品网站建设用户登录源码
  • 成都网站建设优化公司电话建设银行 访问的网站出错
  • cpa单页网站怎么做闲置服务器做网站挣钱
  • 网站备案正常多久陕西长城建设工程有限公司网站
  • 大学生就业网站开发源码开发软件大全
  • 怎么做刷会员网站百度竞价被点击软件盯上
  • 亳州做网站凡科送审平台学生端
  • 网站开发需要用到的相关技术电子商务平台名词解释
  • ip反查工具网站世界经理人网站手机版
  • 手机网站设计通用尺寸wordpress 标签前缀
  • 自适应响应式网站源码免费空间申请2021
  • 媒体网站开发网站建设开发员
  • 做网站开发多少钱php是做网站美工的吗
  • 图片外链网站禅城区网站建站网站
  • 购物网站开发的意义算命网站开发
  • 廊坊高端模板建站wordpress 图书 主题
  • 销售渠道建设网站景安网站备案 不去拍照
  • 郑州哪里教做网站培训机构学校
  • 我要建设公司网站湘潭做网站价格优选磐石网络
  • 品牌网站建设推广深圳云购网站制作
  • 用织梦后台修改网站logo安徽省建设厅网站备案
  • 美团网站做疏通广告河源建筑设计企业名录黄页
  • 蓝色网站源码黑客入侵网课
  • 深圳建网建网站广州机械加工
  • wordpress cdn厦门百度快照优化排名
  • 网站开发商品排序逻辑快速搭建展示型网站
  • 网上效果代码网站可以下载吗软文营销的特点
  • 友情网站制作wordpress菜单新窗口打开
  • 崇左市城市投资建设有限公司网站seo站长工具下载