之前,对于数据映射器的理解不是很懂(即 在mybatis中,通过sqlSession可以直接操作xml中sql语句,也可以新建MAPInterface来操作sql),这几天仔细看了一下,由于基础方面的原因,并不能把全部的设计写出来,只能说个大概,有时间会在看看。
涉及数据映射器(这个名字好像只有在与spring整合才有这个说话,但是感觉这个名字比较形象哈)的几个主要类有SqlSession,DefaultSqlsession,Configuration,MapperProxy,MapperRegistry,需要的知识主要是动态代理。之前我困惑主要是在框架中,全部只有接口和sql配置文件,但是却能够操作数据库,有点不像hibernate,在DAO里面是有session这样涉及事务管理的,mybatis DAO没有,只能操作设定的方法,不能获取事务的。(动态代理可以理解为动态加载+代理模式,如果不懂的话,请参考http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html,这篇博客,下附我自己随便写的简单代码)
( 回到正题,这个东西只能说个大概,请谅解,大神就留下您的理解,方便大家一起提高)
根据源代码,可以知道是以动态加载的形式获取代理对象的(在MapperProxy里面),并且是在此类里面获取代理对象
MapperProxy.java public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (!OBJECT_METHODS.contains(method.getName())) { final Class<?> declaringInterface = findDeclaringInterface(proxy, method);//获取所有需要处理sql的接 final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession);//构造注入 final Object result = mapperMethod.execute(args);//具体返回代理对象 if (result == null && method.getReturnType().isPrimitive() && !method.getReturnType().equals(Void.TYPE)) { throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; } return null; } private Class<?> findDeclaringInterface(Object proxy, Method method) { Class<?> declaringInterface = null; for (Class<?> iface : proxy.getClass().getInterfaces()) { try { Method m = iface.getMethod(method.getName(), method.getParameterTypes()); if (declaringInterface != null) { throw new BindingException("Ambiguous method mapping. Two mapper interfaces contain the identical method signature for " + method); } else if (m != null) { declaringInterface = iface; } } catch (Exception e) { // Intentionally ignore. // This is using exceptions for flow control, // but it's definitely faster. } } if (declaringInterface == null) { throw new BindingException("Could not find interface with the given method " + method); } return declaringInterface; } @SuppressWarnings("unchecked") //mapperInterface为接口,sqlsession为包含配置xml的 public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class<?>[] interfaces = new Class[]{mapperInterface}; MapperProxy proxy = new MapperProxy(sqlSession); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);//获取代理对象 }
调用的MapperMethod,具体相当于注入代理对象的方法实现
//c初始化 public MapperMethod(Class<?> declaringInterface, Method method, SqlSession sqlSession) { paramNames = new ArrayList<String>(); paramPositions = new ArrayList<Integer>(); this.sqlSession = sqlSession; this.method = method; this.config = sqlSession.getConfiguration(); this.hasNamedParameters = false; this.declaringInterface = declaringInterface; setupFields(); setupMethodSignature(); setupCommandType(); validateStatement(); } //具体执行,返回获取能够执行sql的代理对象 public Object execute(Object[] args) { Object result = null; if (SqlCommandType.INSERT == type) { Object param = getParam(args); result = sqlSession.insert(commandName, param); } else if (SqlCommandType.UPDATE == type) { Object param = getParam(args); result = sqlSession.update(commandName, param); } else if (SqlCommandType.DELETE == type) { Object param = getParam(args); result = sqlSession.delete(commandName, param); } else if (SqlCommandType.SELECT == type) { if (returnsVoid && resultHandlerIndex != null) { executeWithResultHandler(args); } else if (returnsList) { result = executeForList(args); } else if (returnsMap) { result = executeForMap(args); } else { Object param = getParam(args); result = sqlSession.selectOne(commandName, param); } } else { throw new BindingException("Unknown execution method for: " + commandName); } return result; }
期间MapperMethod进行匹配(即接口与xml namespace下指定操作),但是为什么可以获取xml文件的配置呢?这时候Configuration这个类就出现了,是可以解析配置文件的内容的,所以可以注入相关的指令和sql语句,在封装好下的底层进行实现,我感觉这就是为什么sqlsession是可以完全控制配置文件里面的所有sql操作的原因,而且这一步是在sqlsssionFactory完成的,但是为什么由sqlsession.getMapper(xxx.class)获取的DAO操作类却只能操作接口定义的类?第一,最简单顾名思义,DAO操作类实现接口而已,而我们自己写的代码确实没有对其进行扩充,其实扩充了,但是没有写在配置文件,还是一回事;第二,在getMapper()里面,我们是以某个接口作为参数的,参考
DefaultSqlSession.class public <T> T getMapper(Class<T> type) { return configuration.getMapper(type, this); } Configuration public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } MapperRegistry public <T> T getMapper(Class<T> type, SqlSession sqlSession) { if (!knownMappers.contains(type)) throw new BindingException("Type " + type + " is not known to the MapperRegistry."); try { return MapperProxy.newMapperProxy(type, sqlSession); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
从上面的代码,我感觉是你单个接口,对吧,首先已经有sqlsession代理对象了,已经能够进行所有操作了,现在是通过getMapper方法获取一个DAO对象,其实还是动态代理的DAO,只不过这次是单个接口,而接口里并没有定义sql操作其他的方法,对吧,所以代理的对象只能进行这些操作了,走的class流程还是跟sqlsession代理对象产生时差不多,或许说在sqlsession里面已经有了所有xml的代理对象,但是我估计底层实现不可行的,因为,得时刻保存在内存里面,还不如构造一个通用的sqlsession,需要去的时候临时把对应的操作方法集合构造代理对象,这样比较科学。这一块我没怎么看明白哈!
以上就是我对mybatis获取SqlSession和DAO操作具体实现的一些简单认识,并且我回继续往下看!
此博客主要用于记录个人学习内容和梳理整体知识,若有许多不明和错误的地方,还请指出,若是其他方面,概不欢迎!
动态代理演示代码
1接口 public interface Name { public void sayHello(String nusername); } 2实现接口类 public class Proxyclass implements Name{ public void sayHello(String username) { // TODO Auto-generated method stub System.out.println(username); } } 3.实现动态代理 public class ProxyName implements InvocationHandler{ private Object proxied; ProxyName(Object proxied){ this.proxied=proxied; } public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { // TODO Auto-generated method stub System.out.println(proxy.getClass().getName()+":"+method+":"+params[0]); System.out.println(method.getName()); return(method.invoke(proxied, params)); } } 4.测试 public class DynamicProxyDemo { public static void main(String args[]) { Proxyclass pro = new Proxyclass(); pro.sayHello("yaoge22"); Name name = (Name) Proxy.newProxyInstance(Name.class.getClassLoader(), new Class[] { Name.class }, new ProxyName(pro)); name.sayHello("hello"); } }
相关推荐
标题中的“mybatis延迟加载样例”意味着我们将探讨如何在MyBatis中实现和使用延迟加载,以及它的具体应用场景。延迟加载是ORM框架的一个重要特性,能够有效防止大数据量的加载导致的内存溢出问题。 描述中提到的...
4. **示例应用**:在实际的MyBatis配置中,你可以这样设置一个懒加载的一对一关联: ```xml <!-- 其他字段映射 --> ``` 然后在Mapper接口中,你可以声明一个返回父对象的方法,父对象中包含一个`Child`...
在Spring Boot应用中集成MyBatis作为持久层框架时,我们常常希望在开发过程中能够实现XML映射文件的热加载,以便在修改了SQL语句后无需重启应用就能看到效果。这种热加载功能能显著提高开发效率。下面将详细介绍如何...
在 Mybatis 中,延迟加载主要应用于关联对象。例如,当我们查询一个用户时,如果不使用延迟加载,那么用户的订单、地址等关联信息会同时被加载,即使我们并不需要这些信息。为了解决这个问题,Mybatis 提供了延迟...
在Spring Boot应用中,MyBatis作为持久层框架,通常会使用XML文件来定义SQL映射。然而,当开发过程中需要频繁修改这些XML文件时,每次改动都需要重启服务才能看到效果,这无疑降低了开发效率。为了解决这个问题,...
在IT行业中,Spring、MVC和MyBatis是构建Java Web应用的常见技术栈。"Spring+mvc+mybatis Mapper xml自动加载"这个主题聚焦于如何在开发过程中优化配置,使得改动Mapper XML文件后,无需重启Tomcat服务器,就可以...
MyBatis懒加载,也称为延迟加载(Lazy Loading),是一种优化技术,主要应用于对象关系映射框架中,如MyBatis。懒加载的核心思想是“按需加载”,即在真正需要数据时才去数据库获取,而不是在初始加载实体对象时就一...
综上所述,这个项目涉及到的IT知识点包括数据库操作的便捷工具Mybatis-Plus,多数据库管理的动态数据源技术,以及Spring框架下的自定义配置、XML解析、注解注入和AOP应用。通过这些技术的整合,可以构建出一个灵活、...
在 MyBatis 中,延迟加载(Lazy Loading)和缓存是两个非常重要的特性,它们对于提升应用程序性能和减少数据库访问有着显著作用。 **延迟加载(Lazy Loading)** 延迟加载是一种设计模式,它在对象被首次请求时才...
MyBatis的动态SQL是基于全面的SQL语句构建器,它使用简单的XML或注解,将接口和Java的POJOs映射成数据库中的记录。MyBatis的动态SQL是基于全面的SQL语句构建器,它使用简单的XML或注解,将接口和Java的POJOs映射成...
这里提到了一个重要的工具类Resources,它是MyBatis提供的,目的是为了方便加载资源文件。 MyBatis的XML配置文件包含了对MyBatis系统的核心设置,这些设置通常包括获取数据库连接实例的数据源(DataSource)配置和...
在开发过程中,为了提高效率,开发者常常需要实现热加载(hot reload)功能,使得修改了MyBatis的相关配置或Mapper文件后,无需重启应用就能立即看到改动的效果。本篇将详细介绍MyBatis热加载配置所需要的关键文件和...
- **XML配置示例**:以下是从类路径资源文件中加载配置文件并构建SqlSessionFactory的示例。 ```java String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources....
设计模式在MyBatis中的应用 MyBatis是一款流行的持久层框架,它提供了许多设计模式来实现灵活、可维护和高效的数据访问机制。在MyBatis中,设计模式被广泛应用于架构设计、核心处理层、接口层等多个方面。下面我们...
掌握MyBatis的基本使用后,你还可以深入学习其高级特性,如延迟加载(Lazy Loading)、动态SQL、缓存机制、MyBatis Generator自动生成代码等。在实际项目中,MyBatis不仅可以用于单表操作,还能处理多表联查、复杂...
在IT行业中,构建高效、可扩展的Web应用是至关重要的,而"spring+springMVC+mybatis+quartz动态定时任务创建"就是一个常见的技术栈,用于实现这样的目标。这个组合充分利用了各组件的优势,提供了强大的后端服务支持...
MyBatis是目前流行的Java持久层框架之一,它支持普通SQL查询、存储过程以及高级映射,能够将Java对象映射到数据库记录中。MyBatis通过简单的XML或注解配置,允许开发者编写SQL语句,将其映射到接口和POJOs(普通Java...
MyBatis的完整配置类提供了所有从XML文件中加载配置信息的选项。 MyBatis不仅通过XML提供配置选项,还允许开发者通过注解的方式来进行映射和配置。这种方式可以将SQL语句和映射规则直接写在接口或者POJO类上,这...
在Mybatis中,延迟加载可以通过配置文件mybatis-config.xml来实现,主要有三种方式:直接加载、侵入式延迟加载和深度延迟加载。 直接加载是指执行完对主加载对象的select语句,马上执行对关联对象的select查询。...
了解并掌握MyBatis中的动态SQL技术对于提高应用性能、增强代码灵活性具有重要意义。 #### 提升应用性能 通过动态SQL,可以有效地减少不必要的数据库交互次数。例如,在构建复杂的多表查询时,可以通过动态添加或...