shardingjdbc分表分庫,主從分離

weixin_33809981發表於2017-12-14

使用shardingjdbc需要修改mybatis的資料來源。原來是mybatis直接引用dataSource,現在需要將dataSource注入到shardingjdbc,然後在將shardingjdbc的shardingDataSource注入給mybatis

<!--資料來源-->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		init-method="init" destroy-method="close">
		<property name="url" value="${db.master.url}" />
		<property name="username" value="${db.master.user}" />
		<property name="password" value="${db.master.password}" />
</bean>
複製程式碼

對apply_orde,apply_device這兩張表進行分表,按createtime進行分表,每週分一張表

<!--shardingjdbc的規則-->
<sharding:standard-strategy id="orderTableShardingStrategy" sharding-column="createtime" range-algorithm-class="com.dsp.common.algorithm.RangleTableShardingAlgorithm" precise-algorithm-class="com.dsp.common.algorithm.PreciseTableShardingAlgorithm"/>
    <sharding:standard-strategy id="applyDeviceTableShardingStrategy" sharding-column="createtime" range-algorithm-class="com.dsp.common.algorithm.RangleTableShardingAlgorithm" precise-algorithm-class="com.dsp.common.algorithm.PreciseTableShardingAlgorithm"/>

    <sharding:data-source id="shardingDataSource">
        <sharding:sharding-rule data-source-names="dataSource">
            <sharding:table-rules>
                <sharding:table-rule logic-table="apply_order" actual-data-nodes="dataSource.apply_order_2017${1..54}" table-strategy-ref="orderTableShardingStrategy" />
                <sharding:table-rule logic-table="apply_device" actual-data-nodes="dataSource.apply_device_2017${1..54}" table-strategy-ref="applyDeviceTableShardingStrategy" />
            </sharding:table-rules>
            <sharding:binding-table-rules>
                <sharding:binding-table-rule logic-tables="apply_order,apply_device"/>
            </sharding:binding-table-rules>
        </sharding:sharding-rule>
        <sharding:props>
            <prop key="sql.show">true</prop>
        </sharding:props>
    </sharding:data-source>
複製程式碼
<!--mybatis部分配置-->
 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="shardingDataSource"/>
        <property name="mapperLocations" value="classpath*:mapper/*.xml"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="shardingDataSource" />
    </bean>
複製程式碼
/**
 * 精確的查詢,用於=,in等精確查詢
 */
public final class PreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
    Logger logger = LoggerFactory.getLogger(PreciseTableShardingAlgorithm.class);
    public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Date> shardingValue) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String format = sdf.format(shardingValue.getValue());
        Integer week = getWeek(shardingValue.getValue());
        String tableName = format+week;
        for (String each : availableTargetNames) {
            if (each.endsWith(tableName)) {
                logger.info("精確查詢返回的表名:"+each);
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }

    /**
     * 獲取當前日期的週數
     * @param date
     * @return
     */
    private Integer getWeek(Date date){
        Calendar instance = Calendar.getInstance();
        instance.setFirstDayOfWeek(Calendar.MONDAY);
        instance.setTime(date);
        int weekNum = instance.get(Calendar.WEEK_OF_YEAR);
        //如果為12月份
        if((instance.get(Calendar.MONTH)+1)==12){
            instance.add(Calendar.WEEK_OF_YEAR,-1);
            int weekNumBefore = instance.get(Calendar.WEEK_OF_YEAR);
            if(weekNum<weekNumBefore){
                return weekNumBefore+1;
            }
        }
        return weekNum;

    }

}
複製程式碼
/**
 * 範圍查詢分表
 */
public final class RangleTableShardingAlgorithm implements RangeShardingAlgorithm<Date> {

    Logger logger = LoggerFactory.getLogger(RangleTableShardingAlgorithm.class);

    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Date> rangeShardingValue) {

        Collection<String> result = new LinkedHashSet<String>(collection.size());

        Range<Date> valueRange = rangeShardingValue.getValueRange();
        Date beginDate = valueRange.lowerEndpoint();
        Date endDate = valueRange.upperEndpoint();

        SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");
        Integer beginDateYear = Integer.valueOf(sdfYear.format(beginDate));
        Integer endDateYear = Integer.valueOf(sdfYear.format(endDate));
        Integer beginWeek = getWeek(beginDate);
        Integer endWeek = getWeek(endDate);
        //年份相等
        if(beginDateYear.equals(endDateYear)){
            //比較月份

            for (int i = beginWeek;i<=endWeek;i++){
                for (String tableName :collection){
                    if(tableName.endsWith(beginDateYear+""+i)){
                        result.add(tableName);
                    }
                }
            }

        }else{
            //年份不等,遍歷年份
            for (int i = beginDateYear;i<=endDateYear;i++){
                //遍歷月份
                if(i==endDateYear){
                    for (int j = beginWeek;j<=endWeek;j++){
                        for (String tableName :collection){
                            if(tableName.endsWith(i+""+j)){
                                result.add(tableName);
                            }
                        }
                    }
                }else{
                    for (int j = beginWeek;j<=12;j++){
                        for (String tableName :collection){
                            if(tableName.endsWith(i+""+j)){
                                result.add(tableName);
                            }
                        }
                    }
                }
            }
        }
        logger.info("範圍查詢返回的表名:"+result);
        return result;
    }


    /**
     * 獲取當前日期的週數
     * @param date
     * @return
     */
    private Integer getWeek(Date date){
        Calendar instance = Calendar.getInstance();
        instance.setFirstDayOfWeek(Calendar.MONDAY);
        instance.setTime(date);
        int weekNum = instance.get(Calendar.WEEK_OF_YEAR);
        //如果為12月份
        if((instance.get(Calendar.MONTH)+1)==12){
            instance.add(Calendar.WEEK_OF_YEAR,-1);
            int weekNumBefore = instance.get(Calendar.WEEK_OF_YEAR);
            if(weekNum<weekNumBefore){
                return weekNumBefore+1;
            }
        }
        return weekNum;

    }
}
複製程式碼

需要注意的地方 使用

<context:property-placeholder location="classpath*:application_local.properties" ignore-unresolvable="true"/>
複製程式碼

不要使用

<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath*:application_local.properties</value>
			</list>
		</property>
	</bean>
複製程式碼

不要將dataSource和shardingjdbc的規則放在一起,因為dataSource裡面的${}和shardingjdbc裡面的${}解析的時候用的不是一個工具。

相關文章