zoukankan      html  css  js  c++  java
  • 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的注解版,明日再更

     

    休息!

    以上!

  • 相关阅读:
    HDU4507 吉哥系列故事――恨7不成妻(数位dp)
    UCF Local Programming Contest 2017 G题(dp)
    ICPC Latin American Regional Contests 2019 I题
    UCF Local Programming Contest 2017 H题(区间dp)
    HDU2089 不要62
    AcWing1084 数字游戏II(数位dp)
    UCF Local Programming Contest 2017 F题(最短路)
    Google Code Jam 2019 Round 1A Pylons(爆搜+贪心)
    AcWing1083 Windy数(数位dp)
    Vue
  • 原文地址:https://www.cnblogs.com/liuyuhangCastle/p/9601835.html
Copyright © 2011-2022 走看看