Spring学习记录(03)——MyBatis-Spring项目

###0.前言
《Java EE互联网轻量级框架整合开发——SSM框架(Spring MVC+Spring+MyBatis)和Redis实现》

本文主要记录Spring框架与MyBatis框架联合使用的说明,主要是使用MyBatis-Spring项目项目

相关连接地址:

###1. MyBatis-Spring的使用

  • 配置数据源
  • 配置SqlSessionFactory(可配置SqlSessionTemplate,同时存在优先使用SqlSessionTemplate)
  • 配置Mapper
  • 事务管理

配置数据源:

  1. 使用spring提供的简单数据库配置,不支持连接池

    //spring-config.xml
    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
    <property name="username" value="root" /> 
    <property name="password" value="root"/> 
    <property name="driverClass" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/ssm" /> 
    </bean>
    
  2. 使用第三方数据库连接池(DBCP)

    //spring-config.xml 
    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/ssm" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <!--连接池的最大数据库连接数 -->
        <property name="maxActive" value="255" />
        <!--最大等待连接中的数量 -->
        <property name="maxIdle" value="5" />
        <!--最大等待毫秒数 -->
        <property name="maxWait" value="10000" />
    </bean>
    
  3. 使用JNDI数据库连接池

    //spring-config.xml 
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
        <property name="jndiName" value="java:comp/env/jdbc/ssm" />
    </bean>
    

配置SqlSessionFactory:
主要通过SqlSessionFactoryBean进行配置

//spring-config.xml
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" /> <!--数据源配置-->
    <property name="configLocation" value="classpath:sqlMapConfig.xml" /> <!--MyBatis配置-->
</bean>

//可选配置JdbcTemplate,同时存在sqlSessionFactory和SqlSessionTemplate,则优先使用SqlSessionTemplate
//线程安全
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
</bean>

MyBatis相关配置:

//sqlMapConfig.xml
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!-- 这个配置使全局的映射器启用或禁用缓存 -->
        <setting name="cacheEnabled" value="true" />
        <!-- 允许 JDBC 支持生成的键。需要适合[修改为:适当]的驱动。如果设置为true,则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如 Derby) -->
        <setting name="useGeneratedKeys" value="true" />
        <!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新  -->
        <setting name="defaultExecutorType" value="REUSE" />
        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间  -->
        <setting name="defaultStatementTimeout" value="25000"/> 
    </settings>
    <!-- 别名配置 -->
    <typeAliases>
        <typeAlias alias="role" type="com.ssm.chapter12.pojo.Role" />
    </typeAliases>

    <!-- 指定映射器路径 -->
    <mappers>
        <mapper resource="com/ssm/chapter12/sql/mapper/RoleMapper.xml" />
    </mappers>
</configuration>

配置Mapper:

  • 单个配置:MapperFactoryBean

    //Spring-config.xml
    <bean id="roleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
        <property name="mapperInterface" value="com.ssm.chapter12.mapper.RoleMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
        <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
    </bean>
    

    mapperInterface:映射器的接口。

  • 批量扫描: MapperScannerConfigurer

    //Spring-config.xml
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ssm.chapter12.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <!-- 使用sqlSessionTemplateBeanName将覆盖sqlSessionFactoryBeanName的配置 -->
        <!-- <property name="sqlSessionTemplateBeanName" value="sqlSessionFactory"/> -->
        <!-- 指定标注才扫描成为Mapper:@Repository-->
        <property name="annotationClass" value="org.springframework.stereotype.Repository" />
        <!-- 方式二:通过基类接口设置扫描
        <property name="markerInterface" value="com.ssm.chapter12.mapper.BaseMapper" />
        -->
    </bean>
    
    //RoleMapper.java
    @Repository //通过注解标记这是一个DAO层
    public interface RoleMapper {
        public int insertRole(Role role);
    }
    
    • basePackage:指定自动扫描的包名,多个以”,”隔开。
    • annotationClass:只扫描带有指定注解的类。eg:只扫描带有@Repository的类
    • markerInterface:指定实现了特定接口的类才为Mapper。eg:public interface RoleMapper extends BaseMapper{...}

配置事务管理器:

  1. 代码配置事务管理器

    1. config类实现TransactionManagementConfigurer接口,实现返回PlatFormTransactionManager的方法。
    2. config类上添加 @EnableTransactionManagement注解,开启Spring上下文使用事务注解@Transactional

示例代码:

@Configuration   //类中存在Bean需要管理
@ComponentScan("com.ssm.chapter13.*")  //扫描指定包底下的类,加入Spring IoC容器
@EnableTransactionManagement           //开启上下文对事务注解@Transactional的使用
public class DBConfig implements TransactionManagementConfigurer{
    //1.配置数据源        
    @Bean(name="dataSource")
    public DataSource initDataSource(){...}

    @Override
    @Bean(name="transactionManager")
    public PlatFormTransactionManager annotationDrivenTransactionManager(){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(initDataSource());
        return transactionManager;
    }
} 
  1. xml配置事务管理器

需要添加命名空间和模板文件:

http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

事务管理器的配置:

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

<!--启用扫描机制,并指定扫描对应的包。-->
<context:component-scan base-package="com.ssm.chapter13.*" />

<!-- 使用注解定义事务 :@Transactional的使用-->
<tx:annotation-driven transaction-manager="transactionManager" />

事务的使用:

  1. 使用@Transactional标记方法为事务方法

    @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,timeout=3)
    public int insertRole(Role role){...}
    
  2. 使用TransactionDefinition进行编程式调用事务。

    TransactionDefinition def = new DefaultTransactionDefinition();
    PlatfromTransactionManager transactionManager = ctx.getBean(PlatfromTransactionManager.class);
    TransactionStatus status = transactionManager.getTransaction(def);
    //SQL执行
    //transactionManager.commit(status); 或者 transactionManager.rollback(status);
    

@Transactional失效问题:

@Transactional也是通过Spring AOP技术实现的,所以方法必须遵循以下几点:

  • 公用方法public
  • 非静态方法static
  • 非自调用,即不能直接调用自身事务方法,需要通过 xxService.mothed()调用。

###2.总结
由于官方提供了MyBatis-Spring项目用于快速整合MyBatis和Spring,所以整合相对简单,只需要根据流程配置Spring和MyBatis即可。
需要注意的是MyBatis的Mapper只是一个接口文件,需要通过MapperScannerConfigurer扫描并注册到Spring IoC中。

END

– Nowy

– 2018.12.14

分享到