springboot整合mybatis並設置多數據源

来源:https://www.cnblogs.com/pluto-charon/archive/2020/03/22/12549521.html
-Advertisement-
Play Games

現在springboot的火熱程度已經超過了spring了,因為springboot簡單快速方便,springboot的初衷就是為了簡化spring的配置,是的開發中集成新功能時更快,簡化或者減少相關的配置。springboot的基礎是“約定大於配置”。整合了所有的框架,可以把springboot當 ...


現在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 List<Object> getDataSourceKey() {
        return dataSourceKey;
    }

    /**
     * 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.add(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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 簡單工廠模式:將調用者和創建者分離,實現解耦,調用者直接向工廠請求,通過工廠去選擇需要實例化的對象,用一個單獨的類來做這個創建實例的過程。 代碼實例: 問題:假設一個關於個人事務管理的項目中有許多類型的對象,其中一個是 Appointment 對象,現在需要通過一種稱為 BloggsCal ...
  • Spring Boot 是微服務中最好的 Java 框架. 我們建議你能夠成為一名 Spring Boot 的專家。本文精選了三十五個常見的Spring Boot知識點,祝你一臂之力! 問題一 Spring Boot、Spring MVC 和 Spring 有什麼區別? 1、Spring Sprin ...
  • 一、Harbor安裝環境要求 硬體環境: 1)CPU 2核以上,最好4核以上 2)記憶體4G以上,最好8G以上 3)硬碟空間至少40G,最好160G以上 軟體環境: 1)docker v17.06以上版本 2)docker compose v1.18.0以上版本 3)Openssl 更新到最新版(一般 ...
  • selenium基本操作 概念:基於瀏覽器自動化的模塊 :基於手機自動化的模塊的應用 環境的安裝 跟爬蟲之間的關聯? 可以實現模擬登陸 便捷的捕獲動態載入數據(可見即可得) 基本操作 導包: (web瀏覽器,driver驅動) 必須提供對應瀏覽器的驅動程式(谷歌,火狐...) "谷歌瀏覽器驅動下載地 ...
  • 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 876. 鏈表的中間結點 題目 給定一個帶有頭結點 head 的非空單鏈表,返回鏈表的中間結點。 如果有兩個中間結點,則返回第二個中間結點。 示例 1: ...
  • JSP+MySQL+Java開發ssh網上預約預約掛號系統的設計與實現 需求使用SSH框架(spring+struts2+hibernate)實現一個網上預約預約掛號系統, 用戶登錄註冊登錄系統, 能按科室查看醫生, 並能夠進行預約掛號和線上留言, 後臺管理系統更能夠進行科室管理,醫生管理,預約管理 ...
  • 一、java.io.DataOutputStream;數據位元組輸出流 1.可以將記憶體中的“int i = 2;"寫入到硬碟文件裡面,寫進去的不是字元串,寫進去的是二進位數據,可以帶有類型。 package com.bjpowernode.java_learning; import java.io.* ...
  • 以前看到過NSQ這個東西,也一直沒去看。今天剛好有時間就搭建了下,簡單嘗試了下這個Go語言下的消息隊列NSQ,我這裡簡要記錄下。 其實,NSQ國內用的是比較少的,我這裡也是算瞭解這麼個東西吧 ,稍微看下源碼,學到東西而已。 NSQ簡介 NSQ是一個基於Go語言的分散式實時消息平臺, 它具有分散式、去 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...