Springboot + MyBatis入门培训 3 多数据源与缓存和数据连接池设置

Posted zhtbs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot + MyBatis入门培训 3 多数据源与缓存和数据连接池设置相关的知识,希望对你有一定的参考价值。

介绍MyBatis项目中如何配置多个数据源连接数据库,以及设置sql文的二级缓存功能,配置多数据源与数据连接池等功能。为大家开发和平时练习的时候提供参考和查询的工具文章。

代码下载百度网盘下载:https://pan.baidu.com/s/1Q6pbC2SR70HKCeVXgOGUPQ
提取码:1234

本站资源下载

Springboot + MyBatis入门培训 1 项目运行环境配置

Springboot + MyBatis入门培训 2 增改删除与查询 in like foreach操作

MyBatis多数据源设置

在实际的项目开发中通常会遇到业务数据保存在不同的数据库中,而我们需要操作多个数据数据库进行业务操作的情况。在MyBati中是可以同时使用多个数据源连接数据库的,项目中导入dynamic-datasource 插件就可以配置多个数据源的连接,使用起来非常的简单,操作与维护性非常的高。dynamic-datasource可以封装成Spring Starter方式引入,支持Mybatis读写分离,支持通过注解动态切换切换数据源。

pom.xml

<!--多数据源需要-->
<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
   <version>3.3.6</version>
</dependency>

spring boot application.yml文配置

​ 配置多数据源唯一技术难度就是配置上,配置正确调用起来非常简单。

数据源在yml文件中的结构

  • datasource: 数据源根节点
  • dynamic: 多数据源配置头节点
  • primary : 默认主数据名称
  • datasource: 数据节点
  • master:默认节点
  • 子节点: 自定义节点名称

配置层级

spring:                   spring顶层标记
 datasource:              1级
    dynamic:              2级
      primary: master     3级
      strict: false       3级
      datasource:         3级
        master:           4级
        子节点名称:         4级

找到目录中的application.yml 配置文件,添加如下内容到application.yml 文件中。

  • 数据源配置要在spring节点下建立
  • 默认节点与子数据库节点下配置数据库连接内容

配置2个数据源,在项目工程中可以使用MyBatis访问这两数据库来进行sql文操作。

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/db1   #数据库一
          username: root
          password: 123456
		  driver-class-name: com.mysql.jdbc.Driver
         zht:
          url: jdbc:mysql://localhost:3306/db2  #数据库二
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver

支持在项目中同时配置不同数据库的数据连接

  • oracle 数据库
  • mysql数据库
  • postgresql数据库
  • sqlserver数据库
  • h2数据库

多数据库配置

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/db1      #mysql
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
         zht:
          url: jdbc:oracle:thin:@localhost:1521:orcl  #oracle
          username: root
          password: 123456
          driver-class-name: oracle.jdbc.driver.OracleDriver

同时配置两个不同的数据库连接源。

切换数据源 @Mapper 容器操作

在文件目录中找到 UserSql.xml文件,定义两数据库连接的 sql文方法。

  • UserList 方法的中的use表在数据库localhost:3306/db1
  • towlist 方法中的userdb2表在数据库localhost:3306/db2

UserSql.xml

<?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.core.my.app.dao.UserDao"> 
  <select id="UserList" resultType="map">
        select * from user
  </select>    
  <select id="towlist" resultType="map">
        select * from userdb2
   </select>
</mapper>    

@DS 注解打在要执行的MyBatis 执行方法上。@DS 标注要执行的数据库连接的名称,方法在执行的时候就执行标注的数据库连接。

如果MyBatis 执行方法上没有标注@DS,方法执行默认的数据库连接。

UserDao接口

@Mapper
public interface UserDao {
    //没有定义@DS 表示执行默认数据库
	 List<Map> UserList(Map map);
     //强制方法访问数据库localhost:3306/db2来执行
	 @DS("zht")
	 List<Map> towlist(Map map);
}

MyBatisTest测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes=OnApp.class)
public class MyBatisTest {
	@Test
	public void TestAddDB(){
		//第一个数据库连接表测试  user表
		userdao.UserList(new HashMap());
		//第二个数据库连接表测试 userdb2表
		userdao.towlist(new HashMap());
	}
}

在测试类中定义对应的测试方法。

运行结果

-----------主数据库user表  -----------------
==>  Preparing: select * from user WHERE id in (?) and user like '%%' 
==> Parameters: null
<==      Total: 0
-----------子数据库sys_user表-----------------
==>  Preparing: select * from sys_user 
==> Parameters: 
<==  Columns: id, acc, paw, u_name, u_post, u_edu, birthday, notes, deptid, isamdin

不同数据库操作同表 @Service容器操作

如果两个数据库中有同一张表,在UserSql.xml中定义同一张表的sql文业务操作,我们要怎么做呢?我们需要定义一个spring @Service容器,在容器中使用**@DS** 注解来区分不同数据库的操作。

UserSql.xml

<select id="addlist" resultType="map">
     select * from user
</select> 

在数据库一和数据库二中同时创建一个表user,在UserSql.xml中定义个 select * from user 业务的sql文方法。

UserDao接口

@Mapper
public interface UserDao {
	//所有数据库共同使用一张表
	List<Map> addlist(Map map);
}

UserDao接口中定义这个表查询的MyBatis 执行方法

UserServer 业务类

在@Service容器类中定义两个执行方法,一个没有**@DS** 注解的方法执行查询默认数据库中user表,别一个定义@DS(“zht”)查询数据库二中的user表信息。

@Service
public class UserServer {
	@Autowired
	UserDao user;
	public List getOne(Map map){
		return user.addlist(map);
	}
	@DS("zht")
	public List getTow(Map map){
		return user.addlist(map);
	}
}

MyBatisTest测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes=OnApp.class)
public class MyBatisTest {
  @Autowired
  UserServer us;//业务容器引入
  @Test
  public void AddDB(){
	//第一个数据库连接user表
	us.getOne(new HashMap());
	//第二个数据库连接user表
	us.getTow(new HashMap());
  }
}

运行结果

-----------主数据库查询  -----------------
==>  Preparing: select * from user 
==> Parameters: 
<==    Columns: id, user
<==        Row: 1, username
<==        Row: 2, zht
<==      Total: 2
-----------子数据库查询  -----------------
==>  Preparing: select * from user 
==> Parameters: 
<==    Columns: id, name
<==        Row: 1, 数据库2
<==      Total: 1

MyBatis缓存 ehcache设置

MyBatis为了提高数据库的使用效率,我们通常会使用到二级缓存,通过二级缓存来操作常用的业务数来达到减轻数据库压力提高效率。java中现在有大量的缓存框架,我们选择ehcache是应为它非常的成熟,和MyBatis结合的度是最好的,最最最重要的是它操作特别简单,基本可以一看就会很容易上手,实际项目使用起来非常方便。

pom.xml

  <dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
  </dependency>

在需要使用缓存的 MyBatis业务sql.xml 中写入 ehcache 缓存配置xml元素。缓存分为两种,1普通缓存EhcacheCache,2阻塞缓存 EhBlockingCache。

  • org.mybatis.caches.ehcache.EhcacheCache 普通缓存

  • org.mybatis.caches.ehcache.EhBlockingCache 阻塞缓存

UserSql.xml加入缓存

<?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.core.my.app.dao.UserDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <select id="addlist" resultType="map">
     select * from user
  </select>           
</mapper>

MyBatis业务sql.xml 中默认设置, 这样就可以简单的声明缓存了。

缓存应用于每个语句

  • 一旦在 xml 中声明了缓存,缓存将应用于 xml 中的所有sql语句。
  • 如果不想使用缓存,在语句上添加 useCache=“false” 作为元素属性。
<!-- 如果不想使用缓存,简单的设置一下 useCache="false" --> 
<select id="addlist" resultType="map" useCache="false">
     select * from user
 </select>
<!-- 不设置useCache="false" 操作的数据信息将保持在缓存中 -->
<insert id="saveuser">
INSERT INTO user(id, user)
    VALUES(#{id}, #{name})
</insert>

ehcache 缓存池大小设置

<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.core.my.app.dao.UserDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache">
    <property name="timeToIdleSeconds" value="3600"/>
    <property name="timeToLiveSeconds" value="3600"/>
    <property name="maxEntriesLocalHeap" value="10000"/>
    <property name="maxEntriesLocalDisk" value="10000000"/>
    <property name="memoryStoreEvictionPolicy" value="LRU"/>
  </cache>

一般在中小型项目中以上的缓存池配置基本可以满足业务需求,在常用的业务 sql.xml中加入以下配置就可以了。

参数列表

名称内容
timeToIdleSeconds设定允许对象处于空闲状态的最长时间
timeToLiveSeconds设定对象允许存在于缓存中的最长时间
maxEntriesLocalHeap缓存可以在本地堆内存中使用的最大缓存条目
maxEntriesLocalDisk独立缓存可以在本地磁盘上使用的最大缓存条目
memoryStoreEvictionPolicy当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)

数据连接池设置

我们使用阿里的druid作为数据连接池,阿里的东西不用说做的真的很强,易用性非常的好,而且功能强大我用过那么多的数据池,它的综合性价比是最高的,而且上手成本非常的低,只要yml文件配对了数据池就可用,它的学习和维护成本就在怎么配置yml中的对应参数。

pom.xml

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.2.1</version>
</dependency>

数据池 application.yml 中的层级

  • 全局数据池设置,与datasource下的dynamic元素同级为全局数据池
  • 独立的数据库连接池设置,在多数据源的数据库连接下面设置自己独立的数据连接池,这个池只能这个个对应的数据自己使用

全局池层级关系

spring:
  datasource:
    dynamic:
    type: com.alibaba.druid.pool.DruidDataSource
    druid://与dynamic同级别 表示是全局数据池所有数据源使用

独立池层级关系

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        主数据库:
            type: com.alibaba.druid.pool.DruidDataSource
            druid://单独的数据连接池设置
        子数据库:
            type: com.alibaba.druid.pool.DruidDataSource
    		druid://单独的数据连接池设置

数据池 application.yml 中的设置

全局池例子

server:
  port: 8888
spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/systext?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
        zht:
          url: jdbc:mysql://localhost:3306/zhtsys?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
        initial-size: 10
        max-active: 100
        min-idle: 10
        max-wait: 60000
        pool-prepared-statements: true
        max-pool-prepared-statement-per-connection-size: 20
        time-between-eviction-runs-millis: 60000
        min-evictable-idle-time-millis: 300000           
mybatis:
  mapperLocations: classpath*:/mapper/*.xml
  configuration: 
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • type 元素表示连接的数据池驱动,如果是其他池下面的标签就换成对应池的元素标签

个数据库的独立池例子

server:
  port: 8888
spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/systext?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            initial-size: 10
            max-active: 100
            min-idle: 10
            max-wait: 60000
            pool-prepared-statements: true
            max-pool-prepared-statement-per-connection-size: 20
            time-between-eviction-runs-millis: 60000
            min-evictable-idle-time-millis: 300000  
        zht:
          url: jdbc:mysql://localhost:3306/zhtsys?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            initial-size: 10
            max-active: 100
            min-idle: 10
            max-wait: 60000
            pool-prepared-statements: true
            max-pool-prepared-statement-per-connection-size: 20
            time-between-eviction-runs-millis: 60000
            min-evictable-idle-time-millis: 300000           
mybatis:
  mapperLocations: classpath*:/mapper/*.xml
  configuration: 
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

druid 配置参数

属性说明备注
initialSize启动程序时,在连接池中初始化多少个连接100
maxActive连接池中最多支持多少个活动会话
maxWait程序向连接池中请求连接时,超过maxWait的值后,认为本次请求失败,即连接池没有可用连接,单位毫秒,设置-1时表示无限等待100
minEvictableIdleTimeMillis池中某个连接的空闲时长达到 N 毫秒后, 连接池在下次检查空闲连接时,将回收该连接,要小于防火墙超时设置net.netfilter.nf_conntrack_tcp_timeout_established的设置
timeBetweenEvictionRunsMillis检查空闲连接的频率,单位毫秒, 非正整数时表示不进行检查
keepAlive程序没有close连接且空闲时长超过 minEvictableIdleTimeMillis,则会执行validationQuery指定的SQL,以保证该程序连接不会池kill掉,其范围不超过minIdle指定的连接个数。true
minIdle回收空闲连接时,将保证至少有minIdle个连接.与initialSize相同
removeAbandoned要求程序从池中get到连接后, N 秒后必须close,否则druid 会强制回收该连接,不管该连接中是活动还是空闲, 以防止进程不会进行close而霸占连接。当发现程序有未正常close连接时设置为true
removeAbandonedTimeout设置druid 强制回收连接的时限,当程序从池中get到连接开始算起,超过此值后,druid将强制回收该连接,单位秒。应大于业务运行最长时间
logAbandoned当druid强制回收连接后,是否将stack trace 记录到日志中true
testWhileIdle当程序请求连接,池在分配连接时,是否先检查该连接是否有效。(高效)true
validationQuery检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果
testOnBorrow程序 申请 连接时,进行连接有效性检查(低效,影响性能)false
testOnReturn程序 返还 连接时,进行连接有效性检查(低效,影响性能)false
poolPreparedStatements缓存通过以下两个方法发起的SQL
maxPoolPrepareStatementPerConnectionSize 每个连接最多缓存多少个SQL20
connectProperties连接属性。比如设置一些连接池统计方面的配置。

druid 是个功能很强大的数据池,提供很多其他功能如果有需要加入其他功能的可以参考一下,下面中的配置内容。

server:
  port: 8888
spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/systext?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
        zht:
          url: jdbc:mysql://localhost:3306/zhtsys?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver 
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 连接池的配置信息
      # 初始化大小,最小,最大
      initial-size: 5
      min-idle: 5
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      validationQuery: SELECT 1
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      # 打开PSCache,并且指定每个连接上PSCache的大小
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 20
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall,slf4j
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000
      # 配置DruidStatFilter
      web-stat-filter:
        url-pattern: "/*"
        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
      # 配置DruidStatViewServlet
      stat-view-servlet:
        enabled: true
        url-pattern: "/druid/*"
        # IP白名单(没有配置或者为空,则允许所有访问)
        allow: 127.0.0.1,192.168.3.25
        # IP黑名单 (存在共同时,deny优先于allow)
        #        deny: localhost
        #  禁用html页面上的“Reset All”功能
        reset-enable: false
        # 登录名
        login-username: admin
        # 登录密码
        login-password: 123456         
mybatis:
  mapperLocations: classpath*:/mapper/*.xml
  configuration: 
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

以上是关于Springboot + MyBatis入门培训 3 多数据源与缓存和数据连接池设置的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot+Mybatis整合入门

SpringBoot整合mybatis快速入门

SpringBoot入门四,添加MyBatis支持

springboot整合mybatis入门

SpringBoot入门之基于注解的Mybatis

SpringBoot 整合 MyBatis-Plus 入门体验