Spring5.x整合mybatis3.x的配置文件详解

项目目录结构如下图:

Spring5.x整合mybatis3.x的配置文件详解_第1张图片

一: 配置文件的约束

约束,就是用到了什么就加上就好,一般以下约束就足够了:

<?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:context="http://www.springframework.org/schema/context"
       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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">

二:引入外部properties文件,用于配置数据源的参数

jdbc.properties文件如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456

方式一:通过PropertyPlaceholderConfigurer

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:jdbc.properties"/>
</bean>

方式二:通过context:property-placeholder标签

   <context:property-placeholder location="classpath:jdbc.properties"/>

配置的作用

  • 像数据库配置这种随环境变化的文件我们并不想打到war中,而是希望引入war包外的文件。
  • 这样配置之后,我们可以在properties文件里随时修改数据源的设置项,
  • 同时降低了耦合度.

推荐使用方式二

  • 其中属性location还提供了file:、http:和ftp:三种前缀,分别通过文件路径、HTTP资源和FTP资源引入文件.
  • classpath表示类路径,也就是resources目录下.

三: 包扫描, 扫描类注解,把类的对象添加到容器中

	 <!--注解的包扫描-->
    <context:component-scan base-package="com.zuoyueer"/>

配置的作用:

  • 扫描base-package指定的包下(包含后代包) 的 @Component、@Service、@Controller、@Repository注解的类,并把这些类注册进Spring容器中管理。
  • 如果不加这个配置,那么@Component、@Service、@Controller、@Repository注解将无效,Spring容器中不会有这些注解修饰的类对象
  • 实际上@Service、@Controller、@Repository注解是@Component的子注解,目的是区分项目层次,目前版本(5.x)实际作用一样,是Spring保留的一个功能,待以后扩展增强这些子注解

属性

use-default-filters默认值是true,表示所有注解都扫描,因为默认是true所以下面两种写法都一样

 <--扫包下全部注解--/>
 <context:component-scan base-package="com.zuoyueer"/>
  <--扫描包下全部注解--/>
 <context:component-scan base-package="com.zuoyueer" use-default-filters="true" />

下面的配置表示,扫描com.zuoyueer包下的部分注解,也就是不包括@Controller修饰的类,
被@Controller修饰的类,不会注册到Spring容器中.

<!-- 实际开发中 spring 配置文件,一般这样配置-->  
<context:component-scan base-package="com.zuoyueer" use-default-filters="true">  
     <context:exclude-filter type="annotation"   
         expression="org.springframework.stereotype.Controller" />  
</context:component-scan>  

下面的配置表示,扫描com.zuoyueer包下的@annotation注解,其他注解不扫描.

<!-- 实际开发中  spring mvc  ,一般这样配置-->     
<context:component-scan base-package="com.zuoyueer" use-default-filters="false">  
    <context:include-filter type="annotation"   
        expression="org.springframework.stereotype.Controller" />  
</context:component-scan>  

小结:

  • use-default-filters 属性的默认值为 true,为true的时候可以省略不写
  • true的时候表示 使用默认的 Filter 进行包扫描,而默认的 Filter 对标有 @Component, @Service,@Controller和@Repository 的注解的类进行扫描
  • false的时候表示 不使用Filter 进行包扫描. 为false的时候不能省略
  • 我们希望 SpringMVC 只来控制网站的跳转逻辑,所以我们只希望 SpringMVC 的配置扫描 @Controllerce 注解标注的类,不希望它扫描其余注解标注的类,所以设置了 use-default-filters 为 false,并使用 context:include-filter 子标签设置其只扫描带有 @Controller 注解标注的类。
  • 而 Spring 就不同了,我们希望 Spring 仅仅不扫描带有 @Controller 注解标注的类,而扫描其他注解标注的类,而这时建立在使用默认的 Filter 进行扫描的基础上,所以 use-default-filters 为 true

为啥Spring和Spring MVC包扫描要分开?
实际上是一种解耦,使程序易于扩展和维护
大家可以看另外一篇博客有详细解释 https://www.cnblogs.com/moxiaotao/p/9246668.html

三: 配置数据源(连接池)

常用的连接池有C3P0, Druid,HikariCP . 推荐使用HikariCP,它是目前最优秀的连接池,而是SpringBoot2.0的默认连接池就是它.

  <!--注册数据源-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

value的值就使用到了jdbc,properties文件中的数据,使用规则就是OGNL(对象导航语言),和El表达意义,是因为EL表达式是它的一部分,

四:配置事务管理器

在Spring中数据库事务是通过PlatformTransactionManager进行管理的,jdbcTemplate是不能支持事务的,而能够支持事务的是org.springframework.transaction.support.TransactionTemplate模板,它是Spring所提供的事务管理器的模板

  • 事务的创建、提交和回滚是通过PlatformTransactionManager接口来完成的。
  • 当事务产生异常时会回滚事务,在默认的实现中所有的异常都会回滚。我们可以通过配置去修改在某些异常发生时回滚或者不回滚事务。
  • 当无异常时,会提交事务。
  • 支持JTA事务,常用的是DataSourceTransactionManager,它继承抽象事务管理器AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又实现了PlatformTransactionManager。这样Spring就可以如同源码中看到的那样使用PlatformTransactionManager接口的方法,创建、提交或者回滚事务了。

用得最多的事务管理器是DataSourceTransactionManager(org.springframework.jdbc.datasource.DataSourceTransactionManager),因此下面将以此例进行讲解。如果使用的持久框架是Hibernate,那么你就要用到spring-orm包org.springframework.orm.hibernate4.HibernateTransactionManager了。它们大同小异.

下面配置一个事务管理器

	<!--配置事务管理器,注意这个id,下面一节会用到-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

使用DataSourceTransactionManager去定义数据库事务管理器,并且注入了数据库连接池。这样Spring就知道你已经将数据库事务委托给事务管理器transactionManager管理了。在jdbcTemplate源码分析时,数据库资源的产生和释放如果没有委托给数据库管理器,那么就由jdbcTemplate管理,但是此时已经委托给了事务管理器,所以jdbcTemplate的数据库资源和事务已经由事务管理器处理了。

五: 配置事务驱动

  • 首先必须说的的:Srping声明式事务管理有2种,一种是XML方式,一种是注解方式,
  • 如果使用XML方式,该配置不用配置
  • 如果使用了注解的方式,该配置必须写,如果不配置,那么注解(声明事务)将无效

下面是配置事务驱动

    <tx:annotation-driven transaction-manager="transactionManager"/>

事务驱动的作用: 解析项目中的@Transactionl 注解

  • 属性transaction-manager的作用是指定事务驱动的事务管理器, transactionManager是第四节中配置的事务管理器的id属性值.
  • Spring默认的事务管理器的id是transactionManager,
  • 如果我们自己配置的事务管理器的id值不是transactionManager而且配置事务驱动的时候不指定事务管理器,那么Spring就会去找默认的,结果找不到,就会报错.
  • 如果我们自己配置的事务管理器的id值是transactionManager,因为默认的事务管理器的id是transactionManager,所以在配置事务驱动的时候可以不指定事务管理器.
  • 总之,为了不错出,建议配置事务驱动的时候指定事务管理器,也就是transaction-manager属性得加上

六: 配置AOP驱动

首先必须说的是: 和事务驱动一样,如果是通过XML方式实现AOP操作,那么可以不配置该驱动,如果是注解方式实现AOP操作,那么必须配置AOP驱动.

第一种配置

	 <!--开启AOP注解驱动-->
    <aop:aspectj-autoproxy proxy-target-class="false"/>
 	或者
     <aop:aspectj-autoproxy />

配置AOP驱动作用: 解析AOP相关的注解

  • 属性proxy-target-class的默认值是false,如果是false可以省略不写
  • false表示使用JDK动态代理织入通知到切入点.
  • true表使用CGLIB动态代理织入通知到切入点,
  • 实际上,即使设置成false,如果切入点所在类没有实现相对应接口,那么Spring也会自动使用CGLIB动态代理
  • 总之,我们不用proxy-target-class属性就好了.一切交给Spring自己处理吧

七: 注册SqlSessionFactory

  • 在基本的MyBatis中,SqlSessionFactory可以使用SqlSessionFactoryBuilder来创建
  • 而我们使用了MyBatis-Spring类库整合了MyBatis,MyBatis-Spring帮助我们将MyBatis代码无缝的整合到了Spring中. 这个类库提供了简单的方式来注入MyBatis数据映射器和SQLSession到Spring容器中.
  • SqlSessionFactoryBean实现了Spring的FactoryBean接口。这意味着Spring最终返回的不是SqlSessionFactoryBean而是作为factory 的getObject()方法返回的结果,即SqlSessionFactory对象 .这相当于下面的java代码:
		SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();   
		SqlSessionFactory sessionFactory = factoryBean.getObject();  
  • SqlSessionFactory有一个必须的属性:dataSource, 也就是必须配置数据源

注册SqlSessionFactory:

 <!--注册SqlSessionFactory, 因为SqlSessionFactory是接口,所以使用SqlSessionFactoryBean来注册-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--引入数据源(必须)-->
        <property name="dataSource" ref="dataSource"/>
        <!--引入别名-->
        <property name="typeAliasesPackage" value="com.zuoyueer.domain"/>
        <!--引入mybatis的配置文件(全局配置文件)-->
        <property name="configLocation" value="SqlMapConfig.xml"/>
    </bean>

因为Spring整合Mybatis,所原来在myBatis配置文件中的设置都能在spring配置文件中做.
重要的事情多说一遍,注册SqlSessionFactory必须引入数据源!

八: 加载映射文件

在很久以前,使用MapperFactoryBean创建的代理类实现了 Mapper 接口,并且注入到Spring容器中,但是这种做法已经淘汰了,因为系统有很多的配置文件时 全部需要手动编写,而且没有必要在 Spring 的 XML 配置文件中注册所有的映射器.
于是MapperScannerConfigurer就应运而生了.MapperScannerConfigurer它将会查找类路径下的映射器并自动将它们创建成MapperFactoryBean。

加载映射文件

 	<!--加载映射文件,  配置 Mapper 扫描器 注册Mapper的包扫描 代替了Mybatis中Mappers标签-->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zuoyueer.dao"/>
        <!--指定SqlSessionFactory,实际上是指定数据源,在单数据源的项目中,这给可以不写-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

basePackage属性是让你为映射器接口文件设置基本的包路径。 你可以使用分号或逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到。

  • 为什么sqlSessionFactoryBeanName要用value而不用ref?
        在mybatis-spring1.1.0以前,是通过将SqlSessionFactory对象注入到sqlSessionFactory,这样做可能会有一个问题,就是在初始化MyBatis时,jdbc.properties文件还没被加载进来,dataSource的属性值没有被替换,就开始构造sqlSessionFactory类,属性值就会加载失败。在1.1.0以后,MapperScannerConfigure提供了String类型的sqlSessionFactoryBeanName,这样将bean name注入到sqlSessionFactoryBeanName,这样就会等到spring初始化完成后,再构建sqlSessionFactory。
  • 如果在多数据源的项目中,这里必须指定SqlSessionFactory,实际上是指定数据源
  • 如果Mapper.xml与Mapper.class不在同一个包下或者包不同名,
        这种情况下就不能使用包扫描了,而应该在注册SqlSessionFactory中配置mapperLocations,来指定映射文件
 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--引入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--引入别名-->
        <property name="typeAliasesPackage" value="com.zuoyueer.domain"/>
        <!--引入mybatis的配置文件-->
        <property name="configLocation" value="SqlMapConfig.xml"/>
		<!--接口的包名和配置文件的包名不一样的时候使用mapperLocations来指定映射配置文件-->
        <property name="mapperLocations" value="classpath*:com/zuoyueer/dao/*.xml"/>
    </bean>

classpath:表示在类路径下找,也就是sources下
classpath*:表示在全部路径下找也就是src和sources下
其中*是个通配符,代表任意的字符串或者某个文件
**代表任意多级目录:比如 classpath:com/**/User*.xml表示在sources目录找,com目录下(包括后代目录)的全部以前缀名是User的xml文件

完整的配置如下:

Spring的配置文件: spring.xml

<?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:context="http://www.springframework.org/schema/context"
       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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--引入外部配置-->
   <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--注解的包扫描-->
    <context:component-scan base-package="com.zuoyueer" use-default-filters="true"/>

    <!--开启事务驱动,必须指定事务管理器,默认的事务管理器名称是transactionManager,
    如果事务管理器的名称不是transactionManager,而且这里没指定,那么会报错-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--开启AOP注解驱动-->
    <aop:aspectj-autoproxy proxy-target-class="false"/>

    <!--注册SqlSessionFactory, 因为SqlSessionFactory是接口,所以使用SqlSessionFactoryBean来注册-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--引入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--引入别名-->
        <property name="typeAliasesPackage" value="com.zuoyueer.domain"/>
        <!--引入mybatis的配置文件-->
        <property name="configLocation" value="SqlMapConfig.xml"/>
        <!--映射文件和接口的包名不一样的时候才配置这个-->
        <property name="mapperLocations" value="classpath*:com/zuoyueer/dao/*.xml"/>
    </bean>

    <!--加载映射文件,  配置 Mapper 扫描器 注册Mapper的包扫描 代替了Mappers标签-->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.zuoyueer.dao"/>
        <!--指定注册SqlSessionFactory,实际上是指定数据源,在单数据源的项目中,这给可以不写-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!--创建数据源-->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
    </bean>

    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
     </bean>

</beans>

Mybatis的配置文件: SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--configuration 里的配置,是需要按照顺序来的,顺序是:properties,settings,typeAliases,environments,mappers,-->
<configuration>
    <!--该文件实际上可以删除,因为已经整合到了spring.xml中了,但是以后还有用,就留着-->
</configuration>

映射文件: AccountDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <!--namespace是命名空间,必须唯一,他是指是接口的全限定名 -->
<mapper namespace="com.zuoyueer.dao.AccountDao">

    <select id="findByName" parameterType="string" resultType="account">
        select * from account where name = #{name}
    </select>

    <update id="edit" parameterType="account">
        update account set name=#{name} ,money=#{money} where id=#{id}
    </update>
</mapper>

Maven依赖

   <dependencies>
        <!-- mybatis整合spring-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--Spring核心容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--SpringJdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--事务相关的-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--SpringAOP相关的坐标-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
             <scope>runtime</scope>
        </dependency>
        <!--Spring整合单元测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--HikariCP连接池-->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!--myBatis坐标-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--日志的坐标-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
    </dependencies>

其他的就不放上来了,因为每个项目都不一样,本文主要讲解的就是Spring.xml怎么写,以及相关配置的作用和注意.

如果本文有错,请指正.谢谢!

参考文献(这些博客也不一定是原创,在此谢谢(原创)大牛的分享):

https://my.oschina.net/u/1020238/blog/509159/
https://www.jianshu.com/p/adf2486ba56e
https://www.cnblogs.com/zhuzihan/p/9100617.html
https://www.cnblogs.com/sanxiao/p/9599308.html

你可能感兴趣的:(Spring)