# 强制路由剖析


<!--more-->


在一些应用场景中，分片条件并不存在于SQL，而存在于外部业务逻辑。因此需要提供一种通过在外部业务代码中指定路由配置的一种方式，在ShardingSphere中叫做**Hint**。如果使用Hint指定了强制分片路由，那么SQL将会无视原有的分片逻辑，直接路由至指定的数据节点操作。

HintManager主要使用ThreadLocal管理分片键信息，进行hint强制路由。在代码中向HintManager添加的配置信息只能在当前线程内有效。

**Hint使用场景：**

- 数据分片操作，分片键没有在SQL或数据表中，而是在业务逻辑代码中
- 读写分离操作，强制在主库进行某些数据操作

**Hitt使用过程:**

- 编写分库或分表路由策略，实现HintShardingAlgorithm接口

  ```java
  public class MyHintShardingAlgorithm implements HintShardingAlgorithm<Integer> { 
    @Override 
    public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Integer> 		   hintShardingValue) { 
      //添加分库或分表路由逻辑 
    } 
  }
  ```

- 在配置文件指定分库或分表策略

  ```properties
  #强制路由库和表 
  spring.shardingsphere.sharding.tables.b_order.database- strategy.hint.algorithm-class-name=com.lagou.hint.MyHintShardingAlgorithm 
  spring.shardingsphere.sharding.tables.b_order.table-strategy.hint.algorithm- class-name=com.lagou.hint.MyHintShardingAlgorithm 
  spring.shardingsphere.sharding.tables.b_order.actual-data-nodes=ds$-> {0..1}.b_order$->{0..1}
  ```

- 在代码执行查询前使用HintManager指定执行策略值

  ```java
  @Test//路由库和表 
  public void test(){ 
  	HintManager hintManager = HintManager.getInstance(); hintManager.addDatabaseShardingValue("b_order",1); 		hintManager.addTableShardingValue("b_order",1);
    List<Order> list = orderRepository.findAll();
    hintManager.close(); 
    list.forEach(o -> { System.out.println(o.getOrderId()+" "+o.getUserId()+" "+o.getOrderPrice()); 
                      }); 
  }
  ```

  在读写分离结构中，为了避免主从同步数据延迟及时获取刚添加或更新的数据，可以采用强制路由走主库查询实时数据，使用`hintManager.setMasterRouteOnly`设置主库路由即可。

