本书主要讲解的是MyBatis,所以对Spring的一些技术,例如,IOC (反转控制)和 AOP (面向切面编程),只是点到一些基础和书中需要使用的部分。

  Spring框架已经成为Java世界最为流行的IOC和AOP框架。通过Spring框架我们可 以使用IOC的依赖注入,即插即拔功能;通过AOP框架,数据库事务可以委托给Spring 处理,消除掉很大一部分的事务代码。在目前Java互联网技术中,Spring MVC大行其道, 它配合MyBatis的高度灵活、可配置、可优化SQL等特性,完全可以构建高性能的大型网 站。毫无疑问,MyBatis和Spring两大框架已经成了 Java互联网技术的主流框架组合之一,它们经受住了大数据量和大批量请求的考验,在大型网站系统中得到了大量的应用。使用MyBatis-Spring使得业务层和模型层得到了更好的分离,与此同时在Spring环境中使用 MyBatis也更加简单,节省了不少的代码。我们甚至不需要显式的使用SqlSessionFactory、 SqlSession等对象。因为MyBatis-Spring为我们封装了它们。

  MyBatis提供了和Spring无缝对接的功能,它主要通过mybatis-spring-x.x.x.jar实现。 本书使用的 MyBatis-Spring 版本为 1.2.3。我们可以在网上(http://mvnrepository.com/artifact/ org. mybatis/mybatis-spring) 下载它。

一、Spring的基础知识

  为了更好地讨论MyBatis在Spring项目中的应用,我们先谈谈Spring的基础知识。Spring技术主要由两个基础的功能I0C和A0P构成。MyBatis-Spring项目提供了一些基础 的类,使得Spring能和MyBatis结合起来用,这个项目需要使用mybatis-spring-x.x.x.jar实现。不过在此之前我们先了解一下Spring的一些基础知识,其中包括Spring IOC、Spring AOP 和Spring关于数据库事务的一些知识。

1、Spring IOC 基础

  在Java基础教程中,我们往往使用创建关键字来完成对服务对象的创建。举个例子, 我们有很多的U盘,它们都能够存储计算机的数据,但是它们可能来自不同的品牌,有金士顿(KingstonUSBDisk)的、闪迪(SanUSBDisk)的,或者其他满足 U 盘接口 (USBDisk)规范的。如果我们用new方法,那么就意味着我们的接口只能用于某种特定品牌的U盘。

USBDisk usbDisk = new KingstonUSBDisk ();

  通过上面的操作,USBDisk和KingstonUSBDisk就形成了耦合。换句话说,如果想用闪迪的U盘我需要修改源码才行。如果未来有更先进的U盘,那就要修改源码了,大型系统的资源多达成百上千,如果都采用这样的方式,系统会造成严重的耦合,不利于维护和扩展。

  这个时候IOC理念来了,首先它不是一种技术,而是一种理念。假设我们不釆用new 方法,而是使用一种描述的方式,每一个U盘都有一段自己的描述,通过接口我们可以读 入这些信息,根据这些信息注入对应的U盘,这样我们在维护源码的时候只需要去描述这 些信息并且提供对应的服务即可,不需要去改动源码了。

 

  仍以U盘为例,如果用的是闪迪U盘,那么在信息描述段给出的是闪迪U盘,系统就会根据这个信息去匹配对应的实现类,而无需用new方法去生成实现类。同样,如果用的是金士顿U盘,那么在信息描述段给出的就是金士顿,系统也会自动生成对应的服务注入到我们的系统中,而我们只需要通过描述就能获得资源,无需自己用new方法去创建资源和服务。

 

  从上面的描述可以知道,我们往Spring中注入资源往往是通过描述来实现的,在Spring 中往往是注解或者是XML描述。Spring中的IOC注入方式分为下面这几种。

•构造方法注入。

• setter 注入。

•接口注入。

  构造方法注入是依靠类的构造去实现的,对于一些参数较少的对象可以使用这个方式注入。比如角色类(Trole),它的构造方法中包含三个属性:编号id)、角色名称(roleName) 和备注(note)O我们需要进行如代码清单8.1所示的操作来构建它。

 MyBatis系列八 MyBatis-Spring(上)

 

 

 

  这样我们就描述了一个TRole,它可以注入到其他的资源中。但是如果构造方法多, 显然构造注入不是一个很好的方法,而Spring更加推荐使用setter注入。假设上例角色类 还有一个没有参数的构造方法,它的三个属性,编号id)、角色名称roleName)和备注 note)都有setter方法,那么我们可以使用setter注入,如代码清单8.2所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   使用setter注入更加灵活,因为使用构造方法,会受到构造方法的参数个数、顺序这 些因素干扰。侵入更加少,所以这是Spring首选的注入方式。

  Spring的接口注入方式。它是一种注入其他服务的接口,比如JNDI数据源的注入,在 Tomcat或者其他的服务器中往往配置了 JNDI数据源,那么就可以使用接口注入我们需要 的资源,如代码清单8-3所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   它允许你从一个远程服务中注入一些服务到本地调用O

  上面讨论了注入的几种方式,在大型系统中,我们往往还会使用注解注入的方式来描 述系统服务之间的关系,这也是Spring所推荐的方式。

2、Spring AOP 基础

   Spring IOC相对而言还是比较容易理解的,如果你懂得了第6章的反射技术,就知道它是用反射技术实现的,而Spring AOP就不是了。在MyBatis-Spring技术中,它最大的用 处是事务的控制,这是一个最麻烦也最难理解的东西。

  Spring AOP是通过动态代理来实现的。首先在传统的MVC构架中,业务层一般都夹 带着数据库的事务管理,例如,插入一个角色,它是使用RoleService接口的实现类 RoleServicelmp 1去实现的,如代码清单8・4所示。

 MyBatis系列八 MyBatis-Spring(上)

 

 

   当程序进入到insertRole方法的时候,Spring就会读取配置的传播行为进行设置,这里 的配置为Propagation.REQUIRED,它的意思是当前方法如果有事务则加入当前事务,否则就 创建新的事务。这样这个insertRole方法就在事务内调用了,那么它是怎么实现的呢?

  在传统Spring的书籍中,我们一般会涉及到一些抽象的概念,如切面、连接点、通知、 切入点、目标对象、AOP代理等等极其抽象的概念。

  这些内容论述的时候太过于抽象,所以我们不长篇大论地罗列一些晦涩的概念去讨论 它们,而是使用原理去讨论它们,下面我们通过原理来分析它们执行的过程。

  Spring AOP实际上就是一个动态代理的典范。不熟悉动态代理的读者可以翻阅本书 6章的内容,请务必掌握它们,这是阅读下面分析的基础,否则你读下面的文字便会像 读天书一样。

  现在以角色服务类(RoleServicelmpl)为例。

  首先Spring可以生成代理对象,这样调度insertRole方法的时候就进入了一个invoke 方法里面。Spring会判断到底要不要拦截这个方法,这是一个切入点的配置问题,它是通 过正则式匹配的,比如我们在正则式配置insert*这样的统配,那么Spring就会拦截这个 insertRole。方法,否则就不拦截,直接通过invoke方法反射调用这个方法,就结束了。这 便是切入点的概念,很简单吧。

  其次就是切面。切面是干什么的?它是插入角色的,里面包含事务,而事务就是整个 方法的一个切面,可能你的方法会很复杂,包含业务、财务和日志等多方面,而它们都受 到同一事务管辖,那么事务就是这方法的一个切面。这个时候Spring就会根据我们配置的 信息,知道这个方法需要事务,釆用传播行为Propagation.REQUIRED运行方法,这就是 Spring的切面。

  再次就是连接点。连接点是在程序运行中根据不同的通知来实现的程序段。由于Spring使用动态代理,我们在反射原始的方法之前可以做一些事情,于是有了前置通知(Beforeadvice),也可以在反射之后做一些事情,那便是后置通知(After advice),反射原来的方法可能正确返回,也可能因此抛出异常,所以还有正常返回后通知(After return advice)和产 生异常的抛出异常后通知(After throwing advice)o也有可能需要用自定义方法取代原有的 方法,就如MyBatis的插件一样,不釆用原有的invoke方法而是使用自定义的方法,所以 还有环绕通知(Around advice),怎么样用动态代理的原理来分析是不是比单独讲概念要清 晰得多呢?

  代理目标,就是哪个类的对象被代理了。这里显然就是RoleServicelmpl对象被代理了。

  AOP代理(AOP Proxy)就是指釆用何种方式进行代理,我们知道JDK的代理需要使 用接口,而CGLIB则不需要,因此在默认的情况下Spring釆用这样的规则。当Spring 服务包含接口描述时釆用JDK动态代理,否则采用CGLIB代理。当然你可以通过配置修 改它们。

 

  基于上面的论述,我们清楚了 AOP的大致情况,这些在理解动态代理的基础上是相对 简单的。如图8.1所示,Spring AOP在动态代理下运行的流程。

MyBatis系列八 MyBatis-Spring(上)

 

 

 

  这里执行方法的逻辑有点复杂,笔者另外给图解释它,如图8.2所示。这便是在Spring AOP动态代理下做的判断和运行的流程图,表面上看起来有点复杂,实际在理解了动态代 理后结合Java基础,就可以十分容易地理解它们了,也可以使用代码去实现它们。

 

 3、Spring事务管理

   Spring事务管理是通过Spring AOP去实现的,在8.1.2节中我们讨论了 Spring AOP 执行过程和基础概念,默认的情况下Spring在执行的方法抛出异常后,引发事务回滚,当 然你可以用拦截器或者配置去改变它们,我们这里只讨论默认的情况,不讨论其他复杂的 情况。我们首先讨论一下Spring的隔离级别和传播行为,这是很容易犯错的地方。

 MyBatis系列八 MyBatis-Spring(上)

 

 

 (1)事务隔离级别

 

  数据库和程序一样,也有并发的问题,在同时存在两个或者两个以上的数据库事务环 境中,同一条记录甚至是不同记录都会由于SQL在不同时刻的执行产生不同的结果,甚至 产生错误。于是便有了隔离级别这样的数据库的概念,按照数据库的概念分为脏读、读写 提交、可重复读、序列化4种。我们来讨论一下它们。

 

  脏读是指一个事务能够读取另外一个事务未提交的数据,如表8.1所示。

 

  这里我们发现事务B读取了事务A未提交的数据,而最后事务A将回滚,这是十分危 险的。为了避免这个问题,我们往往使用读写提交的隔离级别,如表8.2所示。

MyBatis系列八 MyBatis-Spring(上)

这里我们用了读写提交完成了这些逻辑,但是读写提交依旧会产生一些问题,让我们 看看这样的场景,如表8.3所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   这里我们看到,对于余额而言,在T4时刻买单失败了。因为在T3时刻老婆提交了消 800元的事务,这时老公可要出洋相了。为了避免这个问题,我们可以使用可重复读的 策略,这样就消除了老公无钱买单的尴尬场景。

但是可重复读是针对于同一条记录而言的,对于不同的记录会发生下面这样的场景, 如表8-4所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   我们看到老婆在查询之后,老公启动了消费,并先于老婆之前打印账单记录,所以在 T4时刻,打印了 1800元11条记录,这个时候老婆就会去质疑这800元是不是幻读的。上 面和不可重复读很接近,但是我们需要注意的是,不可重复读是针对同一条记录,而幻读 是针对删除和插入记录的。

  为了避免服这个问题我们可以釆用序列化的隔离层。序列化就意味着所有的操作都会按顺序执行,不会出现脏读、不可重读和幻读的情况,如表8.5所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   这就是数据库隔离层的情况,上面我们只讨论了在多并发环境下数据安全性的问题,而没有讨论它们之间的性能。一般而言,性能从脏读一读写提交一可重复读一序列化是直 线下降的,更多的时候我们使用读写提交便可以了,也不是所有的数据库支持所有的隔离级别,比如Oracle数据库只支持读写提交和序列化,它的默认隔离级别为读写提交,而 MySQL数据库的默认隔离级别为可重复读。

(2)传播行为

  传播行为,是指方法之间的调用问题。在大部分的情况下,我们认为事务都应该是一 次性全部成功或者全部失败的。例如,业务做成功了,但是财务没有合乎规范,被财务部 否决了,这个时候就需要回滚所有的事务。但是也会有特殊的场景,比如信用卡还款,在 还款过程中,我们有一个总的程序代码,循环调用一个repayCreditCard的还款方法,进行 还款处理,但是我们发现其中的一张卡发生了异常,这时我们不能把所有执行过的信用卡 数据回滚,,而只能回滚出现异常的这张卡。如果将所有执行过还款操作的信用卡回滚, 那么就意味着之前按时还款的用户也被认为是不按时还款的,这显然不合理。换句话说, 我们在做每一张卡操作的时候都希望有一个独立的事务管控它,使得每一张卡的还款互不 干扰。

  在Spring中定义了 7种传播行为,如表8.6所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   我们应该注意自调用的问题,什么是自调用呢?比如说我们的角色服务类有两个方法,分 别是 insertRoleList 方法和 insertRole 方法,而 insertRole 方法注解为 PROPAGATION. REQUIRES_NEW,如代码清单8-5所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

   所谓自调用就是自己的类方法调用其他方法的过程。如insertRoleList调用了 insertRole 方法,而这里注解insertRole为REQUIRES_NEW,每次调用方法的时候,会生成独立事务。 但是请读者务必注意,这实际上是不生效的,为什么呢?

  我们回顾一下之前讲解的Spring AOP的动态代理运行的过程,Spring的数据库事务是在动态代理进入到一个invoke方法里面的,然后判断是否需要拦截方法,需要的时候才根 据注解和配置生成数据库事务切面上下文,而这里的自调用是没有代理对象的,是原始 对象的调用,所以根本就没有invoke方法去解析注解和配置生成数据库切面的上下文, 独立事务也无从谈起,Spring只会延续使用insertRoleList的上下文信息,所以这个注解 是无效的。你需要这样的功能,你只能独立写一个类,再去调用insertRole方法,因为在另外一个类里面,你得到的是RoleServicelmpl的代理类,进入它的invoke方法的时候它 会去解析注解,知道你需要一个独立事务。在使用的时候请读者务必小心这个问题,避 免落入陷阱。

4、Spring MVC 基础

  Spring MVC是当前最为流行的互联网MVC框架,Spring MVC对框架进行了比较简易的封装,各个层级都是比较清晰的。它的核心是DispatcherServlet, Servlet将根据拦截的配置去拦截一些请求,它的作用是做一个转发在它接收了转发后就需要跳转到其他的地方。例如,在web.xml中这样配置Spring MVC,如代码清单8-6所示。

MyBatis系列八 MyBatis-Spring(上)

  这样凡是以.do结尾的请求都会被DispatcherServlet所拦截,它拦截后一般需要进一步 跳转,一般描述跳转的有XML描述或者注解描述,现在更多得使用注解方式,所以让我们这里主要用注解的方式。一旦在Spring MVC项目中为一个类注解了©Controller,那么它就可以是一个跳转的地方,它在MVC框架中起到一个控制器的作用,如代码清单8-7所示。

代码清单 8-7: Spring MVC Controller 的伪代码

@Controller//标识为控制器.
public class RoleController (
  @RequestMapping (n/role/getRolen) //DispatcherServlet 匹配路径时,进入方法 
  @ResponseBody
//标注把结果转化为JSON   public RoleBean getRole (@RequestParam ("id” ) int id) //标注参数对应关系   RoleBean role = this.roleService.getRole(id);   long end = System.currentTimeMillis();
  return role;   } }

  一旦类给了©Controller标注,那么Spring MVC就认为它是一个控制层,而会根据 @RequestMapping所配置的路径跳转到对应的控制器和方法中去。参数的名称和参数的映 射关系靠@RequestParam注解对应,也比较简单。

这个方法只是返回了一个角色对象,它并不会自己变为JSON,因此我们需要处理视图 解析器,那么我们需要配置视图解析器以拦截请求的结果,如代码清单8.8所示。

MyBatis系列八 MyBatis-Spring(上)

  我们加入 @ResponeBody 标注视图解析器 MappingJacksonHttpMessageConverter 就会拦截这个请求,然后把结果转化为JSON数据,返回给视图层。Spring MVC的跳转流程,如图8-3所示。我们真正的开发主要集中在控制器上。Spring MVC还有许多内容,但是本书是以MyBatis为主,就不介绍太多了

MyBatis系列八 MyBatis-Spring(上)

 

 二、MyBatis-Spring 应用

1、概述

  在Spring发布3.0版本的时候是支持iBatis2项目的,MyBatis项目组也想将MyBatis3 版本的支持添加到Spring3.0中,而不幸的事情发生了,在MyBatis3未完成的时候,Spring3.0 就已经开发完成并发布了。Spring团队可不想发布一个基于非发布版的MyBatis的整合支 持,那么Spring官方的支持就不得不继续等待了。在这个时候MyBatis社区自己编写出了 MyBatis-Spring 项目,使得 MyBatis3 能在 Spring 中使用。

  在Spring中,配置的方法较多,可以通过XML进行配置,也可以通过注解配置,但是通过注解配置巳经成为了主流,所以本书主要讲解通过注解配置MyBatis-SpringO配置MyBatis-Spring分为下面几个部分。

  • 配置数据源。
  • 配置 SqlSessionFactory
  • 配置 SqlSessionTemplate。 •
  • 配置 Mapper 。
  • 事务处理。

  在 MyBatis 中要构建 SqlSessionFactory 对象,让它来产生 SqlSession,而在 MyBatis- Spring项目中SqlSession的使用是通过SqlSessionTemplate来实现的,它提供了对SqlSession 操作的封装。所以通过SqlSessionTemplate可以得到Mappero下面让我们开始在Spring 境下配置MyBatis项目。

2、配置 SqISessionFactory

  我们需要构建SqISessionFactory,它的作用是生成SqlSession,所以这节的目的很明确 就是构建 SqISessionFactory。MyBatis-Spring 项目提供了 org.mybatis.spring.SqlSession FactoryBean类给我们去配置。一般而言,我们需要给出两个参数,一个是数据源,另一个 MyBatis的配置文件路径,这样Spring IOC容器就会初始化这个SqISessionFactory Bean, 解析MyBatis配置文件并连同数据源一同保存在Spring Bean里面。让我们看看配置的方法, 如代码清单8.9所示。

MyBatis系列八 MyBatis-Spring(上)

 

 MyBatis系列八 MyBatis-Spring(上)

  首先,配置一个数据源,它只要实现javax.sql.DataSource接口便可以了,所以它可以 是任意第三方的数据源,也可以是通过JNDI从容器中获得的数据源。然后,构建 SqlSessionFactoryBean对象。我们注入一个数据源和配置文件,classpath的写法说明它在.class 目录文件里面。这样Spring在初始化IOC容器的时候去初始化SqlSessionFactoryBean,它通过 解析配置文件得到MyBatis运行所需的上下文。

  由于这里Spring已经帮助我们初始化了数据源,MyBatis的配置文件就无需再配置 关于数据库environments的节点信息了。所以配置文件就可以配置成类似代码清单8-10 样的了。

MyBatis系列八 MyBatis-Spring(上)

 

 

 MyBatis系列八 MyBatis-Spring(上)

  当然我们也可以根据需要去修改配置文件。这样就成功地配置了 SqlSessionFactory, 接着我们需要创建SqlSessionTemplate。

  严格地说,SqlSessionFactoryBean已经可以通过Spring IOC配置了,我们完全可以通 Spring IOC来代替原来的配置,它为我们提供了以下属性。

MyBatis系列八 MyBatis-Spring(上)

  在大部分情况下,我们无需全部配置,只需要配置其中几项便可以了。如果遇到复杂 的配置,笔者建议大家使用MyBatis配置文件,因为它更便于管理,且可读性高。

3、配置 SqlSessionTemplate

  SqlSessionTemplate (org.mybatis.spring.SqlSessionTemplate)是一个模板类,通过调用 SqlSession来完成工作,所以在MyBatis-Spring项目中它是一个核心类。但是在Spring 构建它是件相当容易的事情,它有两种构建方法,一种是只有一个SqlSessionFactory作为 参数的;另外一种是有两个参数的,一个是SqlSessionFactory,另一个是执行器类型,它 是一个枚举类(org.apache.ibatis.session.ExecutorType)o 弄清楚了这些,让我们看看在 Spring 中是如何构建它们的。

  构建方法一,使用SqlSessionFactory参数构建,如代码清单8-11所示。

MyBatis系列八 MyBatis-Spring(上)

  构建方法二,使用两个参数构建,如代码清单8.12所示。

MyBatis系列八 MyBatis-Spring(上)

  这里ExecutorType的取值范围是:SIMPLE、REUSE、BATCH,对应的是我们在第6 章讨论过的三种执行器的类型。当然大部分情况下我们都不这么配置,而是在配置文件中 配置执行器的类型便可。

  通过这些配置就意味着Spring会把我们之前配置的SqlSessionFactory设置到 SqlSessionTemplate 中。如果我们同时设置了 SqlSessionFactory SqlSessionTemplate,那么 系统就只会用使用SqlSessionTemplate去覆盖掉SqlSessionFactory。

  在iBatis时代SqlSessionTemplate可以执行许多功能,同样的在MyBatis中也是可以的。 但是在目前MyBatis的编程中用得不多,因为我们完全可以直接通过映射器擦除它,这样更 易于理解。但是在定制化编程中SqlSessionTemplate是一个很有用的类,尤其是在特殊的场 (比如你需要Spring的编程事务的时候),或在大型Web应用中,它往往应用于DAO, 所以我们将它注入到某个DAO中,自己编写一个公共的DAO基类也是可以的,然后Spring 中通过依赖注入相关的资源来初始化。现在,我们写一个基类,如代码清单8.13所示。

MyBatis系列八 MyBatis-Spring(上)

如果要做一些增删查改用户信息的工作,那么我们就需要一个用户DAO的接口,如代码清单8.14所示。

MyBatis系列八 MyBatis-Spring(上)

  然后,我们给出实现类,如代码清单8.15所示。

MyBatis系列八 MyBatis-Spring(上)

 

 MyBatis系列八 MyBatis-Spring(上)

  方法较为简单,但是要用到它,我们还要先在Spring中配置它,如代码清单8-16所示。

MyBatis系列八 MyBatis-Spring(上)

  这样就在Spring中注入了 SqISessionTemplate到DAO层。我们就可以使用它做我们想 要做的事情,它的作用就等同于SqlSession对象。让我们可以做想要做的事情。

  这和iBatis时代的编程方式是一样的,我们不建议使用这样的编程方式,原因有两个。

    • SqISessionTemplate是MyBatis的类,我们要使用一个id,去标出我们将会调用的那 SQL,这对于编程来说是困难的,有侵入框架之嫌,可读性较低。
    • 我们在编写代码时不能保证id的正确性。因为IDE无法识别id是否正确,需要运 行的时候才能知道。

  因此笔者建议大家釆用Mapper接口的编程方式。

4、配置Mapper

  在代码中,大部分场景都不建议使用SqlSessionTemplate或者SqlSession的方式,这里 我们釆用Mapper接口编程的方式,让SqlSessionTemplate在开发过程中“消”,这样更 符合面向对象的编程,也更利于我们理解。

(1) MapperFactoryBean

  在MyBatis中,Mapper只需要是一个接口,而不是一个实现类,它是由MyBatis体系 通过动态代理的形式生成代理对象去运行的,所以Spring也没有办法为其生成实现类。为 了处理这个问题,MyBatis-Spring团队提供了一个MapperFactoryBean类作为中介,我们可以通过配置它来实现我们想要的Mapper。配置 MapperFactoryBean 3 个参数,mapperinterface、SqlSessionFactory SqlSessionTemplate 。

  • mapperinterface,用来制定接口 ,当我们的接口继承了配置的接口那么MyBatis就认为它是一个Mapper。
  • SqlSessionFactory, SqlSessiomTemplate 属性不被配置的时候,MyBatis-Spring 才会去设置它。
  • SqlSessionTemplate,当它被设置的时候SqlSessionFactroy将被作废,如代码清单 8.17所示。

MyBatis系列八 MyBatis-Spring(上)

  这样我们就可以使用这个接口进行编程了,它的效果等同于sqlSession.getMapper (UserDAO.class)o不过在Spring中,它更为优雅。

(2)MapperScannerConfigurer

  一个复杂的系统存在许许多多的DAO,比如我们往往不单单有UserDAO,还有角色 RoleDAO.产品的ProducDAO,如果需要一个个配置,那么工作量会很大,不过 MyBatis-Spring团队已经处理了这种场景,它釆用自动扫描的形式来配置我们的映射器, 这样我们就可以在很少的代码情况下完成对映射器的配置,大大提高了效率。

在MyBatis-Spring项目中,我们釆用的是MapperScannerConfigurer。我们可以配置这 么几个属性。

  • basePackage,指定让Spring自动扫描什么包,它会逐层深入扫描。
  • annotationClass,表示如果类被这个注解标识的时候,才进行扫描。
  • sqlSessionFactoryBeanName,指定在 Spring 中定义 sqlSessionFactory bean 名称。 如果它被定义,sqlSessionFactory将不起作用。
  • sqlSessionTemplateBeanName,指定在 Spring 中定义 sqlSessionTemplate bean 的名 称。如果它被定义,sqlSessionFactoryBeanName将不起作用。
  • markerinterface,指定是实现了什么接口就认为它是Mapper。我们需要提供一个公 共的接口去标记。在Spring配置前需要给DAO 一个注解,在Spring中往往是使用 注解©Repository表示DAO层的,让我们对UserDAO进行改造,如代码清单8-18 所示。

MyBatis系列八 MyBatis-Spring(上)

  现在我们在Spring中配置它,如代码清单8-19所示。

MyBatis系列八 MyBatis-Spring(上)

 

 MyBatis系列八 MyBatis-Spring(上)

  这样Spring上下文就会自动扫描com.leam.dao从而找到标注了 Repository的接口,自 动生成Mapper,而无需多余的配置,大大方便了我们的运用。

5、配置事务

  MyBatis和Spring结合后是使用Spring AOP去管理事务的,使用Spring AOP是相当简 单的,它分为声明式事务和编程式事务两种。大部分场景下使用声明式事务便可以了。使 用声明式事务更方便,所以目前是主流方向,本书也保持一致,如代码清单8.20所示。

MyBatis系列八 MyBatis-Spring(上)

  这个时候我们往往需要业务层,业务层既是处理业务的地方,又是管理数据库事务的 地方,我们可以使用Spring的注解Service来表示哪个类为业务层的类。同样,我们也可 以通过自动扫描的方法读取Service对象到Spring上下文中,配置如代码清单8-21所示。

MyBatis系列八 MyBatis-Spring(上)

  这样Spring就会自动扫描这些Service对象的bean读取到上下文中。MyBatis的事务就 交由Spring去控制了。我们只需要在Spring中通过注解注入即可,如代码清单8.22所示。

MyBatis系列八 MyBatis-Spring(上)

 

 

 

 

 

 

 

相关文章:

  • 2022-12-23
  • 2021-05-28
  • 2021-09-18
  • 2021-12-28
  • 2021-09-25
  • 2021-11-23
  • 2021-07-20
猜你喜欢
  • 2021-09-20
  • 2022-12-23
  • 2021-08-02
  • 2022-12-23
  • 2021-04-24
  • 2021-11-24
  • 2021-09-19
相关资源
相似解决方案