2.5 Mybatis 与 Spring 框架整合

先来挂个“眼科”,Spring 与 Mybatis 框架整合 分为 5 步:

  1. 创建项目,引入JAR包
  2. 编写Spring配置文件applicationContext.xml;
  3. 编写Mybatis核心配置mybatis-config.xml;
  4. 引入db.properties(数据库配置文件),并在Spring的配置文件中引入(注意,此处不在Mybatis核心配置中引入了,两个框架整合后,在Spring配置中注入数据源!!!)
  5. 引入log4j.properties(用于在控制台检查执行的SQL语句)

接下来,一步一个脚印,做大做强(哦,也不对,这5步也就是做成,做大做强还远呐。。。。。。。)

第一步 引入JAR包(PS:JAR包真多。。。。贴个图放最后了)

第二步,编写Spring配置文件(进行数据源注入,事务配置,关联Mybatis。重要性不言而喻!)
在这里插入图片描述

第三步 编写Myabtis框架核心配置(主要是关联映射文件,Mybatis起作用的关键。也很重要!)
在这里插入图片描述

第四步 引入db.properties数据库配置文件(这一步属于锦上添花,可以使内部配置外部化,将数据库配置信息从Spring配置文件中分离出来,方便以后项目部署、维护)
在这里插入图片描述

第五步 引入log4j.properties:主要是方便开发人员在单元测试数据库操作时Debug使用的,可以在控制台检查执行的SQL语句,快速定位bug(这个文件目前没有什么灵魂了,这么写就可以)

在这里插入图片描述

好了,到了这Spring 与 Mybatis 框架整合完了



下面就是使用了
具体使用方式呢,这里讨论两种吧:

第一种 传统开发方式主要在DAO层(也就是MVC三层架构的Model层)

这种方法呢,主要是用 mybatis-spring 这个jar包中的SqlSessionTemplate类或者是SqlSessionDaoSupport类来实现的。这里来说说SqlSessionDaoSupport类,它继承自DaoSupport类(说它继承谁干啥。。。),在开发时主要作为DAO的基类来使用,通过SqlSessionDaoSupport类的getSqlSession方法来获取SqlSession,有了SqlSession就可以“为所欲为”了。
上代码!

package com.ssm.test;  // 自定义的单元测试包

import org.junit.jupiter.api.Test;  // 引入的支持单元测试的包
import org.springframework.context.ApplicationContext;  // Spring 的容器 ApplicationContext
import org.springframework.context.support.ClassPathXmlApplicationContext;    // 用来加载Spring 容器的包
import com.ssm.dao.CustomerDao;   // 测试的目标类
import com.ssm.po.Customer;   // 数据库表的映射实体 POJO类
/**
 * DAO测试类
 */
public class DaoTest {
    @Test
    public void findCustomerByIdDaoTest(){
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 根据容器中Bean的id来获取指定的Bean
        CustomerDao customerDao = (CustomerDao) act.getBean("customerDao");
        // 这种获取bean也可以
//	     CustomerDao customerDao = act.getBean(CustomerDao.class);  
        Customer customer = customerDao.findCustomerById(1);
        System.out.println(customer);
    }
}

然后来看看 customerDao.findCustomerById 这个方法在干啥呢(精髓到了):

package com.ssm.dao.impl;

import org.mybatis.spring.support.SqlSessionDaoSupport;
import com.ssm.dao.CustomerDao;
import com.ssm.po.Customer;
// 看到没!!! 继承了SqlSessionDaoSupport类了!!!
public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao {
    // 通过id查询客户
    public Customer findCustomerById(Integer id) {
    
// 看到没!!!利用SqlSessionDaoSupport类的getSQLSession方法获取SqlSession了!!!
        return this.getSqlSession().selectOne("com.ssm.po"
                + ".CustomerMapper.findCustomerById", id);
    }
}

看到 …….selectOone("……") 找到熟悉的感觉了吧,就是去Myabtis的映射文件中找SQL 去了,并利用 SqlSession 去操作数据库了

感觉还想看看Mybatis的映射文件???可以!看一看吧:

<?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">
<mapper namespace="com.ssm.po.CustomerMapper">
    <!--根据id查询客户信息 -->
    
    <!--这不在这呢!!!-->
    <select id="findCustomerById" parameterType="Integer"
            resultType="customer">
        select * from t_customer where id = #{id}
    </select>
    
     <!--添加客户信息 -->
    <insert id="addCustomer" parameterType="customer">
        insert into t_customer(username,jobs,phone)
        values(#{username},#{jobs},#{phone})
    </insert>
</mapper>

好了,这就是传统的基于 mybatis-spring 包中的SqlSessionDaoSupport类 在Spring 与 Mybatis 整合后,操作数据库的最简单的样子;这个办法叫传统方法,当然还有不传统的方法:



第二种 基于Mapper接口方式的开发
(1)基于MapperFactoryBean的整合开发:

核心思想,是根据Mapper接口生成Mapper对象的类,使用前需要在Spring的配置文件中配置一下:

直接上代码,怕看晕了,上图!(Spring配置文件:applicationContext.xml):
在这里插入图片描述

这是在Spring配置文件中注入的Myabtis核心配置文件中关联的映射文件(CustomerMapper.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">
<mapper namespace="com.ssm.mapper.CustomerMapper">
    <!--根据id查询客户信息 -->
    <select id="findCustomerById" parameterType="Integer"
            resultType="customer">
        select * from t_customer where id = #{id}
    </select>
</mapper>

还是简单解释一下Spring的配置文件:
mapperInterface:用于指定接口,注意:这个指定的接口的名称要与Mybatis核心配置中关联的映射文件的名称严格一致!!!,比如这里指定了CustomerMapper接口,那么映射文件名就必须是CustomerMapper.xml();
SqlSessionFactory:用于指定一个SqlSessionFactory(这里是配置好数据源和Mybatis核心配置的一个bean);
SqlSessionTemplate:用于指定SqlSessionTemplate(也是生产SqlSession的),注意:如果此时同时配置了SqlSessionFactory,只会用SqlSessionTemplate。

可能有人好奇 在mapperInterface属性注入的接口CustomerMapper 是啥样的,好的。

package com.ssm.mapper;

import com.ssm.po.Customer;

public interface CustomerMapper {
    // 通过id查询客户
    public Customer findCustomerById(Integer id);

    // 添加客户
    public void addCustomer(Customer customer);


}

最后这是 单元测试的 代码:

package com.ssm.test;

import com.ssm.mapper.CustomerMapper;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import
        org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ssm.po.Customer;

    @Test
    public void findCustomerByIdMapperTest(){
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
        CustomerMapper customerMapper = act.getBean(CustomerMapper.class);
        // 与传统的主要区别 在这里 不用再指定映射文件全路径了!!!
        Customer customer = customerMapper.findCustomerById(1);
        System.out.println(customer);
    }
}

好了,基于MapperFactoryBean的开发就这样了。会有个感觉,这种方式有点儿“黑箱”,实际运行时,也很容易报错,暴露几个坑就会豁然开朗了:

第一个坑:Myabtis核心配置文件中关联的映射文件 的命名空间 一定 要与Spring配置中 mapperInterface 指定的接口路径严格一致!!!,这里就必须是 “com.ssm.mapper.CustomerMapper”
第二个坑:Spring的配置文件中 MapperFactoryBean 的bean下的 子元素 mapperInterface 指定的接口的名称要与Mybatis核心配置中关联的映射文件的名称严格一致!!!,比如这里指定了CustomerMapper接口,那么映射文件名就必须是CustomerMapper.xml
第三个坑:下面的单元测试 customerMapper.findCustomerById(1) 调用的方法名要与Myabtis关联的映射文件 写的什么select update insert delete ……的 id 要严格一致,否则找不到就报错了啊!;
第四个坑:就是参数类型了。首先, customerMapper.findCustomerById(1) 这个方法的传入参数数据类型,要与映射文件中 写的什么select update insert delete ……的 parameterType属性 指定的数据类型一致;且 customerMapper.findCustomerById(1) 的返回类型要与 映射文件中 每个sql的resultType 指定的数据类型一致!!!


(2)基于MapperScannerConfigurer的整合开发:

对于Spring框架的配置,很多人应该有一个认识了,就是一开始肯定会在Spring配置文件中以 bean 的方式 注入,然后获取使用;然后随着项目扩展会让Spring配置文件无法直视,然后就开始了向注解开发方式的过渡,所以 基于MapperScannerConfigurer 的方式就是,避免Spring配置文件太臃肿 将 基于MapperFactoryBean 开发方式 转为注解开发方式。

这是Spring配置文件applicationContext.xml文件的改变(与基于 MapperFactoryBean的开发相比,也就只有这里有变化):
在这里插入图片描述

解释一下:
basePackage:指定映射接口文件所在的包路径,需要扫描多个包时,使用分号或逗号隔开就行。此时会扫描指定的包及其子包中所有文件;
除此之外,还有几个这里没用的属性(一般指定basePackage就可以了,了解就行):
annotationClass:指定了要扫描的注解名称,只有被注解标识的类才会被配置为映射器。
sqlSessionFactoryBeanName:指定在Spring中定义的SqlSessionFactory的Bean名称。
sqlSessionTemplateBeanName:指定在Spring中定义的SqlSessionTemplate的Bean名称。如果定义此属性,则sqlSessionFactoryBeanName将不起作用。
markerInterface:指定创建映射器的接口。

好了,基于MapperScannerConfigurer 的开发也完事了。

附加:
在上述的Spring的配置中,其实已经配置了事务管理,可以测试一下:

单元测试:

package com.ssm.test;

import com.ssm.po.Customer;
import com.ssm.service.CustomerService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 测试事务
 */
public class TransactionTest {
    public static void main(String[] args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
        CustomerService customerService = act.getBean(CustomerService.class);
        Customer customer = new Customer();
        customer.setUsername("zhangsan");
        customer.setJobs("manager");
        customer.setPhone("13233334444");
        customerService.addCustomer(customer);
    }
}

单元测试调用的Service层的CustomerServiceImpl 类:

package com.ssm.service.impl;

import com.ssm.mapper.CustomerMapper;
import com.ssm.po.Customer;
import com.ssm.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {
    //注解注入CustomerMapper
    @Autowired
    private CustomerMapper customerMapper;
    //添加客户
    public void addCustomer(Customer customer) {
        this.customerMapper.addCustomer(customer);
        int i=1/0; //模拟添加操作后系统突然出现的异常问题
    }
}

若Spring事务配置正确,将不会把该条数据插入到数据库中。


综上,来讨论一下,传统方法 与 非传统方法 优缺点:

传统的基于SqlSessionDaoSupport类 开发,可以实现几乎所有功能 了,但是这种方式,会产生大量的冗余代码,随着项目的扩展,只要对自己有要求的同胞们会觉得越来越恶心,一开始的动脑子的活慢慢变成体力活了,对后期维护,就更加恶心了,且出错率越来越高,指不定在改的时候,就遗忘了一处,就需要重新打包了。。。。

附件1:项目的pom.xml(说明一下引入的众多依赖包们):

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值