• (十四)mybatis 和 spring 整合


    目录


    整合思想

    1. spring 管理 sqlSessionFactory ,使用 单例模式 创建该对象 ;

    2. 根据 sqlSessionFactory 创建 sqlsession ,这一步由mybatisspring 整合 以后,自动完成,不需要我们配置 ;

    3. Mapper 接口的代理对象 ,由 spring 管理这些代理对象 ;


    整合步骤

    1. 导包

      导入 springmybatis 的包

      导入 mybatis-spring 整合包 ;


    2. 搭建工程目录

      需要注意的一点,就是在创建包的时候,为 mybatisspring 都创建各自的配置文件包,便于管理 ;


    3. 导入 springmybatis 的配置文件

      其中注意,mybatis 的配置文件中的 environments 标签的内容在和 spring 整合以后,就被废弃了,也就是不再起作用了;

      也就是 数据源事务,最后都由 spring 进行管理了 ;

      废弃的 environments 标签内容 :

      <!--当和 spring 整合以后,environments 配置将废除-->
      <environments default="development">
          <environment id="development">
              <!--事务管理,暂时有mybatis管-->
              <transactionManager type="JDBC"/>
              <!--数据源 暂时也由 mybatis 管理,以后都由 spring 来管理-->
              <dataSource type="POOLED">
                  <property name="driver" value="${jdbc.driver}"/>
                  <property name="url" value="${jdbc.url}"/>
                  <property name="username" value="${jdbc.username}"/>
                  <property name="password" value="${jdbc.password}"/>
              </dataSource>
          </environment>
      </environments>

    4. spring 中管理 sqlSessionFactory

      sqlSessionFactory 不是我们在 mybatis 中使用的那个接口,而是在 mybatis-spring SqlSessionFactoryBean

      SqlSessionFactoryBean 类部分源码:

      public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
              private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
              // 读取mybatis配置文件使用的资源流
              private Resource configLocation;
              .....
              // 读取数据源
              private DataSource dataSource;
              ....
      
      }
      

      我们可以发现,它的属性有 数据源资源流 ,因此,我们在 spring 中的配置的时候,就需要往相关的属性上赋值了 ;

      spring 中配置 sqlSessionFactory

      <!--配置 sqlSessionFactory-->
      <!--
          class :在 mybatis-spring 整合包里面
      -->
      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          <!--设置读取 mybatis 配置文件的资源流-->
          <property name="configLocation"  value="xin/ijava/config/mybatis/sqlMapConfig.xml"/>
          <!--设置数据源,引用下面配置的数据源对象-->
          <property name="dataSource" ref="dataSource"/>
      </bean>
      
      <!--读取数据库的配置文件-->
      <content:property-placeholder location="classpath:xin/ijava/config/mybatis/db.properties" />
      
      <!--配置 DBCP  数据源-->
      <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
          <property name="driverClassName" value="${jdbc.driver}"/>
          <property name="url" value="${jdbc.url}"/>
          <property name="username" value="${jdbc.username"/>
          <property name="password" value="${jdbc.password"/>
          <property name="maxOpenPreparedStatements" value="10"/>
          <property name="maxIdle" value="5"/>
      </bean>

    整合之后原始 dao 开发

    1. 开发接口

      跟之前 mybatis 的原始开发一样,需要写接口 ;


    2. 配置映射关系文件

      和之前单独使用 mybatis 开发是一样的 ;


    3. 开发实现类

      跟之前 mybatis 的原始开发一样,写接口的实现类 ;


    4. 让实现类继承 SqlSessionDaoSupport不同点

      继承以后,我们不再需要写上 sqlSessionFactory 属性了,因为,在继承类中,有这个属性

      获取 SqlSession 使用 this.getSqlSession()

      并且,不再需要我们自己手动去关闭 sqlSession

      /**
      *  @author An
      */
      public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao{
      
          @Override
          public void insertUser(User user) throws Exception {
              SqlSession sqlSession = this.getSqlSession() ;
              sqlSession.insert("test.insertUser",user) ;
      
          }
      

    5. spring 中配置 userDao 对象

      传入 sqlSessionFactory 对象 ;

      <!--配置 UserDao-->
      <bean id="userDao" class="xin.ijava.dao.UserDaoImpl">
          <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
      </bean>
      

    6. 测试代码

      public class UserDaoImplTest {
              private ApplicationContext context ;
              @Before
              public void setUp() throws Exception {
                  context = new ClassPathXmlApplicationContext("xin/ijava/config/spring/application.xml");
              }
              @Test
              public void findUserById() throws Exception {
                  UserDaoImpl userDao = (UserDaoImpl) context.getBean("userDao");
                  User user = userDao.findUserById(1) ;
                  System.out.println(user);
              }
      }

    7. 查看控制台输出

        [service] 2018-09-12 17:26:22,538 - xin.ijava.dao.UserMapper.findUserById -8617 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==>  Preparing: select * from User where id = ? 
        [service] 2018-09-12 17:26:22,720 - xin.ijava.dao.UserMapper.findUserById -8799 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - ==> Parameters: 1(Integer)
        [service] 2018-09-12 17:26:22,806 - xin.ijava.dao.UserMapper.findUserById -8885 [main] DEBUG xin.ijava.dao.UserMapper.findUserById  - <==      Total: 1
        [service] 2018-09-12 17:26:22,815 - net.sf.ehcache.store.disk.Segment -8894 [main] DEBUG net.sf.ehcache.store.disk.Segment  - put added 0 on heap
        [service] 2018-09-12 17:26:22,824 - org.mybatis.spring.SqlSessionUtils -8903 [main] DEBUG org.mybatis.spring.SqlSessionUtils  - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6dd93e5f]
        [service] 2018-09-12 17:26:22,824 - org.springframework.jdbc.datasource.DataSourceUtils -8903 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Returning JDBC Connection to DataSource
        User : name = 张三,id = 1

      只要看到这个输出,就说明 mybatisspring 整合成功 !!


    整合之后 Mapper 代理开发

    1. 配置 xxxMapper.xml 映射关系文件

      跟之前 mybatis 的原始开发一样;


    2. 开发接口

      跟之前 mybatis 的原始开发一样,需要写接口 ;


    3. spring 创建代理对象

      spring 的配置文件中,进行配置 ;

      如果传入的 class 是整合包中的 MapperFactoryBean

      这种方式,需要为每一个接口,都配置一次 ;

       <!--配置映射文件代理对象-->
          <!--
              让 spring 创建代理对象。
          -->
          <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
              <!--依然需要传入 sqlSessionFactory -->
              <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
              <!--传入接口,告诉它为我们创建哪一个接口的代理对象-->
              <property name="mapperInterface" value="xin.ijava.dao.UserCustomerMapper"/>
          </bean>

      如果传入的 class 是整合包中的 MapperScannerConfigurer

      这种方式,会批量的扫描接口,我们只需要配置这一次 ;

      注意,这里传 sqlSessionFactory 进去的时候,使用的是 sqlSessionFactoryBeanName

       <!--扫描包下的所有接口,一次性生成诸多代理对象,并在 spring 中注册-->
          <!--自动创建的代理对象的 id 为 类名字(首字母小写,必须小写)-->
          <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
              <!--配置包名 -->
              <!--要是扫描多个包,中间用逗号隔开-->
              <property name="basePackage" value="xin.ijava.dao"/>
              <!--依然传入  sqlSessionFactory-->
              <!--value  的值是之前配置的 SqlSessionFactory 的 id-->
              <!--这里 name 不能写 sqlSessionFactory ,因为这里先执行;
              假如写为sqlSessionFactory属性,那么上面配置的加载数据库配置文件的配置,将不会得到执行 -->
              <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
           </bean>

      如果使用了批量注册注册 mapper ,那么 mybatis 的配置文件中就 不再需要进行 mapper.xml 的扫描;

      对了,这里有个坑,除了使用 sqlSessionFactoryBeanName 代替 sqlSessionFactory;还需要去掉开头的 default-autowire="byName"


    4. 使用批量加载的方法的测试代码

      public class UserCustomerMapperTest {
          private ApplicationContext context ;
          @Before
          public void setUp() throws Exception {
              context = new ClassPathXmlApplicationContext("xin/ijava/config/spring/application.xml");
          }
      
      
          @Test
          public void findOrderUsers() throws Exception {
      
              UserCustomerMapper userCustomerMapper  = (UserCustomerMapper) context.getBean("userCustomerMapper");
              List<UserCustomer> userCustomers = userCustomerMapper.findOrderUsers();
              System.out.println(userCustomers);
          }
      }

    5. 测试结果

      [service] 2018-09-12 20:25:02,662 - org.mybatis.spring.transaction.SpringManagedTransaction -8640 [main] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction  - JDBC Connection [1728792864, URL=jdbc:mysql:///mybatisDay01?charset=utf-8, UserName=root@localhost, MySQL Connector Java] will not be managed by Spring
      [service] 2018-09-12 20:25:02,684 - xin.ijava.dao.UserCustomerMapper.findOrderUsers -8662 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrderUsers  - ==>  Preparing: SELECT `order`.* ,`user`.`name` ,`user`.sex FROM `order`,`user` WHERE `user`.id = `order`.user_id 
      [service] 2018-09-12 20:25:02,818 - xin.ijava.dao.UserCustomerMapper.findOrderUsers -8796 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrderUsers  - ==> Parameters: 
      [service] 2018-09-12 20:25:02,927 - xin.ijava.dao.UserCustomerMapper.findOrderUsers -8905 [main] DEBUG xin.ijava.dao.UserCustomerMapper.findOrderUsers  - <==      Total: 4
      [service] 2018-09-12 20:25:02,937 - org.mybatis.spring.SqlSessionUtils -8915 [main] DEBUG org.mybatis.spring.SqlSessionUtils  - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1c3bf543]
      [service] 2018-09-12 20:25:02,937 - org.springframework.jdbc.datasource.DataSourceUtils -8915 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Returning JDBC Connection to DataSource
      [User : name = 朱小明,id = 0, User : name = 张三,id = 0, User : name = 张小明,id = 0, User : name = 张三,id = 0]

      只要控制台出现了我们打印的对象,就说明 mybatis 和 spring 整合成功 !!


    总结

    我们发现,其实无论是 原始开发,还是 mapper 代理,接口映射关系文件,都少不了!

  • 相关阅读:
    【POJ
    【POJ
    【POJ
    【POJ
    【POJ
    【POJ
    【POJ
    【POJ
    NAT
    OSPF与ACL综合实验
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665666.html
Copyright © 2020-2023  润新知