SpringMvc+Spring+Mybatis整合
SSM框架整合介绍
SSM是Spring、SpringMvc、MyBatis 这3个框架的简称,是目前最为流行的项目架构。
其中spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
SpringMVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。
MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
SpringMvc 和 MyBatis 其实是两个独立的框架,它们之间没有直接联系,但是 由于 Spring 框架提供了 IOC 的对象管理,切面编程、良好的ORM封装等非常实用的功能,如果把MyBatis 的对象的创建和维护交给Spring 容器进行管理,不仅能大大增强系统的灵活性,还能扩展功能,简化配置,提高性能、减少工作量,所以 SSM 框架整合其实就是分别实现 Spring 与 SpringMvc 、Spring与 MyBatis的整合,而实现整合的主要工作就是把 MyBatis的对象配置到Spring 容器中,交给 Spring 来管理即可,而SpringMvc 天生与Spring无缝集成
基本结构图如下:
简单过程:
当控制器接收到请求后,会调用 Service 层来实现业务,如果需要访问数据库,Service 层则会调用 Dao 层来操作数据库,而 Dao层 则需要使用 SqlSessionFactory 提供的 SqlSession 来实现具体操作,Session最终通过Connection 来实现增删改查等操作,有时为了提高性能,也会从连接池管理的数据源(DataSource)中获取Connection。对于图中,Controller,Service,Dao 的对象的创建和维护都被加入了Spring容器中,SqlSession由SqlSessionFactory创建并管理,所以只要把SqlSessionFactory加入Spring 容器中。Connection由DataSource创建并管理,所以把DataSource加入Spring容器中即可
SSM框架整合步骤
(1)添加三个框架相关的 jar 文件,并创建相关的配置文件
(2)为MyBatis 配置数据源对象
(3)配置数据源和SqlSessionFactory 对象
(4)实现并配置Dao 和Service
(5)使用Spring简化数据库事务处理,即配置声明式事务管理
(6)实现并配置Controller
难点是Spring整个MyBatis
其中步骤 (2)~ (5)属于 Spring 整合MyBatis ,步骤(6)属于Spring整合 SpringMvc
步骤一:添加三个框架相关的 jar 文件,并创建相关的配置文件
1、添加 SpringMvc框架
2、添加 spring框架
3、添加MyBatis框架
步骤二:为MyBatis配置数据源对象:在Spring容器中配置 dbcp 和 c3p0 数据源
配置数据源对象的主要目的,通俗来讲就是缓解系统压力,提高性能
MyBatis是对 Java 数据连接(JDBC)的封装,在访问数据库的时候,同样需要数据库连接,而创建数据库连接是一项开销很大的工作,对于Web应用程序这种多线程并发环境而言,如果每次访问数据库都创建新的连接,会严重影响系统的性能。连接池就是为了解决这个问题而诞生的,它的工作原理并不复杂,其相当于一个容器,里面保存了一定数量的连接对象,当程序到连接池中取对象时,连接池就返回一个可用的,空闲的连接给程序使用,当程序用完这个连接后,并不直接销毁它,而是把这个连接归还给连接池,以供其他线程使用,这样就实现了数据库连接的重复使用,避免多次创建连接对象而带来的系统开销
连接池中的连接对象是由数据源创建的,目前流行的数据源框架有dbcp、c3p0、Proxool等,它们都实现了连接池功能,都能为MyBatis中的SqlSession提供数据库连接,在整合Spring和MyBatis的时候,需要把数据源对象配置到Spring容器中。建议首选c3p0
下面以c3p0和dbcp为例:首先需要在项目中添加jar文件,大家可以自行下载,这里使用的版本是:
c3p0-0.9.1.jar 和 commons-dbcp1.4.jar
根据自己选择的数据源,导入其中一个jar文件即可。接下来在Spring配置文件中配置数据源了。
c3p0和dbcp的配置略有不同,它们的很多属性名称都不一样,c3p0 的配置代码如下
<!--destroy-method="close":当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用 -->
<bean id="dataSource"destroy-method="close"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 连接数据库的驱动类 -->
<property name="driverClass"
value="oracle.jdbc.driver.OracleDriver">
</property>
<!-- 连接数据库的url -->
<property name="jdbcUrl"
value="jdbc:oracle:thin:@127.0.0.1:1521:orcl">
</property>
<property name="user"value="scott"></property>
<property name="password"value="tiger"></property>
<!-- 连接数池的最大连接数-->
<property name="maxPoolSize"value="500"></property>
<!-- 连接数池的最小连接数-->
<property name="minPoolSize"value="1"></property>
<!-- 初始化连接数-->
<property name="initialPoolSize"value="20"></property>
<!-- 连接的最大空闲时间,超时的连接将被丢弃,单位:秒-->
<property name="maxIdleTime"value="60"></property>
<!-- 没有连接可用时,等待的连接时间,单位:毫秒-->
<property name="checkoutTimeout"value="2000"></property>
dbcp的配置代码如下
<beanid="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<propertyname="driverClassName"
value="oracle.jdbc.driver.OracleDriver">
</property>
<propertyname="url"
value="jdbc:oracle:thin:@127.0.0.1:1521:orcl">
</property>
<propertyname="username" value="scott"></property>
<propertyname="password" value="tiger"></property>
<!--最大活动连接数 -->
<propertyname="maxActive" value="500"></property>
<!--最大空闲连接数 -->
<propertyname="maxIdle" value="5"></property>
<!--最小空闲连接数 -->
<propertyname="minIdle" value="1"></property>
<!--初始化连接数 -->
<propertyname="initialSize" value="10"></property>
<!-- 没有连接可用时,等待的连接时间,单位:毫秒-->
<propertyname="maxWait" value="2000"></property>
</bean>
进行了数据源配置以后,Spring就会把相应的数据库连接管理类的对象加载到容器中,MyBatis就可以使用这个对象来获取并管理连接了
步骤二 :配置MyBatis的SqlSessionFactory工厂
MyBatis的持久化操作是通过SqlSession来完成的,而SqlSession又是由SqlSessionFactory管理的,当系统需要进行数据库操作的时候,首先通过SqlSessionFactory取得一个SqlSession对象,然后SqlSession可以通过数据源取得的Connection去连接数据库,从而完成操作。所以,接下来要做的是如何把SqlSessionFactory配置到Spring容器中,代码如下
<bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource"ref="dataSource" />
<property name="mapperLocations" value="classpath:com/mapper/*Mapper.xml"/>
<!--typeAliasesPackage:指定实体类的包名,将类名映射成别名 -->
<property name="typeAliasesPackage"value="com.entity" />
</bean>
Mybatis的所有操作都是基于一个SqlSession的,而SqlSession是由SqlSessionFactory来产生的,SqlSessionFactory又是由SqlSessionFactoryBuilder来生成的。但是Mybatis-Spring是基于SqlSessionFactoryBean的。在使用Mybatis-Spring的时候,我们也需要SqlSession,而且这个SqlSession是内嵌在程序中的,一般不需要我们直接访问。SqlSession也是由SqlSessionFactory来产生的,但是Mybatis-Spring给我们封装了一个SqlSessionFactoryBean,在这个bean里面还是通过SqlSessionFactoryBuilder来建立对应的SqlSessionFactory,进而获取到对应的SqlSession。通过SqlSessionFactoryBean我们可以通过对其指定一些属性来提供Mybatis的一些配置信息
步骤2-1 : mybatis自动扫描加载sql映射文件和接口
mybatis-spring提供了MapperScannerConfigurer这个类,
它将会查找类路径下的映射器并自动将它们创建成MapperFactoryBean, 而MapperFactoryBean的出现为了代替手工使用SqlSessionDaoSupport或SqlSessionTemplate编写数据访问对象(DAO)的代码,使用动态代理实现
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage"value="com.mapper"/>
<property name="sqlSessionFactory"ref="sqlSessionFactory"/>
</bean>
上述配置会扫描com.mapper下的所有接口,然后创建各自接口的动态代理类。
步骤三:使用Spring简化数据库事务处理
问题1:回忆在MyBatis中我们是怎么进行数据操作的?
在MyBatis中我们每次进行一个操作的的时候我们都是要先打开session,然后进行数据操作,然后提交事务,关闭session
问题2:Spring在整合MyBatis后,事务是怎样管理的?
当Spring对MyBatis进行整合之后,不再是每次都去拿Session进行数据操作了,也不需要每次都开启事务,提交事务了, MapperScannerConfigurer会自动执行完操作后提交事务
虽然Spring提供了自动提交事务,但是这样并不满足我们实际的业务需求,因为有时候在保存一个数据之后,程序希望它能继续保存另一条数据,即希望在保存完两条或者多条之后一起进行事务提 交,这样即使出错,还可以回滚,确保数据的一致性,要么都成功要么都失败,这时候我们就不能每保存完一条数据之后事务就自动提交,因为这样它们不在同一个事务当中,我们不能保证数据的一致行。所以这时候我们就需要手动的来配置我们的事务,这就需要用到Spring为MyBatis提供的事务管理机制
事务是各种类型的应用程序都需要考虑的问题,特别是web应用程序,数据库事务就是一个典型的事务,Spring 提供了一套完整、优秀的事务处理机制,这套机制拥有以下特点:
1、依赖底层实现,但不与底层API耦合,例如,在ssm框架中,Spring依赖MyBatis实现数据库事务管理,但编程时并不需要直接调用MyBatis的事务API
2、提供了编程式事务处理,也提供了声明式事务处理。编程式事务是指在程序中以代码的方式管理事务,这个方式很灵活,但代码具有侵入式,耦合度高;声明式事务是以配置的方式管理事务,它基于AOP实现,与代码完全分离,配置即可用,减少了工作量,但需要有良好的约定,在实际开发中,一般使用后者。
声明式事务处理其实现基本步骤如下:
配置事务管理类对象
配置事务的增强处理类(即配置事务的传播特性)
配置事务的AOP切入点,并织入事务处理
配置事务管理类对象代码如下:
<bean name="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"ref="dataSource"/>
</bean>
<tx:adviceid="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:methodname="search*" read-only="true"propagation="REQUIRED" isolation="DEFAULT"timeout="-1"/>
<tx:methodname="add*"/>
<tx:methodname="update*"/>
<tx:methodname="modify*"/>
<tx:methodname="remove*"/>
<!--<tx:method name="get*"/> --><!--最好不要这么配置,会导致属性的getter也加入事务处理 -->
</tx:attributes>
</tx:advice>
事务的传播特性在<tx:method>中进行设置,Spring支持对不同的方法设置不同的事务属性,所以可以为一个<tx:advice> 配置多个<tx:method>,其中name属性指定匹配的方法(模糊匹配),这里需要对这些方法名进行约定,以保证这些匹配到的方法能够正确被切入。以下是事务的常用属性介绍
read- only : 设置该事务中是否允许修改数据,对于只执行查询功能的事务,把它设置为true,能提高事务的执行速度。
propagation:事务传播机制,一般设置为REQUIRED,如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。如果取值为REQUIRES_NEW,则新建事务,如果当前存在事务,把当前事务挂起
Isolation:事务的隔离等级,即当前事务和其他事务的隔离程度,在并发情况下需要考虑该属性的设置。
取值为 default,使用数据库默认的隔离级别,oracle默认隔离级别为READ COMMITTED:可以避免脏读,但可能会出现不可重复读和幻读
取值 READ_UNCOMMITTED:会出现脏读,不可重复读和幻读
取值 REPEATABLE_READ:会出现幻读
取值SERIALIZABLE:串行化
timeout:允许事务运行的最长时间,以秒为单位,取值-1,则永久运行
配置事务的传播特性以后,最后还需要设置事务的AOP切入点,代码如下:
<!-- 设置切入点 -->
<aop:config>
<aop:pointcutexpression="execution(public * com.serviceImpl..*(..))"id="service"/>
<!-- 在特定的连接点,通知所开启的事务针对所提供的方法-->
<aop:advisoradvice-ref="txAdvice" pointcut-ref="service"/>
</aop:config>
设置的含义是:对com.serviceImpl包及其子包下的所有类的所有公共方法进行切入,当然被切入的方法还要经过<tx:method>筛选,而通常一般是把事务边界设置到service层,因为很多时候都是在服务层来完成一系列的业务操作,如果放到Dao数据层,其粒度太小了,
经过这三个步骤设置好声明式事务以后,当service中的业务方法被调用之前,Spring会获取事务对象并启动事务,并使用try-catch-finally来处理异常,业务方法执行成功则会提交事务,默认情况下如果抛出了RuntimeException就会回滚事务
通过Listener加载Spring容器
对于Spring来说,它需要启动容器后才能为其他框架提供服务,由于Web应用程序的入口是被Web服务器控制的,所以无法在main()方法中通过创建ClassPathXmlApplicationContext 对象来加载Spring容器。为了解决这个问题,Spring 提供了一个监听器来启动容器:org.springframework.web.context.ContextLoaderListener
该监听器实现了ServletContextListener 接口,可以在Web容器启动的时候初始化Spring 容器,从而完成Spring的加载,当然,前提条件是需要在web.xml中配置好这个监听器,代码如下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
其中,contextConfigLocation 用来指定Spring配置文件的路径,<listener-class>节点下配置ContextLoaderListener,经过以上配置,就能在Web 应用程序启动的同时启动Spring 容器了
完整配置如下
Web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>proctice_ssm</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list>
<!-- 配置mybatis配置文件的映射路径--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mybatis.xml</param-value> </context-param>
<!-- 监听器类:完成spring框架的初始化操作,例如bean的创建,对象发的注入等 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<!-- 配置springmvc的前段控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 随着容器一起启动 --> <load-on-startup>1</load-on-startup> </servlet> <!-- springmvc控制器所控制的请求URL,如若是*.do则向下执行,如若是其他则不经过前段控制器 --> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
<!-- 配置Spring提供的编码过滤器,设置乱码问题 --> <filter> <filter-name>charEncoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>charEncoding</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>
</web-app> |
spring-mvc配置文件
<?xml version="1.0" encoding="UTF-8"?> <!-- 配置的头文件 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 自动扫描指定包中含有@Repository,@Service,@Controller注解的对象 --> <!-- 注意在指定包的时候,通常是一个controller和一个service实现类,dao层则不需要, 因为在spring-mybatis的配置文件当中,已经为每个接口生成了动态代理对象,以及通过其内部维护的 SqlSessionTemplate对象负责打开session,提交和回滚 因此只需在controller和service实现类当中添加相应的注解 --> <context:component-scan base-package="com.controller,com.serviceImpl"></context:component-scan>
<!-- 将普通字符串配合ResponseBody输出到客户端 --> <bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8" /> </bean>
<!-- 定义将对象或者集合转换为json格式字符串对象 --> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes" value="application/json;charset=utf-8" /> </bean>
<!-- 配置映射处理器,将url请求映射给某个具体的handler --> <!-- 启动springmvc的注解,在ioc容器中注册RequestMappingHandlerMapping --> <mvc:annotation-driven> <mvc:message-converters> <ref bean="stringConverter"/> <ref bean="jsonConverter"/> </mvc:message-converters> </mvc:annotation-driven> <!-- 配置视图解析器,作用一:通过InternalResourceViewResolver将逻辑视图转换为真实的物理视图 作用二:通过View对象渲染数据到jsp中 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀:将逻辑视图名拼接指定的url前缀 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 后缀:将逻辑视图名拼接成指定的后缀 --> <property name="suffix" value=".jsp"></property> </bean>
<!-- 文件上传的类型解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 配置文件的编码方式 --> <property name="defaultEncoding" value="utf-8" /> <!-- 设置上传文件的最大尺寸为5MB --> <property name="maxUploadSize" value="5242880"/> <!-- 配置缓存 --> <property name="maxInMemorySize" value="40960"/> </bean>
<!-- 定义拦截器链 --> <!-- <mvc:interceptors> --> <!-- 定义计算控制器耗时的拦截器 --> <!-- <mvc:interceptor> --> <!-- mvc:mapping:需要拦截的url请求 --> <!-- <mvc:mapping path="/**"/> --> <!-- <bean class="com.userInceptor.ControllerTime"></bean> --> <!-- </mvc:interceptor> -->
<!-- 定义权限验证拦截器 --> <!-- <mvc:interceptor> --> <!-- <mvc:mapping path="/**"/> --> <!-- <mvc:exclude-mapping path="/login.do"/> --> <!-- <mvc:exclude-mapping path="/checklogin.do"/> --> <!-- 放行指定的url --> <!-- <bean class="com.userInceptor.CheckUserLogin"></bean> --> <!-- </mvc:interceptor> -->
<!-- </mvc:interceptors> --> </beans> |
Spring-mybatis
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!--步骤一:配置数据源--> <!--destroy-method="close":当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用 --> <bean id="dataSource" destroy-method="close" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 连接数据库的驱动类 --> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property> <!-- 连接数据库的url --> <property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"></property> <property name="user" value="scott"></property> <property name="password" value="tiger"></property> <!-- 连接数池的最大连接数--> <property name="maxPoolSize" value="500"></property> <!-- 连接数池的最小连接数--> <property name="minPoolSize" value="1"></property> <!-- 初始化连接数--> <property name="initialPoolSize" value="20"></property> <!-- 连接的最大空闲时间,超时的连接将被丢弃,单位:秒--> <property name="maxIdleTime" value="10"></property> <!-- 没有连接可用时,等待的连接时间,单位:毫秒--> <property name="checkoutTimeout" value="20000"></property> </bean>
<!--步骤二:配置MyBatis的SqlSessionFactory工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- 给指定包中的对象定义类型别名,名称是对象名,然后首字母小写 --> <property name="typeAliasesPackage" value="com.entity"></property> </bean>
<!--步骤2-1:mybatis自动扫描加载sql映射文件和接口 --> <!-- MapperScannerConfigurer:负责扫描指定包中的接口和接口对应的sql映射文件,然后给每个接口生成动态代理对象,同时通过其内部维护的SqlSessionTemplate对象负责打开session,提交和回滚 事务,关闭session等操作 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.mapper"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
<!-- 声明式事务管理 --> <!--步骤三:配置事务管理类对象 --> <bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--步骤四:配置事务的传播特性: 事务所经过的方法约定 --> <tx:advice id="txadvice" transaction-manager="tm"> <tx:attributes> <tx:method name="select*" /> <tx:method name="check*" /> <tx:method name="insert*" /> <tx:method name="add*" /> <tx:method name="update*" /> <tx:method name="modify*" /> <tx:method name="delete*" /> <tx:method name="drop*" /> </tx:attributes> </tx:advice> <!--步骤五:配置事务的AOP切入点,并织入事务处理 --> <aop:config> <!-- 定义切入点 --> <aop:pointcut expression="execution(public * com.serviceImpl.*.*(..))" id="pt1" /> <!-- 在特定的连接点,通知所开启的事务针对所提供的方法 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pt1" /> </aop:config>
</beans> |
简单案列
首先是一个请求
@RequestMapping("/emp") public ModelAndView getemp(){ System.out.println("nihao"); List<Emp> list = empservice.selectemp(); System.out.println(list); ModelAndView m = new ModelAndView(); //m.addObject("listemp",list); m.setViewName("emp"); returnm;
} |
利用注解获取的接口的动态代理对象,Empservice为接口
@Autowired private Empservice empservice; public Empservice getEmpservice() { returnempservice; } publicvoid setEmpservice(Empservice empservice) { this.empservice = empservice; } |
接口
publicinterface Empservice { public List<Emp> selectemp(); } |
接口的实现类
@Service publicclass EmpServiceImpl implements Empservice{
private EmpDaoMapper dao; public EmpDaoMapper getDao() { returndao; } @Autowired Autowired为通过类型注入 publicvoid setDao(EmpDaoMapper dao) { this.dao = dao; } @Override 重写接口的方法 public List<Emp> selectemp() { System.out.println("service层"); returndao.selectemp(); } } |
注意:EmpDaoMapper为一个接口,表面看来并没有对应的实现类,不能够实例化,得到对应的对象,进而调用其相应的方法,但是在spring-mybatis配置了这个,所以在配置文件中,已经为没和接口生成了动态代理对象,因此在这里能够通过Autowired获取ioc容器当中的对象 <!--步骤2-1:mybatis自动扫描加载sql映射文件和接口 --> <!-- MapperScannerConfigurer:负责扫描指定包中的接口和接口对应的sql映射文件,然后给每个接口生成动态代理对象,同时通过其内部维护的SqlSessionTemplate对象负责打开session,提交和回滚 事务,关闭session等操作--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.mapper"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean> |
接口的名称一定要和sql映射文件的类名一致,最好在同一个包地下
Sql映射文件
<!-- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+sql映射文件名, 这样就能够保证namespace的值是唯一的 --> <mapper namespace="com.mapper.EmpDaoMapper"> <select id="selectemp" resultType="com.entity.Emp"> select * from emp </select> </mapper> |
注意:sql语句的id一定得和service中的调用方法一致,通常来说在一个完整的请求以及处理当中,方法最好在controller,service,dao层保持一致,方便修改使用,减少错误