zoukankan      html  css  js  c++  java
  • MapperFactoryBean和MapperScannerConfigurer的作用和区别

    在介绍这两个映射接口之前首先了解这两个接口的目的是啥:

    为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象(DAO)的代码,MyBatis-Spring 提供了一个动态代理的实现——MapperFactoryBean。这个类可以让你直接注入数据映射器接口到你的 service 层bean 中。当使用映射器时,你仅仅如调用你的 DAO 一样调用它们就可以了,但是你不需要编写任何 DAO 实现的代码,因为 MyBatis-Spring将会为你创建代理。同样,MapperFactoryBean创建的代理控制开放和关闭 session

    也就是说dao层的对数据访问对象被映射器直接注入到了service层,因此这个dao实现类就没必要写和注册了,从而简化操作,那么sqlsession也就不需要了吧。

    先详细回顾一下之前的spring的原生sqlsession方法,也就是使用到了dao实现层。

    方法一:使用SqlSessionTemplate生成Mapper

    需要先在spring-dao.xml里面注册

    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/student?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="datasource"/>
    <property name="configLocation" value="mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:com/bupt/dao/*.xml"/>
    </bean>

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <!-- 只能使用构造器注入sqlsessionfactory因为没有set方法 -->
    <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    dao层里面创建实现UserMapper的类

    package com.bupt.dao;
    
    import com.bupt.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper{
    
        private SqlSessionTemplate sqlSessionTemplate;
    
        public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
            this.sqlSessionTemplate = sqlSessionTemplate;
        }
    
        @Override
        public List<User> selectUser() {
            return sqlSessionTemplate.getMapper(UserMapper.class).selectUser();
        }
    
        @Override
        public int addUser(User user) {
            return 0;
        }
    
        @Override
        public int deleteUser(int id) {
            return 0;
        }
    }

    可以看到此时sqlSessionTemplate因为已经被注册到spring-dao.xml里面,通过set方法便可以直接获取sqlSessionTemplate对象,通过该对象生成Mapper调用相关的数据操作方法。

    方法二:继承SqlSessionDaoSupport生成Mapper

    该方法只需要继承SqlSessionDaoSupport类便可以直接获取sqlSession对象,因此不需要额外的注册Bean

    dao层里面创建实现UserMapper的类UserDaoImpl.java

    package com.bupt.dao;
    
    import com.bupt.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper {
    
    //   SqlSessionDaoSupport有一个getSqlSession方法可以直接获取一个sqlsession对象
        @Override
        public List<User> selectUser() {
            User user = new User(445,"小明","123456");
            UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
            mapper.addUser(user);
            mapper.deleteUser(444);
            return mapper.selectUser();
        }
    
        @Override
        public int addUser(User user) {
    
            return getSqlSession().getMapper(UserMapper.class).addUser(user);
        }
    
        @Override
        public int deleteUser(int id) {
            return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
        }
    }

    通过这两种方法在dao层里面封装了sqlsession对dao的操作,因此可以在service层里面去直接调用就可以操作数据库了,不过要先把上面的两种方法注册到spring里面ApplicationContext.xml

        <bean id="userMapper" class="com.bupt.dao.UserMapperImpl">
            <property name="sqlSessionTemplate" ref="sqlSession"/>
        </bean>
    
        <bean id="userDao" class="com.bupt.dao.UserDaoImpl">
            <property name="sqlSessionFactory" ref="sqlSessionFactory" />
        </bean>

    先写个测试看一下

        @Test
        public void test04(){
            ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            UserMapper userMapper = classPathXmlApplicationContext.getBean("userMapper", UserMapper.class);
            for (User user : userMapper.selectUser()) {
                System.out.println(user);
            }
        }
    
        @Test
        public void test05(){
            ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            UserMapper userMapper = classPathXmlApplicationContext.getBean("userDao", UserMapper.class);
            for (User user : userMapper.selectUser()) {
                System.out.println(user);
            }
        }
     

    可以看到这两种方法都是spring的生成sqlsession获取Mapper操作dao方法的两种对策,但是spring也提供了进一步的封装技术,也就是不需要显示的去获取sqlsession操作dao,MapperFactoryBean就是其中

    一个技术。

    方法三:MapperFactoryBean封装sqlsession

    mybatis-config.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>
    
        <typeAliases>
            <package name="com.bupt.pojo"/>
        </typeAliases>
    
    <!--    这个文件放别名和setting-->
    </configuration>

    spring-dao.xml

    <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="user" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
    
            <property name="maxPoolSize" value="30"/>
            <property name="minPoolSize" value="10"/>
            <property name="autoCommitOnClose" value="false"/>
            <property name="checkoutTimeout" value="10000"/>
    
            <property name="acquireRetryAttempts" value="2"/>
         </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    
            <property name="dataSource" ref="datasource"/>
    
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>
    <bean id="bookMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.bupt.dao.BookMapper"/>
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
     </bean>

    通过注册MapperFactoryBean我们就不要去写Mapper接口的实现类(也就是封装了sqlsession的使用),就可以直接在service里面进行使用,dao里面只需要BookMapper接口和对应的sql操作的xml文件

    在service层里面可以直接通过set方法注入dao里面的接口,通过接口对象直接使用操作数据库的方法

    BookService接口

    package com.bupt.service;
    
    import com.bupt.pojo.Books;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface BookService {
        //增加一个Book
        int addBook(Books book);
        //根据id删除一个Book
        int deleteBookById(int id);
        //更新Book
        int updateBook(Books books);
        //根据id查询,返回一个Book
        Books queryBookById(int id);
        //查询全部Book,返回list集合
        List<Books> queryAllBook();
    
        List<Books> queryBookByName(@Param("bookName") String bookname);
    }

    BookServiceImpl实现类

    package com.bupt.service;
    
    import com.bupt.dao.BookMapper;
    import com.bupt.pojo.Books;
    
    import java.util.List;
    
    public class BookServiceImpl implements BookService{
    
        //调用dao层的操作,设置一个set接口,方便Spring管理
        private BookMapper bookMapper;
    
        public void setBookMapper(BookMapper bookMapper) {
            this.bookMapper = bookMapper;
        }
    
        public int addBook(Books book) {
            return bookMapper.addBook(book);
        }
    
        public int deleteBookById(int id) {
            return bookMapper.deleteBookById(id);
        }
    
        public int updateBook(Books books) {
            return bookMapper.updateBook(books);
        }
    
        public Books queryBookById(int id) {
            return bookMapper.queryBookById(id);
        }
    
        public List<Books> queryAllBook() {
            return bookMapper.queryAllBook();
        }
    
        @Override
        public List<Books> queryBookByName(String bookname) {
            return bookMapper.queryBookByName(bookname);
        }
    
    }

    然后把service层进行注入到bean里面

    在spring-service.xml里面(其中bookMapper已经被自动注册)

        <!-- 扫描service相关的bean -->
        <context:component-scan base-package="com.bupt.service" />
    
        <!--BookServiceImpl注入到IOC容器中-->
        <bean id="BookServiceImpl" class="com.bupt.service.BookServiceImpl">
    <property name="bookMapper" ref="bookMapper"/> </bean>

    这样就可以直接在control里面使用该service

     @Resource(name = "BookServiceImpl")
        private BookService bookService;
        @RequestMapping("/allBook")
        public String list(Model model){
            List<Books> books = bookService.queryAllBook();
            model.addAttribute("list",books);
            return "allbook";
    
        }

    关于MapperFactoryBean底层的东西可以看这篇文章:https://www.cnblogs.com/Joe-Go/p/10256241.html

    但是MapperFactoryBean的一个问题是每个接口我们都需要注册一下,是不是很麻烦。需要用到的映射器较多的话,采用这种配置方式就会很低效。为了解决这个问题,我们可以使用MapperScannerConfigurer,让它扫描特定的包,自动帮我们成批的创建映射器。这样一来,就能大大减少配置的工作量。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <property name="basePackage" value="com.bupt.dao"/>
    </bean>

    其他的相关操作就是和方法三一样,但是由于扫描包的存在可以对包里面的所有接口直接注入,很是方便。

    作者:你的雷哥
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    《移动WEB前端高级开发实践@www.java1234.com.pdf》【2】
    《生鲜零售智能化之路》
    房屋布局分析《Physics Inspired Optimization on Semantic Transfer Features: An Alternative Method for Room Layout Estimation》
    《2018:skymind.ai 发布了一份非常全面的开源数据集》
    Flask/Tornado/Django
    《特征提取与图像处理》
    《icra16_slam_tutorial_tardos.pdf》
    《3D_Deep_Learning_for_Robot_Perception.pdf》
    《深度访谈:华为开源数据格式 CarbonData 项目,实现大数据即席查询秒级响应》
    数据库性能测试
  • 原文地址:https://www.cnblogs.com/henuliulei/p/14647420.html
Copyright © 2011-2022 走看看