zoukankan      html  css  js  c++  java
  • springboot整合mybatis并设置多数据源

    现在springboot的火热程度已经超过了spring了,因为springboot简单快速方便,springboot的初衷就是为了简化spring的配置,是的开发中集成新功能时更快,简化或者减少相关的配置。springboot的基础是“约定大于配置”。整合了所有的框架,可以把springboot当作一个框架集合。
    我们来看看spring官网对springboot的特点的描述:
         1. 创建独立的Spring应用程序
         2.直接嵌入Tomcat、Jetty或Undertow(不需要部署WAR文件)
         3.提供自以为是的“starter”依赖项以简化构建配置
         4.尽可能自动配置Spring和第三方库
         5.提供生产就绪功能,如度量、运行状况检查和外部化配置
         6.完全没有代码生成,也不需要XML配置(重点)

    今天来介绍下springboot整合mybatis。

    一.springboot项目的搭建

      1.springboot项目的创建

        2.springboot跳转页面,这里跟spring是差不多的。

        @RestController
        public class HelloController {
    
            @RequestMapping(value = "/hello")
            public String hello(){
                return "index";
            }
        }
        这里的返回的"index"默认位于resources/static下的。
    当springboot启动的时候,我们可以看到这两行: Tomcat initialized with port(s):
    8080 (http) 这一行说明springboot的默认端口为8080。
    也可以在application.propertices(application.yml)里面配置: server: port:
    8088 Starting Servlet engine: [Apache Tomcat/9.0.31] 这一行说明springboot内置的tomcat的版本。

       这样启动springboot项目后,在浏览器地址栏上输入localhost:8080/hello。就可以打开一个页面。

    二.springboot整合mybatis

         本文不使用application.properties文件 而使用更加简洁的application.yml文件。将resource文件夹下原有的application.properties文件删除,创建application.yml配置文件(备注:其实SpringBoot底层会把application.yml文件解析为application.properties),
         .yml和.properties没什么区别,差异在于yml会有层级的划分,并且注意在冒号:后面要有空格.
         在这里是使用的@MapperScan注解来,而不是用的mybatisConfig.xml配置mybatis的。

        1.配置数据源,在application.yml的配置文件中。

    spring:
       datasource:
          driver-class-class: com.mysql.jdbc.Driver
          ## type: com.zaxxer.hikari.HikariDataSource
          jdbcUrl: jdbc:mysql://localhost:3306/zj?serverTimezone=GMT%2B8
          username: root
          password: root

        2.配置mybaits的mapper路径

    mybatis:
            mapper-locations: classpath:mapping/*.xml

       3.mapper接口

      public interface UserMapper {
    
              /***
               * 根据主键id查询用户
               * @param id
               * @return
               */
              User selectByPrimaryKey(Integer id);
      }  

        4.user的实体这里就不说了,这个很容易
        5.在resources下面创建一个mapping/UserMapper.xml文件,这里的路径是对应上面第二部配置的mybatis的mapper路径的。mapper.xml的namespace就是mapper类的全类名。

    <?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="cn.seven.demo.dao.UserMapper">
         <resultMap id="baseResultMap" type="cn.seven.demo.entity.User">
              <id column="id" jdbcType="INTEGER" property="id"></id>
              <result column="realName" jdbcType="VARCHAR" property="realName"></result>
              <result column="username" jdbcType="VARCHAR" property="username"></result>
              <result column="sex" jdbcType="INTEGER" property="sex"></result>
         </resultMap>
         <!--根据主键查询值-->
         <select id="selectByPrimaryKey" parameterType="java.lang.Integer"  resultMap="baseResultMap">
               select * from T_USER where id = #{id}
         </select>
    
    </mapper>

         6.mybatis的测试类

    @SpringBootTest(classes = SpringbootdemoApplication.class)
    @RunWith(SpringRunner.class)//让测试运行于Spring测试环境
    public class MybatisTest {
    
         @Resource
         private UserMapper userMapper;
    
         @Test
         public void test(){
              User user = userMapper.selectByPrimaryKey(1);
              System.out.println(user);
         }
    }

          到这里springboot整合mybatis就完成了。就是这么简单。

    三.配置mybatis多数据源

         1. 配置MySQL多数据源

           spring:
                datasource:
                  master:
                    driver-class-class: com.mysql.jdbc.Driver
                    type: com.zaxxer.hikari.HikariDataSource
                    jdbcUrl: jdbc:mysql://localhost:3306/zj?serverTimezone=GMT%2B8
                    username: root
                    password: root
                  slave:
                    driver-class-class: com.mysql.jdbc.Driver
                    type: com.zaxxer.hikari.HikariDataSource
                    jdbcUrl: jdbc:mysql://localhost:3307/zj?serverTimezone=GMT%2B8
                    username: root
                    password: root

         2.由于是多数据源,所以在pringboot都启动类(*Application.java)上需要禁用默认得数据源组件

      //禁用默认的数据源组件
       @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

         3.需要自己创建一个动态数据源的组件,这里我创建的是mybatisConfig.java类;

              @Configuration
              @MapperScan(basePackages = "cn.seven.demo.dao")//扫瞄DAO的包
              @Slf4j
              public class MybatisConfig {
    
                  /**
                   * 创建主数据源
                   * @return
                   */
                  @Bean("master")
                  @Primary //设置优先级
                  @ConfigurationProperties("spring.datasource.master") //配置属性文件
                  public DataSource master(){
                      return DataSourceBuilder.create().build();//builder建造者模式
                  }
    
                  /**
                   * 创建从数据源
                   * @return
                   */
                  @Bean("slave")
                  @Primary
                  @ConfigurationProperties("spring.datasource.slave")
                  public DataSource slave(){
                      return DataSourceBuilder.create().build();
                  }
    
                  /**
                   * 生成自定义的数据源
                   * @return
                   */
                  @Bean("dynamicDataSource")
                  public DataSource dynamicDataSource(){
                      DynamicDataSource dynamicDataSource = new DynamicDataSource();
                      Map<Object,Object>  mapDataSource = new HashMap<Object,Object>(2);
                      mapDataSource.put("master",master());
                      mapDataSource.put("slave",slave());
                      //将master数据源作为指定的数据源
                      dynamicDataSource.setDefaultDataSource(master());
                      //将master和slave数据源作为指定的数据源
                      dynamicDataSource.setDataSource(mapDataSource);
                      return dynamicDataSource;
                  }
    
                  @Bean
                  public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
                      SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
                      //配置数据源,此处配置为关键配置,如果没有将dynamicDataSource作为数据源则不能实现切换
                      sessionFactoryBean.setDataSource(dynamicDataSource());
                      //扫描model-entity的包
                      sessionFactoryBean.setTypeAliasesPackage("cn.seven.demo.entity");
                      //扫描映射文件
                      PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
                      sessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapping/*.xml"));
                      return sessionFactoryBean;
                  }
    
                  /**
                   * 配置事务管理,使用事务时哎方法头部添加@Transactional注解即可
                   * @return
                   */
                  @Bean
                  public PlatformTransactionManager transactionManager(){
                      return new DataSourceTransactionManager(dynamicDataSource());
                  }
    
           }

            4.数据源的注解接口

    @Target({ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER})//设置注解的作用范围
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface DataSource {
    
        String value() default "master";
    }

         5.自定义的动态数据源

    public class DynamicDataSource extends AbstractRoutingDataSource {
        /**
         * 如果不希望数据源在启动配置时就加载好,可以定制这个方法,从任何你希望的地方读取并返回数据源,
         * 比如从数据库,文件,外部接口等读取数据源信息,并最终返回一个DataSource实现类对象即可
         * @return
         */
        @Override
        protected DataSource determineTargetDataSource() {
            return super.determineTargetDataSource();
        }
    
        /**
         * 如果希望所有的数据源在启动配置时加载好,这里通过设置数据源key值来切换数据源,定制这个方法
         * @return
         */
        @Override
        protected Object determineCurrentLookupKey() {
            return DynamicDataSourceContextHolder.getDataSourceKey();
        }
    
        /**
         * 设置默认的数据源
         * @param defaultDataSource
         */
        public void setDefaultDataSource(Object defaultDataSource){
            super.setDefaultTargetDataSource(defaultDataSource);
        }
    
        /**
         * 社渚数据源
         * @param dataSource
         */
        public void setDataSource(Map<Object,Object> dataSource){
            super.setTargetDataSources(dataSource);
            //将数据源的key放到数据源上下文的key集合中,用于切换时判断数据源是否有效
            DynamicDataSourceContextHolder.addDataSourceKey(dataSource.keySet());
        }
    }

        6.动态数据源上下文

    public class DynamicDataSourceContextHolder {
    
        /**
         * 用于存放数据源的本地线程
         */
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(){
            /**
             * 讲master数据源的key作为默认的数据源的key
             * @return
             */
            @Override
            protected String initialValue() {
               // return super.initialValue();//
                return "master";
            }
        };
    
        /**数据源的key集合,用于切换时判断数据源是否存在*/
        private static List<Object> dataSourceKey = new ArrayList<Object>();
    
        /**
         * @return the value of contextHolder
         */
        public static ThreadLocal<String> getContextHolder() {
            return contextHolder;
        }
    
        /**
         * @return the value of dataSourceKey
         */
        public static String getDataSourceKey() {
            return contextHolder.get();
        }
    
        /**
         * Sets the dataSourceKey
         *
         * @param dataSourceKey dataSourceKey
         */
        public static void setDataSourceKey(String dataSourceKey) {
            contextHolder.set(dataSourceKey);
        }
    
        /**
         * 重置数据源
         */
        public static void cleanDataSource(){
            contextHolder.remove();
        }
    
        /**
         * 判断是否包含数据源
         * @param key 数据源的key
         * @return yes no
         */
        public static boolean containDataSourceKey(String key){
            return dataSourceKey.contains(key);
        }
    
        /**
         * 添加数据源key,支持加多个,所以需要用collection
         * @param keys 数据源key
         * @return
         */
        public static boolean addDataSourceKey(Collection<? extends Object> keys){
            return dataSourceKey.addAll(keys);
        }
    }

       7.  动态数据源的切面类

    @Aspect
    @Order(-1) //优先于事务注解执行
    @Component
    @Slf4j
    public class DynamicDataSourceAspect {
    
        @Before("@annotation(dataSource)")
        public void switchDataSource(JoinPoint point,DataSource dataSource){
            if(!DynamicDataSourceContextHolder.containDataSourceKey(dataSource.value())){
                System.out.println("数据库不匹配 : "+ dataSource.value());
            }else{
                System.out.println("数据库切换 : "+ dataSource.value());
                DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value());
            }
        }
    
        /**
         *  清空数据源
         * @param point
         * @param dataSource
         */
        @After("@annotation(dataSource)")
        public void restoreDataSource(JoinPoint point,DataSource dataSource){
            DynamicDataSourceContextHolder.cleanDataSource();
            System.out.println("数据库连接清空:"+dataSource.value());
        }
    }

       8.注意mapper接口的userMapper的查询方法上设置:@DataSource("slave"),由于我们的默认数据库是master,所以这里需要设置成slave;

    /***
     * 配置多数据源  注解后面的表示方法
     * @param id
     * @return
     */
     @DataSource("slave")
     User selectByPrimaryKey(Integer id);
    同时由于在mybaitsConfig里写了扫描映射文件的代码:
    //扫描映射文件 PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); sessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapping/*.xml")); 所以需要将之前在yml文件里设置的读取mapper.xml文件的路径删除。

       9.使用上面的测试类测试

       到这,springboot整合mybatis并设置多数据源就已经完成了。

       欢迎大家下载源码:https://files.cnblogs.com/files/pluto-charon/springbootdemo.rar

  • 相关阅读:
    移动端开发 rem 案例
    html基值 仿淘宝
    使用FreeSWITCH做电话自动回访设置
    Nodejs 实现ESL内联FreeSWITCH设定说明
    ADC自动转接功能Lua实现
    sipML5聊天功能实现
    FreeSWITCH与PSTN对接
    FreeSWITCH Git版本管理
    FreeSWITCH Git版本管理
    SIP 认证
  • 原文地址:https://www.cnblogs.com/pluto-charon/p/12549521.html
Copyright © 2011-2022 走看看