• 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的注解版,明日再更

     

    休息!

    以上!

  • 相关阅读:
    2016/10/18 数据库设计三大范式
    2016/10/13 Oracle COALESCE()
    2016/10/13 oracle中的round()
    2016/10/10 数据、数据元素和数据项
    2016/09/29 Maven简介
    2016/09/29 瀑布模型开发和敏捷开发
    python2和python3中的类
    使用JQuery完成页面定时弹出广告
    JQuery入门+js库文件分享
    使用JavaScript完成控制下拉列表左右选择
  • 原文地址:https://www.cnblogs.com/liuyuhangCastle/p/9601835.html
Copyright © 2020-2023  润新知