DB數據源之SpringBoot+MyBatis踏坑過程(二)手工配置數據源與加載Mapper.xml掃描


DB數據源之SpringBoot+MyBatis踏坑過程(二)手工配置數據源與加載Mapper.xml掃描

liuyuhang原創,未經允許進制轉載 

 

 

吐槽之后應該有所改了,該方式可以作為一種過渡方式來使用。

 

系列目錄連接

DB數據源之SpringBoot+Mybatis踏坑過程實錄(一)

 

1.環境說明

  • 初次使用springboot,時間有限,需要迅速搭建好架構,沒有時間研究
  • 使用springboot過程中數據源無法獲取;
  • 使用springboot過程中注解莫名其妙失效;
  • 用springboot過程中因為版本不懂,不掃描application.properties;
  • 使用springboot過程中因為版本不懂,不掃描mybatis的mapper.xml包;
  • springboot或spring注解使用十分不習慣或者還沒有來得及深入學習的情況;

 

  假設有以上問題,又時間緊迫,建議使用本文手工配置方式!!

  springboot,parent 2.0.2.和1.5.3.都已經測試過,

  在java8和java7環境下測試過。前者配java8,后者配java7,

  使用MyEclipse 2017 C1 64x,MyEclipse 2016之前的版本無法使用java8

  pom.xml核心如下:

 

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
<!-- 添加MySQL依賴 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 添加JDBC依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- mybaits基礎依賴 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.0</version>
        </dependency>
        <!-- mybatis插件依賴 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- mapper依賴 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.3.7</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

 

2.配置思路

 

  2.1.手工獲取application.properties文件中的屬性;

  2.2.創建數據源DataSource;

  2.3.注入數據源屬性;

  2.4.創建SqlSessionFactory;

  2.5.SqlSessionFactory配置DataSource;

  2.6.SqlSessionFactory配置掃描MyBatis-config.xml文件;

  2.7.SqlSessionFactory配置掃描Mapper.xml所在包;

  2.8.獲取session查詢數據庫進行測試;

 

3.所需類與結構

  3.0.application.properties文件與相應內容作為數據源;

  3.1.SysConfig類,用於獲取application.properties中的property;

  3.2.DataConfig類,用於獲取SqlSessionFactory;

  3.3.ExampleController類,用於測試;

  3.4.AppRun類,springboot的啟動入口,將DataConfig初始化;

  3.5.mapper.xml內容

 

4.代碼 

 

  4.0.application.properties部分內容段落:

  

1 master.url=jdbc:mysql://qqq.jjj.xxx.iii:3306/master?characterEncoding=utf8
2 master.username=root
3 master.password=root
4 master.driver=com.mysql.jdbc.Driver
5 #master.driver-class-name=com.mysql.jdbc.Driver  一般是使用這個命名模式

  

  4.1.SysConfig類,代碼如下:

 

 1 package com.FM.config;
 2 
 3 import java.io.IOException;
 4 import java.util.Properties;
 5 
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.core.io.ClassPathResource;
 8 import org.springframework.core.io.Resource;
 9 import org.springframework.core.io.support.PropertiesLoaderUtils;
10 
11 /**
12  * 用於讀取properties的類,基礎配置文件名為application.properties,置於resources根目錄下
13  * @author Liuyuhang
14  */
15 public class SysConfig {
16 
17     private Properties properties;
18 
19     /**
20      * 修改無參構造,默認該類實例化的時候,加載配置文件中的內容,不做單例,因為配置文件可能更改
21      */
22     public SysConfig() {
23         try {
24             Resource resource = new ClassPathResource("/application.properties");
25             properties = PropertiesLoaderUtils.loadProperties(resource);
26         } catch (IOException e) {
27             e.printStackTrace();
28         }
29     }
30 
31     /**
32      * 獲取屬性,傳入參數key
33      */
34     public String getProperty(String key) {
35         return properties.getProperty(key);
36     }
37 }

 

  4.2.DataSourceConfig類,代碼如下:

 

 1 package com.FM.config;
 2 
 3 import java.util.HashMap;
 4 
 5 import javax.sql.DataSource;
 6 
 7 import org.apache.ibatis.session.SqlSessionFactory;
 8 import org.mybatis.spring.SqlSessionFactoryBean;
 9 import org.springframework.boot.jdbc.DataSourceBuilder;
10 import org.springframework.core.io.DefaultResourceLoader;
11 import org.springframework.core.io.Resource;
12 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
13 /**
14  * DataConfig,獲取數據源,配置給SqlSessionFactory,並以此獲取session
15  * 
16  * @author liuyuhang
17  */
18 public class DataConfig {
19     /**
20      * 緩存factory的map,作為單例SessionFactory存儲
21      */
22     public static HashMap<String, SqlSessionFactory> factoryMap = new HashMap<String, SqlSessionFactory>();
23 
24     /**
25      * 構造器對緩存中的factory只實例化一次
26      * 不保證該單例能順利執行,若看出問題,自行更改
27      * @throws Exception
28      */
29     public DataConfig() {
30         System.out.println("out init sessionFactory:" + factoryMap);
31         if (factoryMap.isEmpty()) {
32             synchronized (factoryMap) {
33                 if (factoryMap.isEmpty()) {
34                     try {
35                         SqlSessionFactory sessionFactory = getSessionFactory();
36                         factoryMap.put("master", sessionFactory);
37                         System.out.println("in init sessionFactory:" + factoryMap);
38                     } catch (Exception e) {
39                         System.out.println("該錯誤比較嚴重,出現在數據源無參構造函數中!!");
40                         e.printStackTrace();
41                     }
42 
43                 }
44             }
45 
46         }
47 
48     }
49 
50     /**
51      * 手動獲取sessionFactory用例
52      * @param dataSourcePerfix
53      * @return
54      * @throws Exception
55      */
56     public SqlSessionFactory getSessionFactory() throws Exception {
57         SysConfig sc = new SysConfig();
58         String masterUrl = sc.getProperty("master.url");
59         String masterDriver = sc.getProperty("master.driver");
60         String masterUsername = sc.getProperty("master.username");
61         String masterPassword = sc.getProperty("master.password");
62         // 創建數據源
63         DataSourceBuilder create = DataSourceBuilder.create();
64         create.url(masterUrl);
65         create.driverClassName(masterDriver);
66         create.username(masterUsername);
67         create.password(masterPassword);
68         DataSource source = create.build();
69         // 創建sessionFactory
70         SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
71         factoryBean.setDataSource(source);// 加載數據源
72         // 掃描mapper.xml
73         Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:com/FM/mapper/*.xml");
74         factoryBean.setMapperLocations(resources);
75         // 讀取config
76         factoryBean.setConfigLocation(new DefaultResourceLoader().getResource("classpath:mybatis-config.xml"));
77         SqlSessionFactory sessionFactory = factoryBean.getObject();
78         return sessionFactory;
79     }
80 
81 }

 

  4.3.ExampleController類,代碼如下:

 

 1  package com.FM.controller;
 2  
 3  import java.util.HashMap;
 4  import java.util.List;
 5  import java.util.Map;
 6  
 7  import javax.servlet.http.HttpServletRequest;
 8   
 9  import org.apache.ibatis.session.SqlSession;
10  import org.apache.ibatis.session.SqlSessionFactory;
11  import org.springframework.web.bind.annotation.RequestMapping;
12  import org.springframework.web.bind.annotation.RestController;
13  
14  import com.FM.config.DataConfig;
15  
16 /**
17  * Controler用於測試
18  * @author liuyuhang
19  */
20  @RestController //等同於responseBody + controller雙重注解
21  public class ExampleController {
22  
23      /**
24       * 手動創建session查詢數據庫用例,該方法可以創建多個sessionFactory,用多線程
25       * @param request
26       * @return
27       * @throws Exception
28       */
29      @RequestMapping("/helloMybatis")
30      public List helloMybatis(HttpServletRequest request) throws Exception {
31          //數據源配置無參構造器
32          DataConfig dc = new DataConfig();
33          SqlSessionFactory sessionFactory = dc.getSessionFactory();//獲取sessionfactory
34          SqlSession session = sessionFactory.openSession();//獲取session
35          List<Object> selectList = session.selectList("com.FM.mapper.MySqlMapper.getUser");
36          return selectList;//自動轉換為json
37      }
38 }

 

  4.4.AppRun類,代碼如下:

 

 1 package com.FM;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.SpringBootConfiguration;
 5 import org.springframework.boot.autoconfigure.SpringBootApplication;
 6 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 7 import org.springframework.boot.web.servlet.ServletComponentScan;
 8 
 9 import com.FM.config.DataConfig;
10 
11 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) // 禁用默認的單數據源配置
12 @SpringBootConfiguration // springboot基礎配置注解
13 @ServletComponentScan // springboot servlet filter
14 // @EnableConfigurationProperties//該注解於springboot1.5以上廢棄
15 public class AppRun {
16 
17     public static void main(String[] args) throws Exception {
18         SpringApplication.run(AppRun.class, args);
19         DataConfig dc = new DataConfig();//初始化配置
20         
21     }
22 }

 

  4.5.mapper.xml內容

 

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 3 <mapper namespace="com.FM.mapper.MySqlMapper">
 4 <!-- 隨便寫作為測試而已 -->
 5     <resultMap id="getUserMap" type="java.util.Map">
 6         <result column="id" property="id" jdbcType="INTEGER" javaType="int" />
 7         <result column="username" property="username" jdbcType="VARCHAR" javaType="String" /><
 8         <result column="password" property="password" jdbcType="VARCHAR" javaType="String" />
 9     </resultMap>
10     <select id="getUser" parameterType="java.util.Map" resultMap="getUserMap">
11         select * from user
12     </select>
13 </mapper>

 

 

5.測試

  啟動后控制台顯示如下:

  瀏覽器輸入    http://localhost:8080/helloMybatis

  控制台結果如下圖:

 

  頁面結果如下圖:

 

 

 

6.總結

  spring注解一直是我餓心結,當我想將我的代碼改成以注解方式來進行裝配注入的時候,總是不行的,

  於是乎我學會了很多奇葩的手段,可能不主流。

 

  吐槽歸吐槽,學習歸學習,工作歸工作,一碼是一碼!!!

 

  注:本文配置方式會產生幾個問題

 

    要確保手動加載mapper.xml的掃描只掃描一次,否則是否會加載產生多個mapper加入VM管理並不確定,很可能數量很多。

    springboot以這種方式配置的數據源,本質上是交給內置的tomcat來管理的,內置的tomcat來管理會涉及到連接池的問題。

      如果數據庫對於連接數量沒有擴容,而內置tomcat的連接池沒有配置,短時間內會產生大量連接而不銷毀,會導致連接      

      拒絕,而報錯。

 

  可能報出的兩個常見的錯誤,主要內容如下:

 

      a:Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

        Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

        The last packet successfully received from the server was 14,595,596 milliseconds ago.  The last packet sent successfully to the server was 14,595,612 milliseconds ago.

 

        該錯誤的原因通常是因為session沒有保證關閉引起的

 

      b: o.a.tomcat.jdbc.pool.ConnectionPool      : Unable to create initial connections of pool.

        Data source rejected establishment of connection,  message from server: "Too many connections"

        

        本示例中使用的是MySql數據庫,Threads_connected設置的數值是512,因此報上述錯誤。

        該錯誤的原因不僅有Mysql數據庫優化的問題,同時也有連接池管理配置的問題

 

    以上列舉問題將在后文中處理,更新后將在文尾插入連接!

 

  對於以上配置過程的springBoot的注解版,明日再更

 

休息!

以上!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM