package com.viewhigh.framework.common.db.dynamic;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
@Intercepts(value = {
@Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class }),
@Signature(type = Executor.class, method = "update", args = {
MappedStatement.class, Object.class }) })
public class RWSplitting implements Interceptor {
JdbcContextHolder jdbcContextHolder;
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
if (mappedStatement.getSqlCommandType() == SqlCommandType.SELECT) {
System.out.println("read!~~");
jdbcContextHolder.setSlave();
} else {
if (null == jdbcContextHolder.getJdbcType()) {
System.out.println("write!~~");
jdbcContextHolder.setMaster();
}
}
try {
return invocation.proceed();
} finally {
jdbcContextHolder.clearJdbcType();
}
}
@Override
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
}
@Override
public void setProperties(Properties arg0) {
System.out.println("set properties!~~");
System.out.println(arg0);
}
public void setJdbcContextHolder(JdbcContextHolder jdbcContextHolder) {
this.jdbcContextHolder = jdbcContextHolder;
}
}
@wendal 谢谢指点,大神能否给一个 例子 简单一点即可 ,多谢大神了
@wendal 哥写一个吧 ,我发红包 成不
@wendal 哥 帮帮忙 写个demo吧 给您团队 发大红包
public class SpringDaoRunner implements DaoRunner {
@Override
public void run(DataSource dataSource, ConnCallback callback) {
Connection con = DataSourceUtils.getConnection(dataSource);
try {
callback.invoke(con);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
} finally {
DataSourceUtils.releaseConnection(con, dataSource);
}
}
}
仿照springDaoRunner 自定义使用一个runner
自己一个 DataSource 参考 spring AbstractRoutingDataSource
然后 , 判断 sql 操作, 从 AbstractRoutingDataSource 中获得相应的数据源
@hzl7652 不太理解 在哪里判断 读和写呢 能给个代码例子么 发红包
提交代码了
https://github.com/wendal/nutz-book-project/commit/82838a2dcadb6bef9bd300ee285596f6fc4a540c
基本上是这样, 改改dao.js变成这个样子
var ioc = {
dataSource : {
// master数据库的DataSource
},
dataSource_slave : {
// slave数据库的DataSource
},
dao : {
type : "org.nutz.dao.impl.NutDao",
args : [{refer:"dataSource"}], // 仅引用master的, 魔法不在这里.
fields : {
executor : {refer:"masterSlaveExecutor"} // 引用新的Executor
}
},
masterSlaveExecutor : {
type : "net.wendal.nutzbook.util.MasterSlaveDaoExecutor",
fields : {
slave : {refer:"dataSource_slave"} // 引用slave数据库
}
}
MasterSlaveDaoExecutor的代码(能用,但不够完善是真的),如果出现什么问题,大家再反馈吧
package net.wendal.nutzbook.util;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.nutz.dao.DaoException;
import org.nutz.dao.sql.DaoStatement;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.plugins.cache.dao.CachedNutDaoExecutor;
import org.nutz.trans.Trans;
/**
* 演示主从数据库. 继承CachedNutDaoExecutor是为了daocache缓存,不需要的话,直接继承NutDaoExecutor即可.
*
* @author wendal
*
*/
public class MasterSlaveDaoExecutor extends CachedNutDaoExecutor {
protected static Log log = Logs.get();
protected DataSource slave; // TODO 变成数组来支持多个slave?
public void exec(Connection conn, DaoStatement st) {
// 事务内,不可以Slave
if (!Trans.isTransactionNone() || !(st.isSelect() || st.isForceExecQuery())) {
super.exec(conn, st);
return;
}
if (log.isDebugEnabled())
log.debug("exec at slave DataSource >> " + st.toPreparedStatement());
// 重头戏开始了
Connection _conn = null;
try {
_conn = slave.getConnection();
super.exec(_conn, st);
}
catch (SQLException e) {
throw new DaoException("slave fail", e);
}
finally {
if (_conn != null)
try {
_conn.close();
}
catch (SQLException e) {
log.warn("fail to close slave connection!!!!", e);
}
}
}
}
@wendal 哥 微信号告诉我 给您发红包
@wendal 哥 那个配置 能用 spring的xml 在配置一下么 dao。js 还是不太明白 配好了 我在发红包
<bean id="dao" type="org.nutz.impl.NutDao">
<property name="dataSource" ref="dataSource"></property>
<property name="executor" ref="masterSlaveExecutor"></property>
</bean>
<bean id="masterSlaveExecutor" type="net.wendal.nutzbook.util.MasterSlaveDaoExecutor">
<property name="slave" ref="dataSource_slave"></property>
</bean>
@wendal 牛逼 哥 微信告诉我
@wendal 大神哥 这个读写分离 能放到 下个版本去么,这样我就不用自己动脑写了,哈哈 我觉得也会有人需要这样的 东西,希望支持 配置 自动读写分离 那样就很牛逼了 谢谢大神。
@wendal 看到了 神哥 40 不多 请您笑纳
@qq_2a1c6850 那是随机值,金额随天意,哈哈
来自炫酷的 NutzCN
@wendal 日 我说的么 怎么只能7.6啊
@wendal import org.nutz.plugins.cache.dao.CachedNutDaoExecutor;
这个包 在那下的啊 怎么没找到啊
@Wizzercn 你写的就是不对 ,这个我也会
@Wizzercn 你会怎么没有写出来,我只关心结果 不好意思
@wendal 继承NutDaoRunner 报错诶
if (!Trans.isTransactionNone() || !(st.isSelect() || st.isForceExecQuery())) {
super.exec(conn, st);//这个地方显示错误
return;
}
if (log.isDebugEnabled())
log.debug("exec at slave DataSource >> " + st.toPreparedStatement());
// 重头戏开始了
Connection _conn = null;
try {
_conn = slave.getConnection();
super.exec(_conn, st);//这个地方显示错误
}
@Rekoe The method exec(Connection, DaoStatement) is undefined for the type NutDaoRunner
package com.viewhigh.data.common.dao;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.nutz.dao.DaoException;
import org.nutz.dao.impl.sql.run.NutDaoRunner;
import org.nutz.dao.sql.DaoStatement;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.trans.Trans;
public class MasterSlaveDaoExecutor extends NutDaoRunner{
protected static Log log = Logs.get();
protected DataSource slave; // TODO 变成数组来支持多个slave?
public void exec(Connection conn, DaoStatement st) {
// 事务内,不可以Slave
if (!Trans.isTransactionNone() || !(st.isSelect() || st.isForceExecQuery())) {
super.exec(conn, st);
return;
}
if (log.isDebugEnabled())
log.debug("exec at slave DataSource >> " + st.toPreparedStatement());
// 重头戏开始了
Connection _conn = null;
try {
_conn = slave.getConnection();
super.exec(_conn, st);
}
catch (SQLException e) {
throw new DaoException("slave fail", e);
}
finally {
if (_conn != null)
try {
_conn.close();
}
catch (SQLException e) {
log.warn("fail to close slave connection!!!!", e);
}
}
}
}
@Wizzercn 我去年买了个表
@Rekoe 这个不知道在哪里下载
@Rekoe 没有吧 nutz包 没有引用到这个类,是pluin的