SpringBoot Mybatis Mycat 多租戶(hù)數(shù)據(jù)庫(kù)實(shí)現(xiàn)
點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)
重磅干貨,第一時(shí)間送達(dá)
0x01:Mycat
下載
wget http://dl.mycat.io/1.6.7.3/20190927161129/Mycat-server-1.6.7.3-release-20190927161129-linux.tar.gz配置
server.xml,Mycat服務(wù)器配置,默認(rèn)端口8066
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="useSqlStat">0</property>
<property name="useGlobleTableCheck">0</property>
<property name="sequnceHandlerType">2</property>
<property name="handleDistributedTransactions">0</property>
<property name="useOffHeapForMerge">1</property>
<property name="memoryPageSize">1m</property>
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<property name="systemReserveMemorySize">384m</property>
<property name="useZKSwitch">true</property>
</system>
<!--Mycat用戶(hù)名-->
<user name="root">
<!--Mycat密碼-->
<property name="password">root</property>
<!--Mycat數(shù)據(jù)庫(kù)名-->
<property name="schemas">mycat_test</property>
</user>
</mycat:server>
schema.xml,Mycat和Mysql節(jié)點(diǎn)映射配置
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!--Mycat數(shù)據(jù)庫(kù)名-->
<schema name="mycat_test" checkSQLschema="true" sqlMaxLimit="100">
<!--Mycat表名,節(jié)點(diǎn)名稱(chēng)列表-->
<table name="mycat_test_student" dataNode="dn1,dn2"/>
</schema>
<!--Mycat節(jié)點(diǎn)名稱(chēng)、節(jié)點(diǎn)地址、mysql數(shù)據(jù)庫(kù)名-->
<dataNode name="dn1" dataHost="localhost1" database="db01" />
<dataNode name="dn2" dataHost="localhost1" database="db02" />
<!--Mycat節(jié)點(diǎn)地址-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- mysql數(shù)據(jù)庫(kù)服務(wù)器、賬戶(hù)、密碼 -->
<writeHost host="hostM1" url="192.168.1.71:3306" user="test"
password="test@1234">
</writeHost>
</dataHost>
</mycat:schema>
0x02:Spring Boot
數(shù)據(jù)源配置
#mycat連接信息
spring.datasource.url=jdbc:mysql://localhost:8066/mycat_test?serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#mybatis攔截器配置
mybatis.config-location=classpath:mybatis.xml
Mybatis
mybatis.xml插件配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 打印查詢(xún)語(yǔ)句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<typeAliases>
<typeAlias alias="TestPojo" type="xx.xx.TestPojo"/>
</typeAliases>
<!-- 攔截器插件,改寫(xiě)sql -->
<plugins>
<plugin interceptor="xx.interceptor.MyInterceptor">
</plugin>
</plugins>
</configuration>
攔截器
//攔截StatementHandler的prepare方法
@Intercepts(value = {
@Signature(type = StatementHandler.class,
method = "prepare",
args = {Connection.class,Integer.class})})
public class MyInterceptor implements Interceptor {
// 修改sql,添加前后綴
private static final String preState="/*!mycat:datanode=";
private static final String afterState="*/";
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler=(StatementHandler)invocation.getTarget();
MetaObject metaStatementHandler=SystemMetaObject.forObject(statementHandler);
Object object=null;
//分離代理對(duì)象鏈
while(metaStatementHandler.hasGetter("h")){
object=metaStatementHandler.getValue("h");
metaStatementHandler=SystemMetaObject.forObject(object);
}
//獲取sql
String sql=(String)metaStatementHandler.getValue("delegate.boundSql.sql");
//根據(jù)會(huì)話(huà)上下文,獲取節(jié)點(diǎn)標(biāo)識(shí)
String node=(String) SessionUtil.getSession().getAttribute("appId");
if(node!=null) {
//重寫(xiě)sql,適配mycat
sql = preState + node + afterState + sql;
}
System.out.println("sql is "+sql);
metaStatementHandler.setValue("delegate.boundSql.sql",sql);
Object result = invocation.proceed();
System.out.println("Invocation.proceed()");
return result;
}
// 返回當(dāng)前攔截的對(duì)象(StatementHandler)的動(dòng)態(tài)代理
// 當(dāng)攔截對(duì)象的方法被執(zhí)行時(shí), 動(dòng)態(tài)代理中執(zhí)行攔截器intercept方法.
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
String prop1 = properties.getProperty("prop1");
String prop2 = properties.getProperty("prop2");
System.out.println(prop1 + "------" + prop2);
}
}
總結(jié)
以上為關(guān)鍵實(shí)現(xiàn),主要過(guò)程如下:
搭建 Mycat 服務(wù),設(shè)置提供的數(shù)據(jù)庫(kù)信息
配置Mycat動(dòng)態(tài)映射的兩個(gè)節(jié)點(diǎn),Mycat根據(jù)sql語(yǔ)句中的
/*!mycat:datanode=dn1*/進(jìn)行動(dòng)態(tài)切換數(shù)據(jù)源后執(zhí)行sql配置 SpringBoot 的 Mycat 數(shù)據(jù)源連接
配置 Mybatis 的攔截器插件
配置 Mybatis 攔截器實(shí)現(xiàn),根據(jù)上下文節(jié)點(diǎn),改寫(xiě) sql
注意
生產(chǎn)可采用Mycat集群,集群用ZK管理,以動(dòng)態(tài)實(shí)例化數(shù)據(jù)源
推薦閱讀
關(guān)于程序員大白
程序員大白是一群哈工大,東北大學(xué),西湖大學(xué)和上海交通大學(xué)的碩士博士運(yùn)營(yíng)維護(hù)的號(hào),大家樂(lè)于分享高質(zhì)量文章,喜歡總結(jié)知識(shí),歡迎關(guān)注[程序員大白],大家一起學(xué)習(xí)進(jìn)步!
評(píng)論
圖片
表情


