項目pom.xml
文件中,引入sharding-jdbc的依賴:java
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
複製代碼
項目bootstrap.yml
增長讀寫分離的配置,如下是dev環境的配置:mysql
spring:
shardingsphere:
datasource:
names: master, slave
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/testdb
username: ''
password: ''
slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/testdb1
username: ''
password: ''
masterslave:
name: ms
master-data-source-name: master
slave-data-source-names: slave
複製代碼
dev環境實際關閉了主從同步,經過手動修改從庫的數據來演示效果spring
CREATE TABLE `t1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT 'testname',
`age` int(10) unsigned NOT NULL DEFAULT '30',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 主庫插入的數據
INSERT INTO `testdb`.`t1`(`id`, `name`, `age`) VALUES (1, 'wangao', 10);
-- 從庫插入的數據
INSERT INTO `testdb1`.`t1`(`id`, `name`, `age`) VALUES (1, 'wangao', 20);
複製代碼
@Entity
@Table(name = "t1")
@Data
public class User {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "name")
private String name;
@Column(name = "age")
private Integer age;
}
複製代碼
public interface UserDao extends JpaRepository<User, Integer> {
}
複製代碼
@Test
public void base() {
User user = new User();
user.setName("wangao");
user.setAge(10);
user = userDao.save(user);
System.out.println(user);
}
複製代碼
save方法能夠正常返回帶自增id的對象:sql
主庫中有新插入的數據:數據庫
從庫中沒有數據(主從同步關閉):apache
讀取id爲1的數據,注意此時是從從庫中獲取,年齡爲20bootstrap
@Test
public void readSlave() {
User user = userDao.findById(1).get();
System.out.println(user);
}
複製代碼
部分狀況須要強制從主庫進行讀取。依舊讀取id爲1的數據,注意此時是從主庫中獲取,年齡爲10:api
@Test
public void readMaster() {
HintManager manager = HintManager.getInstance();
manager.setMasterRouteOnly();
User user = userDao.findById(1).get();
System.out.println(user);
//必定記得最後close
manager.close();
}
複製代碼
官方文檔關於讀寫分離有這樣一段話:app
這裏須要注意的是,默認配置spring.jpa.open-in-view=true
,此時一個Restful請求對數據庫的鏈接是同一個,若是存在寫入操做,則後續讀操做均從主庫讀取spring-boot
@RestController
public class UserController {
private final UserDao userDao;
public UserController(UserDao userDao) {
this.userDao = userDao;
}
@GetMapping("api/user/{id}")
public User get(@PathVariable int id) {
//進行寫入操做
User user = new User();
user.setName("奧利奧");
user.setAge(30);
user = userDao.save(user);
System.out.println(user);
//進行讀取操做
return userDao.findById(id).orElse(null);
}
}
複製代碼
若是將配置改爲spring.jpa.open-in-view=false
,此時每一個操做數據庫的鏈接都會從鏈接池中獲取,這樣讀取的操做會從從庫讀取:
更多細節能夠參考sharding-jdbc的官方網站獲取信息: