shardingsphere已經很方便的被springboot集成了,你只要引入sharding-jdbc-spring-boot-starter
這個包就可以了,而如果是原生java的話,你就需要自己去實現了,主要是重新定義數據源,定義規則等問題,本文主要介紹原生環境下的shardingsphere的使用。
依賴引用
<dependencies>
<!-- mysql 數據源 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- HikariCP連接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- shardingsphere分庫分表 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>4.1.1</version> <!-- 替換成最新版本 -->
</dependency>
<!-- ORM -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.15.Final</version>
</dependency>
<!-- 生產力工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
建立DataSource數據源
- 添加了數據源,確定了mysql數據庫,支持同時設置多個數據源
- 定義了分庫分表的規則
public static DataSource createDataSource() throws SQLException {
// 配置真實數據源
Map<String, DataSource> dataSourceMap = new HashMap<>();
// 配置第一個 MySQL 數據源
HikariDataSource ds0 = new HikariDataSource();
ds0.setDriverClassName("com.mysql.jdbc.Driver");
ds0.setJdbcUrl("jdbc:mysql://192.168.xx.xx:3306/sharding0");
ds0.setUsername("root");
ds0.setPassword("123456");
dataSourceMap.put("ds0", ds0);
// 配置分片規則
TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration("t_order", "ds0.t_order_${0..2}");
ShardingStrategyConfiguration shardingStrategyConfiguration = new StandardShardingStrategyConfiguration("order_id", new ModuloShardingAlgorithm());
tableRuleConfig.setTableShardingStrategyConfig(shardingStrategyConfiguration);
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTableRuleConfigs().add(tableRuleConfig);
// 創建 ShardingSphere 數據源
return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());
}
建立分表規則
/**
* 分表算法
*/
public class ModuloShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(String.valueOf(shardingValue.getValue() % 2))) {
return each;
}
}
throw new UnsupportedOperationException();
}
}
源生SQL方式讀取數據
static void select() throws SQLException {
// 創建數據源
DataSource dataSource = createDataSource();
// 執行SQL
try (Connection conn = dataSource.getConnection()) {
String sql = "SELECT * FROM t_order WHERE order_id = ?";
try (PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
preparedStatement.setLong(1, 11L);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
while (resultSet.next()) {
System.out.println(resultSet.getString("order_id"));
}
}
}
}
}
Hibernate方式,寫入,讀取數據
定義實體
@Entity
@Data
@Table(name = "t_order")
@NamedQueries({
@NamedQuery(
name = "findById",
query = "FROM Order t WHERE t.orderId = :orderId"
)
})
public class Order {
@Id
@Column(name = "order_id", nullable = false)
private Long orderId;
@Column(name = "user_id", nullable = false)
private Long userId;
@Column(name = "amount", nullable = false)
private Double amount;
}
定義數據倉庫
public class OrderRepository {
// 創建EntityManagerFactory
EntityManagerFactory entityManagerFactory;
// 創建EntityManager
EntityManager entityManager;
public OrderRepository() throws SQLException {
this.entityManagerFactory = Persistence.createEntityManagerFactory("lindDb", getProperties(Main.createDataSource()));
this.entityManager = entityManagerFactory.createEntityManager();
}
private static Map<String, Object> getProperties(DataSource dataSource) {
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.nonJtaDataSource", dataSource);
return properties;
}
public List<Order> findById(Long id) {
return entityManager.createQuery("findById", Order.class).setParameter("orderId", id).getResultList();
}
public void save(Order order) {
entityManager.getTransaction().begin();
entityManager.persist(order);
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
}
}
定義添加邏輯及測試
static void HihernateInsert() throws SQLException {
OrderRepository orderRepository = new OrderRepository();
Order order = new Order();
order.setAmount(100d);
order.setOrderId(11L);
order.setUserId(6L);
orderRepository.save(order);
}
根據分表的規則,這條數據會被寫到t_order_1
這張數據表裏。
注意:當採用分表規則之後,如果你的記錄主鍵沒有按着規則存儲,是無法獲取到時數據的,如order_id爲1的記錄被存儲到了t_order_0裏,那這條數據將無法被找到。