SpringBoot Mybatis 分庫分表 sharding

開源  https://github.com/letian-tang/mybatis-sharding.git

史上最簡潔的分庫分表中間件  
基於SpringBoot+Mybatis的分庫分表
基於Mapper的切面  
數據源默認使用HikariDataSource
@Component
public class ShardingStrategyImpl implements ShardingStrategy {

    @Override
    public Long getShardingKey() {
        // 例子:從ThreadLocal中獲取當前賣家id,通過賣家id sharding
        return SellerIdHolder.getSellerId();
    }
}

mybatis-db-sharding 分庫分表
mybatis-db-example OrderServiceTest 單元測試

如果有事務,需要在開啓事務之前確定數據源   
那麼就需要對@Transactional 和 TransactionTemplate.execute做攔截    

private static final String EXPRESSION_TRANSACTIONAL =
            "@annotation(org.springframework.transaction.annotation.Transactional)";

private static final String EXPRESSION_TRANSACTIONAL_TEMPLATE =
        "execution(* org.springframework.transaction.support.TransactionTemplate.execute(..))";

private final String[] expressions =
        new String[] {EXPRESSION_TRANSACTIONAL, EXPRESSION_TRANSACTIONAL_TEMPLATE};

/**
 * 攔截器
 * 
 * @return defaultPointcutAdvisor
 */
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
    List<String> expressionList = shardingProperties.getMapperPointcuts();
    Assert.notEmpty(expressionList, "Mapper Pointcut is null");
    DataSourceAdvice interceptor = new DataSourceAdvice(shardStrategy, shardingProperties);
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    expressionList.addAll(Arrays.asList(expressions));
    String expression = String.join(" || ", expressionList);
    pointcut.setExpression(expression);
    DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
    advisor.setPointcut(pointcut);
    advisor.setAdvice(interceptor);
    return advisor;
}
#開啓
mybatis.db.sharding.enabled=true
#Mapper切面,多個 逗號分隔 如 execution(* com.tdy..*Mapper.*(..)),execution(* com.tdy..*Mapper.*(..))
mybatis.db.sharding.mapper-pointcuts=execution(* com.tdy..*Mapper.*(..))
#數據庫1
mybatis.db.sharding.data-sources[0].jdbc-url=jdbc:mysql://localhost:3306/sophon_0?serverTimezone=Asia/Shanghai&allowMultiQueries=true&useSSL=false&zeroDateTimeBehavior=convertToNull&useAffectedRows=true
mybatis.db.sharding.data-sources[0].username=username
mybatis.db.sharding.data-sources[0].password=password
mybatis.db.sharding.data-sources[0].maximum-pool-size=10
mybatis.db.sharding.data-sources[0].idle-timeout=10000
#數據庫2
mybatis.db.sharding.data-sources[1].jdbc-url=jdbc:mysql://localhost:3306/sophon_1?serverTimezone=Asia/Shanghai&allowMultiQueries=true&useSSL=false&zeroDateTimeBehavior=convertToNull&useAffectedRows=true
mybatis.db.sharding.data-sources[1].username=username
mybatis.db.sharding.data-sources[1].password=password
mybatis.db.sharding.data-sources[1].maximum-pool-size=3
mybatis.db.sharding.data-sources[1].idle-timeout=10000
#表名t_order,nums分表數量4,不配置的表不進行分表
mybatis.db.sharding.tables.t_order.nums=4

開源  https://github.com/letian-tang/mybatis-sharding.git

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private OrderMapper orderMapper;

    /**
     * 單表支持
     * 
     * @param order
     */
    @Override
    public void insert(Order order) {
        orderMapper.insert(order);
    }

    /**
     * @Transactional 註解事務支持
     * @param orders
     */
    @Override
    @Transactional
    public void insertBatch(List<Order> orders) {
        for (Order order : orders) {
            orderMapper.insert(order);
        }
    }

    /**
     * 事務模板 transactionTemplate 支持
     * 
     * @param orders
     */
    @Override
    public void insertBatchTemplate(List<Order> orders) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                for (Order order : orders) {
                    orderMapper.insert(order);
                }
            }
        });
    }

    /**
     * 查詢支持
     * 
     * @return
     */
    @Override
    public List<Order> select() {
        return orderMapper.selectList(new LambdaQueryWrapper<Order>());
    }
}

單元測試

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        classes = ShardingApplication.class)
public class OrderServiceTest {

    @Autowired
    private OrderService orderService;


    @Before
    public void init() {
        SellerIdHolder.setSellerId(12L);
    }

    @After
    public void after() {
        SellerIdHolder.clear();
    }

    /**
     * 單表
     */
    @Test
    public void saveOrder() {
        orderService.insert(Order.builder().name("11111").build());
    }

    /**
     * 事務方式 @Transactional
     */
    @Test
    public void saveOrder2() {
        orderService.insertBatch(Lists.newArrayList(Order.builder().name("22222").build(),
                Order.builder().name("33333").build()));
    }

    /**
     * 事務 transactionTemplate方式
     */
    @Test
    public void saveOrder3() {
        orderService.insertBatchTemplate(Lists.newArrayList(Order.builder().name("44444").build(),
                Order.builder().name("55555").build()));
    }

    /**
     * 查詢
     */
    @Test
    public void selectOrder() {
        orderService.select();
    }

    /**
     * 測試 多條sql語句,分號;分隔
     */
    @Test
    public void saveOrder4() {
        orderService.insertBatchList(Lists.newArrayList(Order.builder().name("66666").build(),
                Order.builder().name("77777").build()));
    }
}

開源  https://github.com/letian-tang/mybatis-sharding.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章