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

 

休息!

以上!

转载于:https://www.cnblogs.com/liuyuhangCastle/p/9601835.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot项目中使用MyBatis Plus和Druid多数据的步骤如下: 1. 添依赖 在`pom.xml`文件中添以下依赖: ```xml <!-- MyBatis Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency> <!-- Druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> ``` 2. 配置Druid数据 在`application.yml`中添Druid数据配置: ```yaml spring: datasource: # 主数据 druid: url: jdbc:mysql://localhost:3306/main_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # Druid配置 initialSize: 5 minIdle: 5 maxActive: 20 testOnBorrow: false testOnReturn: false testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL # 从数据 druid2: url: jdbc:mysql://localhost:3306/sub_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # Druid配置 initialSize: 5 minIdle: 5 maxActive: 20 testOnBorrow: false testOnReturn: false testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL ``` 3. 配置MyBatis Plus 在`application.yml`中添MyBatis Plus的配置: ```yaml mybatis-plus: # 主数据配置 mapper-locations: classpath:mapper/main/*.xml type-aliases-package: com.example.main.entity global-config: db-config: id-type: auto field-strategy: not_empty logic-delete-value: 1 logic-not-delete-value: 0 configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 从数据配置 multi-datasource: main: mapper-locations: classpath:mapper/main/*.xml type-aliases-package: com.example.main.entity sub: mapper-locations: classpath:mapper/sub/*.xml type-aliases-package: com.example.sub.entity ``` 4. 配置数据路由 在`com.example.config`包下创建`DynamicDataSourceConfig`类,用于配置数据路由: ```java @Configuration public class DynamicDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.druid") public DataSource mainDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.druid2") public DataSource subDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public DataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object, Object> dataSourceMap = new HashMap<>(2); dataSourceMap.put("main", mainDataSource()); dataSourceMap.put("sub", subDataSource()); // 将主数据作为默认数据 dynamicDataSource.setDefaultTargetDataSource(mainDataSource()); dynamicDataSource.setTargetDataSources(dataSourceMap); return dynamicDataSource; } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource()); sqlSessionFactoryBean.setTypeAliasesPackage("com.example.main.entity"); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/main/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate() throws Exception { return new SqlSessionTemplate(sqlSessionFactory()); } } ``` 5. 配置数据切换 在`com.example.config`包下创建`DynamicDataSource`类,用于实现数据切换: ```java public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } } ``` 在`com.example.config`包下创建`DataSourceContextHolder`类,用于存储当前数据: ```java public class DataSourceContextHolder { private static final ThreadLocal<String> DATASOURCE_CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(String dataSource) { DATASOURCE_CONTEXT_HOLDER.set(dataSource); } public static String getDataSource() { return DATASOURCE_CONTEXT_HOLDER.get(); } public static void clearDataSource() { DATASOURCE_CONTEXT_HOLDER.remove(); } } ``` 在`com.example.aop`包下创建`DataSourceAspect`类,用于切换数据: ```java @Aspect @Component public class DataSourceAspect { @Pointcut("@annotation(com.example.annotation.DataSource)") public void dataSourcePointCut() { } @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); DataSource dataSource = signature.getMethod().getAnnotation(DataSource.class); if (dataSource != null) { String value = dataSource.value(); DataSourceContextHolder.setDataSource(value); } } @After("dataSourcePointCut()") public void after(JoinPoint joinPoint) { DataSourceContextHolder.clearDataSource(); } } ``` 6. 使用多数据 在需要使用从数据的方法上上`@DataSource("sub")`注解,如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> listUsers() { DataSourceContextHolder.setDataSource("sub"); List<User> users = userMapper.selectList(null); DataSourceContextHolder.clearDataSource(); return users; } } ``` 这样就完成了Spring Boot项目中使用MyBatis Plus和Druid多数据配置

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值