SpringBoot Mybatis 分库分表 sharding

    技术2022-07-10  143

    开源  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

    Processed: 0.018, SQL: 9