`
baobeituping
  • 浏览: 1068149 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

mybatis源码学习--spring+mybatis注解方式为什么mybatis的dao接口不需要实现类

 
阅读更多

相信大家在刚开始学习mybatis注解方式,或者spring+mybatis注解方式的时候,一定会有一个疑问,为什么mybatis的dao接口只需要一个接口,不需要实现类,就可以正常使用,笔者最开始的时候也会有这种疑问,当时在网上查了很多资料,也问过公司比较年长的同事,但是并没有得到答案,后来通过自己看mybatis的源码的方式才明白其中道理,接下来我就对大家分享,为什么dao接口不需要实现类的原理,这篇文章的讲解主要分为两部分:

1.mybatis注解方式是怎样通过没有实现类的dao接口进行数据库操作

2.spring+mybatis注解方式是怎样在没有实现类的dao接口的情况下结合的

 

文章的结构是通过  总结+详细讲解  的方式来进行说明的,希望大家能和我一同进步,例子程序放在github上了,mybatis-demo

环境:

mybatis   3.2.7

mybatis-spring 1.2.2

spring  4.1.6

总结:

       1.mybatis注解方式通过没有实现类的dao接口进行数据库操作的原理,一句话概括,就是jdk proxy,就是jdk代理

       2.spring+mybatis注解方式,也是没有实现类的,但是spring会默认返回MapperFactoryBean对象作为实现类的替换,但是这个只是被spring使用的,mybatis本身还是通过jdk代理来运行的。

 

详细讲解:

     1.mybatis注解方式是怎样通过没有实现类的dao接口进行数据库操作

 

[java] view plain copy
 
 
  1. /** 
  2.  *  
  3.  * 类UserMapper.java的实现描述:TODO 类实现描述  
  4.  * @author yuezhihua 2015年7月9日 上午11:18:30 
  5.  */  
  6. public interface UserMapper {  
  7.       
  8.       
  9.     /** 
  10.      * 根据用户id查询用户角色 
  11.      * @param userId 
  12.      * @return 
  13.      */  
  14.     @Select("select * from role_main a INNER JOIN user_role b ON a.id = b.role_id WHERE b.user_id=#{userId}")  
  15.     public List<RolePO> getRolesByUserId(@Param("userId")Integer userId);  
  16.       
  17.       
  18.     /** 
  19.      * 根据用户id查询用户角色名 
  20.      * @param userId 
  21.      * @return 
  22.      */  
  23.     @Select("select a.role_name from role_main a INNER JOIN user_role b ON a.id = b.role_id WHERE b.user_id=#{userId}")  
  24.     public Set<String> getRoleNamesByUserId(@Param("userId")Integer userId);  
  25.       
  26.       
  27.     /** 
  28.      * 根据userid查询用户的所有权限 
  29.      * @param userId 
  30.      * @return 
  31.      */  
  32.     @Select("SELECT a.permission_name FROM permission_main a INNER JOIN role_permission b ON a.id=b.permission_id WHERE b.role_id IN (SELECT d.role_id from user_main c INNER JOIN user_role d ON c.id = d.user_id WHERE c.id=#{userId})")  
  33.     public Set<String> getPermissionsByUserId(@Param("userId")Integer userId);  
  34.       
  35.     /** 
  36.      * 通过用户名查询用户信息 
  37.      * @param username 
  38.      * @return 
  39.      */  
  40.     @Select("select * from user_main where username=#{username}")  
  41.     @Results({  
  42.           @Result(property = "roleNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getRoleNamesByUserId")),  
  43.           @Result(property = "permissionNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getPermissionsByUserId"))  
  44.       })  
  45.     public UserPO getUserByUsername(@Param("username")String username);  
  46.       
  47.       
  48.     @Select("select username from user_main")  
  49.     public List<String> getRoleMain();  
  50.   
  51. }  

 

 

 

测试用例:

 

[java] view plain copy
 
 
  1. /** 
  2.  *  
  3.  * 类SqlTemplateTest.java的实现描述:TODO 类实现描述  
  4.  * @author yuezhihua 2015年7月29日 下午2:07:44 
  5.  */  
  6. @RunWith(SpringJUnit4ClassRunner.class)  
  7. @ContextConfiguration(locations = {  
  8.         "classpath*:spring/demo-locator.xml"  
  9. })  
  10. public class SqlTemplateTest {  
  11.       
  12.     @Autowired  
  13.     private SqlSessionTemplate sqlSessionTemplate;  
  14.       
  15.     @Autowired  
  16.     private SqlSessionFactory sqlSessionFactory;  
  17.       
  18.     /** 
  19.      * 初始化datasource 
  20.      */  
  21.     @Before  
  22.     public void init(){  
  23.         DataSource ds = null;  
  24.         try {  
  25.             ds = BaseDataTest.createUnpooledDataSource(BaseDataTest.DERBY_PROPERTIES);  
  26.             BaseDataTest.runScript(ds, "com/mybatis/demo/databases/lazyloader/lazyloader-schema.sql");  
  27.             BaseDataTest.runScript(ds, "com/mybatis/demo/databases/lazyloader/lazyloader-dataload.sql");  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         } catch (SQLException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34.       
  35.       
  36.     /** 
  37.      * 测试mybatis自身的查询 
  38.      */  
  39.     @Test  
  40.     public void testMybatisSelect(){  
  41.         SqlSession session = sqlSessionFactory.openSession();  
  42.         UserMapper mapper = session.getMapper(UserMapper.class);  
  43.         UserPO userPo = mapper.getUserByUsername("zhangsan");  
  44.         System.out.println("-----testMybatisSelect:"+userPo.getUsername());  
  45.     }  
  46.       
  47.       
  48.       
  49.     /** 
  50.      * mybatis-spring : sqlSessionTemplate测试查询 
  51.      * java.lang.UnsupportedOperationException: Manual close is not allowed over a Spring managed SqlSession不要在意 
  52.      */  
  53.     @Test  
  54.     public void testSelect(){  
  55.         UserPO  result = sqlSessionTemplate.selectOne("com.mybatis.demo.lazyload.mapper.UserMapper.getUserByUsername""zhangsan");  
  56.         System.out.println(result);  
  57.     }  
  58.       
  59.   
  60. }  


笔者这里不是纯使用mybatis,而是使用mybatis+spring,讲解第一部分的时候,我还是会用带有spring的方式来给大家讲解,大家注重看原理就好

 

第一部分的时候会用到测试用例;testMybatisSelect

大家可以看到,测试用例里边获取dao接口的方法时session.getMapper(UserMapper.class);那咱们就看看sqlsession是怎么样获取usermapper接口的,返回的这个usermaper接口又有什么改变

获取usermapper接口代理对象的时序图

 

 

返回的Usermapper编程了jdk代理对象,org.apache.ibatis.binding.MapperProxy@7e276594

虽然这里打印信息显示貌似mapperproxy是usermapper的实现类,但是笔者认为,mapperproxy不能算是usermapper的实现类,因为笔者觉得实现类的概念是应该实现usermapper接口的,但是mapperproxy不是,mapperproxy只是usermapper执行方法之前的一个拦截器

所以session.getMapper(UserMapper.class)返回的其实是usermapper的代理对象,而且usermapper中定义的方法执行都是通过mapperproxy的invoke方法代理执行的,

接下来我们看看mapper.getUserByUsername("zhangsan");这行代码的执行过程,通过usermapper一个方法的执行来讲解mybatis是怎么通过dao接口执行数据库操作的

mapperproxy.invoke(相当于一个拦截器):

 

[java] view plain copy
 
 
  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  2.     if (Object.class.equals(method.getDeclaringClass())) {  
  3.       try {  
  4.         return method.invoke(this, args);  
  5.       } catch (Throwable t) {  
  6.         throw ExceptionUtil.unwrapThrowable(t);  
  7.       }  
  8.     }  
  9.     final MapperMethod mapperMethod = cachedMapperMethod(method);  
  10.     return mapperMethod.execute(sqlSession, args);  
  11.   }  


这个方法中,首先会过滤object中的通用方法,遇到object方法会直接执行

 

但是如果是非通用方法,就会调用mappermethod.execute来代理执行方法,

mappermethod.execute

 

[java] view plain copy
 
 
  1. public Object execute(SqlSession sqlSession, Object[] args) {  
  2.     Object result;  
  3.     if (SqlCommandType.INSERT == command.getType()) {  
  4.       Object param = method.convertArgsToSqlCommandParam(args);  
  5.       result = rowCountResult(sqlSession.insert(command.getName(), param));  
  6.     } else if (SqlCommandType.UPDATE == command.getType()) {  
  7.       Object param = method.convertArgsToSqlCommandParam(args);  
  8.       result = rowCountResult(sqlSession.update(command.getName(), param));  
  9.     } else if (SqlCommandType.DELETE == command.getType()) {  
  10.       Object param = method.convertArgsToSqlCommandParam(args);  
  11.       result = rowCountResult(sqlSession.delete(command.getName(), param));  
  12.     } else if (SqlCommandType.SELECT == command.getType()) {  
  13.       if (method.returnsVoid() && method.hasResultHandler()) {  
  14.         executeWithResultHandler(sqlSession, args);  
  15.         result = null;  
  16.       } else if (method.returnsMany()) {  
  17.         result = executeForMany(sqlSession, args);  
  18.       } else if (method.returnsMap()) {  
  19.         result = executeForMap(sqlSession, args);  
  20.       } else {  
  21.         Object param = method.convertArgsToSqlCommandParam(args);  
  22.         result = sqlSession.selectOne(command.getName(), param);  
  23.       }  
  24.     } else {  
  25.       throw new BindingException("Unknown execution method for: " + command.getName());  
  26.     }  
  27.     if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {  
  28.       throw new BindingException("Mapper method '" + command.getName()   
  29.           + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");  
  30.     }  
  31.     return result;  
  32.   }  


这个execute方法会根据不同的注解@select,@update,@delete,@insert来分配不同的执行sql环境,进行操作数据库,其实这四个操作可以分为两类,一类是更新类型,返回更新的行数;一类是查询类型,返回查询的结果,这两部分的内部原理我会在其他的文章中进行详细解释。

 

所以,可以总结说,mybatis执行jdk代理的dao接口方法,跳转到mappermethod,execute方法来执行具体的数据库操作,并且返回结果;而且通过jdk代理的方法返回的代理对象,让人感觉和原接口对象一样,造成使用没有实现类的接口来执行的感觉

 

 

第二部分:

spring+mybatis注解方式是怎样在没有实现类的dao接口的情况下结合的

咱们先看一下spring是怎么管理mybatis的dao接口的吧。

我画了一个流程图

 

配置文件扫描所有mybatis的dao接口:

 

[html] view plain copy
 
 
  1. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
  2.         <property name="basePackage" value="com.mybatis.demo.*.mapper" />  
  3.         <!-- 这里要用传beanName,不能传bean的ref,否则,会提前加载,用不到PropertyPlaceholder,切记 -->  
  4.         <property name="sqlSessionFactoryBeanName" value="demo_sqlSessionFactory" />  
  5.     </bean>  



 

ClasspathMapperScanner.doScan

 

[java] view plain copy
 
 
  1. /** 
  2.    * Calls the parent search that will search and register all the candidates. 
  3.    * Then the registered objects are post processed to set them as 
  4.    * MapperFactoryBeans 
  5.    */  
  6.   @Override  
  7.   public Set<BeanDefinitionHolder> doScan(String... basePackages) {  
  8.     Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);  
  9.   
  10.     if (beanDefinitions.isEmpty()) {  
  11.       logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");  
  12.     } else {  
  13.       for (BeanDefinitionHolder holder : beanDefinitions) {  
  14.         GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();  
  15.   
  16.         if (logger.isDebugEnabled()) {  
  17.           logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()   
  18.               + "' and '" + definition.getBeanClassName() + "' mapperInterface");  
  19.         }  
  20.   
  21.         // the mapper interface is the original class of the bean  
  22.         // but, the actual class of the bean is MapperFactoryBean  
  23.         <span style="color:#ff6666;">definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());  
  24.         definition.setBeanClass(MapperFactoryBean.class);</span>  
  25.   
  26.         definition.getPropertyValues().add("addToConfig"this.addToConfig);  
  27.   
  28.         boolean explicitFactoryUsed = false;  
  29.         if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {  
  30.           definition.getPropertyValues().add("sqlSessionFactory"new RuntimeBeanReference(this.sqlSessionFactoryBeanName));  
  31.           explicitFactoryUsed = true;  
  32.         } else if (this.sqlSessionFactory != null) {  
  33.           definition.getPropertyValues().add("sqlSessionFactory"this.sqlSessionFactory);  
  34.           explicitFactoryUsed = true;  
  35.         }  
  36.   
  37.         if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {  
  38.           if (explicitFactoryUsed) {  
  39.             logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");  
  40.           }  
  41.           definition.getPropertyValues().add("sqlSessionTemplate"new RuntimeBeanReference(this.sqlSessionTemplateBeanName));  
  42.           explicitFactoryUsed = true;  
  43.         } else if (this.sqlSessionTemplate != null) {  
  44.           if (explicitFactoryUsed) {  
  45.             logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");  
  46.           }  
  47.           definition.getPropertyValues().add("sqlSessionTemplate"this.sqlSessionTemplate);  
  48.           explicitFactoryUsed = true;  
  49.         }  
  50.   
  51.         if (!explicitFactoryUsed) {  
  52.           if (logger.isDebugEnabled()) {  
  53.             logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");  
  54.           }  
  55.           definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);  
  56.         }  
  57.       }  
  58.     }  
  59.   
  60.     return beanDefinitions;  
  61.   }  


大家注意看红色部分,红色部分的意思就是对于mybatis的dao接口,spring是以MapperFactoryBean的方式来管理的,举个例子说

 

@autowired

private UserMapper userMapper;

这个userMapper返回的实例对象会是MapperFactoryBean,这个过程是由spring控制的,因为笔者对于spring原理没有深入研究过,笔者在这里不做说明。

可能大家好奇,为什么这里不能直接像第一部分一样,通过sqlsession.getMapper(...)的方式来获取dao接口对象呢,笔者在这里觉得,之所以出现MapperFactoryBean

这个中间对象,是因为SqlSessionTemplate,sqlsessionTemplate是mybatis-spring封装的用于方法执行mybatis方法的工具类,但是大家平时可能很少用到这个,

笔者在这里做了一个小测试利用,简单的看一下它的用法:

 

[java] view plain copy
 
 
  1. /** 
  2.  *  
  3.  * 类SqlTemplateTest.java的实现描述:TODO 类实现描述  
  4.  * @author yuezhihua 2015年7月29日 下午2:07:44 
  5.  */  
  6. @RunWith(SpringJUnit4ClassRunner.class)  
  7. @ContextConfiguration(locations = {  
  8.         "classpath*:spring/demo-locator.xml"  
  9. })  
  10. public class SqlTemplateTest {  
  11.       
  12.     @Autowired  
  13.     private SqlSessionTemplate sqlSessionTemplate;  
  14.       
  15.     @Autowired  
  16.     private SqlSessionFactory sqlSessionFactory;  
  17.       
  18.     /** 
  19.      * 初始化datasource 
  20.      */  
  21.     @Before  
  22.     public void init(){  
  23.         DataSource ds = null;  
  24.         try {  
  25.             ds = BaseDataTest.createUnpooledDataSource(BaseDataTest.DERBY_PROPERTIES);  
  26.             BaseDataTest.runScript(ds, "com/mybatis/demo/databases/lazyloader/lazyloader-schema.sql");  
  27.             BaseDataTest.runScript(ds, "com/mybatis/demo/databases/lazyloader/lazyloader-dataload.sql");  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         } catch (SQLException e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34.       
  35.       
  36.     /** 
  37.      * 测试mybatis自身的查询 
  38.      */  
  39.     @Test  
  40.     public void testMybatisSelect(){  
  41.         SqlSession session = sqlSessionFactory.openSession();  
  42.         UserMapper mapper = session.getMapper(UserMapper.class);  
  43.         System.out.println("jdk proxy mapper : "+mapper);  
  44.         UserPO userPo = mapper.getUserByUsername("zhangsan");  
  45.         System.out.println("-----testMybatisSelect:"+userPo.getUsername());  
  46.     }  
  47.       
  48.       
  49.       
  50.     /** 
  51.      * mybatis-spring : sqlSessionTemplate测试查询 
  52.      * java.lang.UnsupportedOperationException: Manual close is not allowed over a Spring managed SqlSession不要在意 
  53.      */  
  54.     @Test  
  55.     public void testSelect(){  
  56.         UserPO  result = sqlSessionTemplate.selectOne("com.mybatis.demo.lazyload.mapper.UserMapper.getUserByUsername""zhangsan");  
  57.         System.out.println(result);  
  58.     }  
  59.       
  60.   
  61. }  


大家看上面testSelect这个测试用例,可以看到sqlsessiontemplate的基本使用方法

 

 

spring+mybatis注解方式获取dao接口对象的方法;:

MapperFactoryBean.getObject

 

[java] view plain copy
 
 
  1. /** 
  2.    * {@inheritDoc} 
  3.    */  
  4.   public T getObject() throws Exception {  
  5.     return getSqlSession().getMapper(this.mapperInterface);  
  6.   }  


这里边的getSqlSession其实就是sqlsessiontemplate

 

 

总结:对于第一部分可以说是返回了mybatis的dao接口的jdk代理对象,通过mapperproxy这个类似于拦截器一样的类跳转执行sql的,可以说是原生dao接口的一层代理对象;

那么对于第二部分来说,确实有三层代理对象:

 

所以,咱们在spring中使用

 

@autowired

private UserMapper userMapper;

来注入对象的时候,其实是经历了 cglib --> mapperfactorybean  --> sqlsessiontemplate  --> mapperproxy  -->  原生dao接口  的包装过程,才获取的

 

所以咱们在使用spring来调用没有实现类的mybatis的dao接口的时候,并不是像看起来那么简单,而是经过多层代理包装的一个代理对象,对方法的执行也跳转到mybatis框架中的mappermethod中了

分享到:
评论

相关推荐

    mybatis-spring-1.3.1.jar下载

    4. **注入Mapper**:在需要使用Mapper的地方,可以直接通过@Autowired注解注入对应的Mapper接口,Spring会自动提供实现。 5. **事务管理**:在Service层,使用@Transactional注解开启事务,MyBatis-Spring会自动...

    mybatis-spring-1.3.3.jar官方下载

    这样,我们可以在 Spring 环境中通过 DAO 接口直接调用 SQL 方法,而无需关心实现细节。 5. **Transaction Management**:MyBatis-Spring 提供了与 Spring 事务管理的无缝集成,可以使用 Spring 的声明式事务管理来...

    MyBatis整合Spring中间件jar包 mybatis-spring-1.3.0.jar

    此时,无需编写任何实现类,Spring会自动为`UserMapper`生成一个实现了该接口的代理类,并将其注入到需要的地方。 此外,MyBatis-Spring还支持将Mapper接口的方法直接作为`@Autowired`注解的目标,这样就可以在...

    spring-mybatis-spring-1.3.2.tar.gz

    3. DAO实现:Spring将自动创建Mapper接口的代理对象,通过@Autowired注解注入到Service层,调用Mapper接口的方法执行SQL。 四、SpringMVC与Spring整合 1. DispatcherServlet配置:在web.xml中配置DispatcherServlet...

    SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程

    6. **实体类和DAO接口**:定义业务对象实体类,以及与Mybatis接口进行交互的DAO接口。 7. **Service层**:实现业务逻辑,通过@Autowired注入DAO接口,调用数据库操作。 8. **Controller层**:处理HTTP请求,调用...

    mybatis-spring-1.0.0.rar

    - 在 DAO 类中注入 Mapper 接口,Spring 自动创建代理实现。 - 在 Service 层中注入 DAO 实例,调用 DAO 方法进行数据库操作。 4. **版本差异**: `mybatis-spring-1.0.0` 是早期版本,可能不包含某些新特性或...

    mybatis-spring-1.3.2.zip

    在实际应用中,`mybatis-spring-1.3.2.jar` 文件作为依赖被引入后,开发人员可以编写基于 MyBatis 的 DAO 层接口,这些接口将由 MyBatis-Spring 自动实现并注入到 Spring 容器中。这样,Service 层可以通过依赖注入...

    mybatis-spring-1.2.0.rar

    7. **注解支持**:除了 XML 映射文件,MyBatis-Spring 还支持在 Service 或 DAO 类中直接使用注解进行 SQL 映射,提高开发效率。 在"mybatis-spring-1.2.0"压缩包中,可能包含以下内容: - **jar 文件**:mybatis-...

    mybatis-spring-1.3.2.jar

    MyBatis-Spring 是一个将 MyBatis ORM 框架与 Spring 框架集成的库,它的主要目标是简化在 Spring 应用中使用 MyBatis 的过程,实现数据访问层(DAO)的无缝集成。这个 `mybatis-spring-1.3.2.jar` 文件就是该集成库...

    mybatis-3.2.2-src.rar 源码

    2. **XML配置与注解**:Mybatis 使用XML或注解的方式定义SQL映射文件,这些文件包含了SQL语句及其参数绑定、结果映射等信息。开发者可以灵活地编写复杂的SQL,同时避免了大量DAO层的代码。 3. **动态SQL**:Mybatis...

    《spring+mybatis 企业应用实战》源码、类库全资料

    通过学习和实践这个实战项目,你可以深入了解Spring和MyBatis如何协同工作,如何设计和实现一个完整的业务流程,以及如何处理异常和事务。同时,这也将帮助你理解企业级应用的架构设计,提升你在实际开发中的技能和...

    mybatis-spring-1.2.0-bundle.zip

    通过 @Mapper 注解,可以直接将一个接口声明为 MyBatis 的 Mapper,Spring 会自动创建其实例并注入到其他组件中。 4. **MapperScannerConfigurer**:这个类允许开发者扫描指定包下的 Mapper 接口,自动注册为 ...

    SSM框架-详细整合教程(Spring+SpringMVC+MyBatis).pdf

    - 实现Service接口,使用@Autowired注解注入需要的DAO或Mapper。 10. **控制器层** - 创建SpringMVC的Controller类,定义处理HTTP请求的方法,注入Service,调用业务逻辑。 11. **视图层** - 创建JSP或其他视图...

    struts2+spring+mybatis+easyui的实现

    在集成这四个组件时,首先我们需要在pom.xml文件中添加相应的依赖,然后创建项目的目录结构,包括src/main/resources下的配置文件(如struts.xml、spring-context.xml、mybatis-config.xml等),以及src/main/webapp...

    Mybatis-Spring-1.2.2中文文档.zip

    Mybatis-Spring是一个将流行的Mybatis持久层框架与Spring框架集成的库,它使得在Spring应用中使用Mybatis变得更加方便。这个1.2.2版本的中文文档为开发者提供了详细的指南,帮助理解如何有效地整合这两个强大的框架...

    mybatis-spring-1.3.1

    Spring与MyBatis的整合能够实现数据访问层(DAO)的解耦,使得业务逻辑层与数据访问层之间的交互更为透明。通过Spring的管理,我们可以方便地实现DAO的事务控制、生命周期管理以及依赖注入,从而提升代码的可测试性...

    mybatis-3.2.6 mybatis-spring-1.2.2

    1. **添加依赖**:在项目中,需要将MyBatis和mybatis-spring的相应版本JAR包加入到类路径下。在现代的Maven或Gradle项目中,这意味着在pom.xml或build.gradle文件中添加对应的依赖项。 2. **配置MyBatis**:创建...

    mybatis-spring-1.0.1-bundle.zip

    4. @Autowired 和 @MapperScan:这两个注解是 MyBatis-Spring 提供的,@Autowired 可以自动装配 SqlSessionTemplate 或 SqlSessionFactory,@MapperScan 用于标记扫描Mapper接口的包路径。 5. 事务管理:MyBatis-...

    spring-boot-starter-mybatis-spring-boot-2.1.2.zip

    `spring-boot-starter-mybatis`是Spring Boot为MyBatis提供的一站式解决方案,它包含MyBatis核心库、MyBatis-Spring以及相关的依赖,使得开发者无需手动管理这些依赖,只需简单配置即可实现MyBatis的集成。...

    spring-mybatis-spring-1.1.1.zip

    9. **测试**:编写JUnit测试类,验证整合是否成功,确认可以通过Spring容器获取到Mapper接口实例,并能正常执行SQL。 在"spring-mybatis-spring-1.1.1.zip"资源包中,可能包含了完整的示例代码、配置文件以及相关的...

Global site tag (gtag.js) - Google Analytics