三、Spring Boot集成sharding-jdbc实现按时间分库分表

回顾

前篇内容已经实现了spring boot集成mybatis访问MySQL,本篇在此基础上集成sharding-jdbc实现分库分表等功能。

集成sharding-jdbc

首先创建创建数据库和表。这是sharding-jdbc所要求的。

create database db_201810;
create database db_201811;

use db_201810;
create table gps_20181014(id int not null auto_increment,gprs varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
create table gps_20181015(id int not null auto_increment,gprs varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
insert into gps_20181014 values(0,'0123456789012345','2018-10-14 0:0:0');
insert into gps_20181015 values(0,'0123456789012345','2018-10-15 0:0:0');

use db_201811;
create table gps_20181114(id int not null auto_increment,gprs varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
create table gps_20181115(id int not null auto_increment,gprs varchar(16) NOT NULL,sys_time datetime,PRIMARY KEY (id));
insert into gps_20181114 values(0,'0123456789012345','2018-11-14 0:0:0');
insert into gps_20181115 values(0,'0123456789012345','2018-11-15 0:0:0');

接着是pom.xml文件,添加sharding-jdbc到工程中。主要是下面两个依赖:

         
        
            io.shardingjdbc
            sharding-jdbc-core
            2.0.3
        

        
            commons-dbcp
            commons-dbcp
            1.3
        

完整的pom.xml文件内容如下



	4.0.0

	com
	SpringBootDemo
	0.0.1-SNAPSHOT
	jar

	SpringBootDemo
	Demo project for Spring Boot

	
		org.springframework.boot
		spring-boot-starter-parent
		2.0.5.RELEASE
		 
	

	
		UTF-8
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-data-redis
		
		
			org.springframework.boot
			spring-boot-starter-jdbc
		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			1.3.2
		

		
			mysql
			mysql-connector-java
			runtime
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
		 
		
			io.shardingjdbc
			sharding-jdbc-core
			2.0.3
		

		
    		commons-dbcp
    		commons-dbcp
    		1.3
		
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	



剩下就是代码了。首先是数据源配置和库策略、表策略:

DataSourceConfig.java

package com.net.config;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.net.config.DatabaseShardingAlgorithm;
import com.net.config.TableShardingAlgorithm;

import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.api.config.TableRuleConfiguration;
import io.shardingjdbc.core.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingjdbc.core.jdbc.core.datasource.ShardingDataSource;


@Configuration
@MapperScan(basePackages = "com.net.domain", sqlSessionFactoryRef = "sqlSessionFactory")
public class DataSourceConfig {
	//配置sharding-jdbc的DataSource,给上层应用使用,这个DataSource包含所有的逻辑库和逻辑表,应用增删改查时,修改对应sql
	//然后选择合适的数据库继续操作。因此这个DataSource创建很重要。
	@Bean
	@Primary
	public DataSource shardingDataSource() throws SQLException {
		
		ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
      
		//用户表配置,可以添加多个配置
		shardingRuleConfig.getTableRuleConfigs().add(getUserTableRuleConfiguration());
		shardingRuleConfig.getTableRuleConfigs().add(getUserTableRuleConfiguration1());
		shardingRuleConfig.getBindingTableGroups().add("gps");
      
		//设置数据库策略,传入的是sys_time
		shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("sys_time", DatabaseShardingAlgorithm.class.getName()));
		//设置数据表策略,传入的是sys_time
		shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("sys_time", TableShardingAlgorithm.class.getName()));
      
      
		return new ShardingDataSource(shardingRuleConfig.build(createDataSourceMap()));
	}

	//创建用户表规则
	@Bean
	TableRuleConfiguration getUserTableRuleConfiguration() {
		TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();

		orderTableRuleConfig.setLogicTable("gps");
		//设置数据节点,格式为dbxx.tablexx。这里的名称要和map的别名一致。下面两种方式都可以
		//orderTableRuleConfig.setActualDataNodes("db_${0..1}.gps_${0..1}");
		orderTableRuleConfig.setActualDataNodes("db_201810.gps_20181014,db_201810.gps_20181015,db_201811.gps_20181114,db_201811.gps_20181115");
		//设置纵列名称
		orderTableRuleConfig.setKeyGeneratorColumnName("sys_time");
		return orderTableRuleConfig;
	}
	
	@Bean
	TableRuleConfiguration getUserTableRuleConfiguration1() {
		TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
		//设置用户表逻辑
		orderTableRuleConfig.setLogicTable("tb_user");
		//设置数据节点,格式为dbxx.tablexx。这里的名称要和map的别名一致
		orderTableRuleConfig.setActualDataNodes("gps_com.tb_user");
      
		return orderTableRuleConfig;
	}
  

	//下面函数是获取数据源,即包含有多少个数据库,读入到系统中存放于map中
	private Map createDataSourceMap() {
		Map result = new HashMap<>();

		result.put("gps_com", createDataSource("jdbc:mysql://localhost:3306/gps_com?characterEncoding=utf8&useSSL=false"));
		result.put("db_201810", createDataSource("jdbc:mysql://localhost:3306/db_201810?characterEncoding=utf8&useSSL=false"));
		result.put("db_201811", createDataSource("jdbc:mysql://localhost:3306/db_201811?characterEncoding=utf8&useSSL=false"));
		return result;
	}

	private DataSource createDataSource(final String dataSourceName) {
		//使用默认连接池
		BasicDataSource result = new BasicDataSource();
		result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
		//设置数据库路径
		result.setUrl(dataSourceName);
		//设置数据库用户名
		result.setUsername("root");
		//设置数据密码
		result.setPassword("123456");
		return result;
	}
  
  
  
  
  
  
	/**
	 * 需要手动配置事务管理器
	 */
	@Bean
	public DataSourceTransactionManager transactitonManager(DataSource shardingDataSource) {
		return new DataSourceTransactionManager(shardingDataSource);
	}

  
	//下面是SessionFactory配置,二选一,由类前语句选择  @MapperScan(basePackages = "com.net.domain", sqlSessionFactoryRef = "sqlSessionFactory")
	@Bean
	@Primary
	public SqlSessionFactory sqlSessionFactory(DataSource shardingDataSource) throws Exception {
		SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
		sessionFactory.setDataSource(shardingDataSource);
		return sessionFactory.getObject();
	}

}

DatabaseShardingAlgorithm.java

package com.net.config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;

import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;



public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm {
    @Override
    public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {

    	String db_name="db_";
    	try {
			Date date = (Date) new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(preciseShardingValue.getValue());
			
			String year = String.format("%tY", date);
			String mon  = String.format("%tm",date);
			db_name=db_name+year+mon;
			System.out.println("db_name:" + db_name);
	} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}
    	
    	for (String each : collection) {
        	System.out.println("db:" + each);
        	if (each.equals(db_name)) {
                return each;
            }
        }
    	
    	throw new IllegalArgumentException();
    }
}

TableShardingAlgorithm.java

package com.net.config;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;

import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;


public class TableShardingAlgorithm implements PreciseShardingAlgorithm {
    @Override
    public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {
    	String tb_name=preciseShardingValue.getLogicTableName() + "_";
    	try {
			Date date = (Date) new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(preciseShardingValue.getValue());
			
			String year = String.format("%tY", date);
			String mon  = String.format("%tm",date);
			String dat  = String.format("%td",date);
			tb_name=tb_name+year+mon+dat;
			System.out.println("tb_name:" + tb_name);
	} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	}
    	
    	for (String each : collection) {
        	System.out.println("tb:" + each);
        	
        	if (each.equals(tb_name)) {
                return each;
            }
        }
    	
    	throw new IllegalArgumentException();
    }
}

这时工程结构如图所示:

三、Spring Boot集成sharding-jdbc实现按时间分库分表_第1张图片

运行程序,没有问题,浏览器触发访问数据库也能正常访问gps_com的tb_user表。

三、Spring Boot集成sharding-jdbc实现按时间分库分表_第2张图片

以上说明集成sharding-jdbc没有问题。至于能访问数据库是由于DataSourceConfig.java中加上了下面代码。

shardingRuleConfig.getTableRuleConfigs().add(getUserTableRuleConfiguration1());

@Bean
TableRuleConfiguration getUserTableRuleConfiguration1() {
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
        //设置用户表逻辑
        orderTableRuleConfig.setLogicTable("tb_user");
        //设置数据节点,格式为dbxx.tablexx。这里的名称要和map的别名一致
        orderTableRuleConfig.setActualDataNodes("gps_com.tb_user");
      
        return orderTableRuleConfig;
}

 

测试并使用sharding-jdbc

上面完成了sharding-jdbc的集成,但是还没有真正发挥作用,也就是分库分表的功能。

继续添加代码,最后工程结构图是:

三、Spring Boot集成sharding-jdbc实现按时间分库分表_第3张图片

GpsData.java

package com.net.domain;

import java.io.Serializable;

public class GpsData implements Serializable{  

	private static final long serialVersionUID = 1L;
	String gprs;
	String sys_time;
	
	
	public void setGprs(String gprs)
	{
		this.gprs = gprs;
	}
	public String getGprs()
	{
		return this.gprs;
	}
	
	public void setSystime(String sys_time)
	{
		this.sys_time = sys_time;
	}
	public String getSystime()
	{
		return this.sys_time;
	}

}

GpsDataMapper.java

package com.net.domain;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.net.domain.GpsData;

@Mapper
public interface GpsDataMapper {

	@Select("select * from gps where sys_time = #{sys_time}")
	List findAll(@Param("sys_time") String sys_time);
}

GpsDataService.java

package com.net.service;

import java.util.List;

import com.net.domain.GpsData;

public interface GpsDataService {

	List getAll(String sys_time);
}

GpsDataServiceImpl.java

package com.net.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.net.domain.GpsData;
import com.net.domain.GpsDataMapper;
import com.net.service.GpsDataService;

@Service("gpsDataService")
public class GpsDataServiceImpl implements GpsDataService{

	@Autowired
	private GpsDataMapper gpsDataMapper;
	
	@Override
	public List getAll(String sys_time)
	{
		return gpsDataMapper.findAll(sys_time);
	}
}

最后是测试代码

TestWithWeb.java

package com.net.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.net.domain.User;
import com.net.domain.GpsData;
import com.net.service.GpsDataService;
import com.net.service.UserService;


@RestController
public class TestWithWeb {
	
	@Autowired
	@Qualifier("userService")
	private UserService userService;
	
	@Autowired
	@Qualifier("gpsDataService")
	private GpsDataService gpsDataService;
	
	@RequestMapping("/log")
	public String login()
	{		
		System.out.println("hello");
		
		User user = userService.login("root", "123456");
		System.out.println(user.toString());
		
		List GpsData_list = gpsDataService.getAll("2018-11-14 0:0:0");

		System.out.println(GpsData_list.get(0).getGprs()); 
		System.out.println(GpsData_list.get(0).getSystime());
		
		return "OK";
	}
}

代码展示结束,开始运行测试。

测试语句:gpsDataService.getAll("2018-11-14 0:0:0");

结果如下:

三、Spring Boot集成sharding-jdbc实现按时间分库分表_第4张图片

 

由于在代码里面直接配置了数据源,所以application.properties里面关于数据库的信息不起作用,可以直接去掉。

结束。

 

 

你可能感兴趣的:(Spring,Boot)