什么是多数据源

作为程序员在开发程序中,经常遇到一个后台程序,需要连接多个数据库的情况,这个时候就比较麻烦了,就可以通过多数据源的方式来实现。

什么是PageHelper

pageHelper是一个用来实现分页查询的java包,通过这个包,程序员再也不用写limit等sql语句,并且它是跨平台的,在mysql上不用,sqlserver也不用,别的因为博主没有试过,暂时保留意见。它是非侵入式的,只需要在普通的条件查询前和后各增加一行代码就可以了。

//pageNum页码,pageSize 页大小
PageHelper.startPage(pageNum, pageSize);
//数据库查询
List<CheckProcessVO> datas = getCheckProcessVOS(query);
//返回的pageInfo就是分页好的了,total什么都有
PageInfo<CheckProcessVO> pageInfo = PageInfo.of(datas);

多数据源的实现

第一步

  • 导入几个maven包
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
    <version>2.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>

第二步

  • 编写多数据源数据库连接配置项

博主这里是将多数据源单独打包成了一个工具包,供公司所有人依赖的这样不用写重复代码。

接下来我会一一介绍里面的详细信息。

  • 数据库连接信息配置,采用springboot配置文件注入方式

请自行更换包名,lombok如果报错,就添加lombok依赖,并在idea中添加lombok的插件

下方所有的属性,都可以通过application.yml文件进行配置,这个就不用说了吧!springboot的基本用法!

package com.hollysys.mutiple.datasource.conf.bean;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 多数据源配置1
 *
 * @author niuniu
 * @since 2019/8/7 15:43
 */
@Getter
@Setter
@ConfigurationProperties(prefix = "hollysys.multiple.datasource.common")
public class CommonDatasourceBean {
    /**
     * 链接url
     */
    private String jdbcUrl;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 最小连接池大小
     */
    private int minPoolSize = 10;
    /**
     * 最大链接吃大小
     */
    private int maxPoolSize = 30;
    /**
     * 一个连接的生命时长(毫秒)
     * 超时而且没被使用则被释放(retired)
     * 缺省:30分钟
     */
    private int maxLifetime = 1000 * 60 * 30;
    /**
     * 连接池中允许的最大连接数。缺省值:10;
     * 推荐的公式:((core_count * 2) + effective_spindle_count)
     */
    private int maximumPoolSize = 10;
    /**
     * 最大空闲时间
     */
    private int idleTimeout = 1000 * 60;
    /**
     * 接只读数据库时配置为true,保证安全
     * 默认是false
     */
    private boolean readOnly = false;

    /**
     * 登录数据库超时时间
     * 超时获取连接失败
     */
    private int loginTimeOut = 1000 * 60;

    /**
     * 等待连接池分配连接的最大时长(毫秒)
     * 超过这个时长还没可用的连接则发生SQLException
     * 默认30s
     */
    private int connectionTimeout = 1000 * 30;

    /**
     * 获取连接失败重新获等待最大时间,在这个时间内如果有可用连接,将返回
     */
    private int borrowConnectionTimeout = 1000 * 30;
    /**
     * 连接回收时间
     */
    private int maintenanceInterval = 1000 * 60;

    /**
     * 保持数据库连接
     */
    private String testQuery = "select 1";
    /**
     * mapper位置
     */
    private String mapperLocation;
    ;
    /**
     * 包文件位置
     */
    private String typeAliasesPackage;
}
  • 多数据源核心配置

上面的是基本,所有的数据源都应该可以配置上述属性,下面的代码才是真正实现多数据源并整合了pageHelper的精髓代码

package com.hollysys.mutiple.datasource.conf;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.github.pagehelper.PageInterceptor;
import com.github.pagehelper.autoconfigure.PageHelperProperties;
import com.hollysys.mutiple.datasource.conf.bean.CommonDatasourceBean;
import com.mysql.cj.jdbc.MysqlXADataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;

/**
 * mysql多数据源配置01
 *
 * @author niuniu
 * @since 2019/8/7 15:59
 */
@Configuration
@ConditionalOnProperty(prefix = "hollysys.multiple.datasource.common", name = "able", havingValue = "true")
@MapperScan(basePackages = "com.hollysys.**.common.**.dao", sqlSessionTemplateRef = "CommonSqlSessionTemplate")
public class CommonDatasourceConfig {

    @Bean(name = "CommonDatasource")
    @Primary
    public DataSource getDataSource(CommonDatasourceBean commonDatasource) throws SQLException {
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setURL(commonDatasource.getJdbcUrl());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        mysqlXADataSource.setPassword(commonDatasource.getPassword());
        mysqlXADataSource.setUser(commonDatasource.getUsername());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        //交给AtomikosDataSource管理
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("CommonDatasource");
        atomikosDataSourceBean.setMinPoolSize(commonDatasource.getMinPoolSize());
        atomikosDataSourceBean.setMaxPoolSize(commonDatasource.getMaxPoolSize());
        atomikosDataSourceBean.setBorrowConnectionTimeout(commonDatasource.getBorrowConnectionTimeout());
        atomikosDataSourceBean.setLoginTimeout(commonDatasource.getLoginTimeOut());
        atomikosDataSourceBean.setMaintenanceInterval(commonDatasource.getMaintenanceInterval());
        atomikosDataSourceBean.setMaxIdleTime(commonDatasource.getIdleTimeout());
        atomikosDataSourceBean.setTestQuery(commonDatasource.getTestQuery());
        return atomikosDataSourceBean;
    }

    @Bean(name = "CommonSqlSessionFactory")
    public SqlSessionFactory getSqlSessionFactory(@Qualifier("CommonDatasource") DataSource dataSource,
                                                  CommonDatasourceBean commonDatasource, PageHelperProperties pageHelperProperties) throws Exception {
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        String mapperLocation = commonDatasource.getMapperLocation();
        Resource[] resources = new PathMatchingResourcePatternResolver().
                getResources(mapperLocation);
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        mybatisSqlSessionFactoryBean.setTypeAliasesPackage(commonDatasource.getTypeAliasesPackage());
        mybatisSqlSessionFactoryBean.setMapperLocations(resources);
        Properties properties = pageHelperProperties.getProperties();
        PageInterceptor pageInterceptor = new PageInterceptor();
        pageInterceptor.setProperties(properties);
        Interceptor[] interceptors = {pageInterceptor};
        mybatisSqlSessionFactoryBean.setPlugins(interceptors);
        return mybatisSqlSessionFactoryBean.getObject();
    }

    @Bean(name = "CommonSqlSessionTemplate")
    public SqlSessionTemplate getSqlSessionTemplate(
            @Qualifier("CommonSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
  • 代码写到这里一个数据源的配置就完成了
注意!
  • 配置自己的多数据源,这里可以修改的代码有:
  1. @ConfigurationProperties(prefix = "hollysys.multiple.datasource.common")

这是数据源连接属性配置的前缀,通过修改prefix的值,来修改注入时键值对的键名

如:hollysys.multiple.datasource.common.url="jdbc:mysql:///dbNameuse

  1. @ConditionalOnProperty(prefix = "hollysys.multiple.datasource.common", name = "able", havingValue = "true")
    @MapperScan(basePackages = "com.hollysys.**.common.**.dao", sqlSessionTemplateRef = "CommonSqlSessionTemplate")

第一行是需要在springboot的application.yml中配置hollysys.multiple.datasource.common.able=true 必须有这一行才会使这个配置文件生效,起到一个随时开关一个数据源的作用,当然这里的路径可以修改为你自己的,也是修改"prefix",也可以输出这一行

第二行比较重要,两个杠是因为我的编辑器需要转义... 实际没有

basepackage:dao接口放的位置(可以按照你自己的需求修改,可以使用通配符)

sqlSessionTemplateRef:下面代码要用到,如果修改,一定要一起改,否则会报错

修改位置:

  1. @Bean(name = "CommonSqlSessionTemplate")
  1. 其实通过代码我们可以看到,下面代码是在创建SqlSession工厂,和Template 因为我们最终是通过Template来使用操作的,如果你是从spring3.0过来的,你一定很了解下面两个方法是在干什么!

getSqlSessionTemplate() getSqlSessionFactory()

这里有一个顺序,先创建数据源,把数据源给工厂,工厂提供链接给操作模板

在修改注解上的名称时一定要注意下面截图部分

保持一致的地方

这三处一定要保持值是一致的,否则报错。

到这里,一处的多数据源就配置完成了

如果想配置多个,请把上方代码,多复制几套,修改一下注解,类名就可以了

使用演示

直接上截图吧

  • springboot 开始文件要注意屏蔽自带数据源配置

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, PageHelperAutoConfiguration.class})

//引用数据源,使其生效

@EnableConfigurationProperties(value = {CommonDatasourceBean.class, AlarmDatasourceBean.class, EnergyDatasourceBean.class,
        OeeDatasourceBean.class, PanelDatasourceBean.class, StartStopDatasourceBean.class, ZhangGuanDatasourceBean.class,
        PageHelperProperties.class})
  • 可以看到,我这里引用了7个数据源,PageHelper是帮助分页的
  • yml中的配置

启用数据源并配置

PageHelper的配置

  • 上面就是多数据源整合pageHelper的代码

完成了

虽然有一个数据源的配置,但是其他代码都是一样的,只要复制黏贴,就可以配置多个了!

有什么疑问的话,请在下面留言。

Last modification:September 3rd, 2020 at 02:42 pm
如果觉得我的文章对你有用,请随意赞赏