NutzCN Logo
问答 nutz如何配置读写分离,就像mybites一样日下代码
发布于 3048天前 作者 qq_2a1c6850 4154 次浏览 复制 上一个帖子 下一个帖子
标签:
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;
	}

}

40 回复

我不是代码翻译官,谢谢.

要读写分离, 继承NutDaoRunner,在里面做处理.

@wendal 谢谢指点,大神能否给一个 例子 简单一点即可 ,多谢大神了

没有简单例子. 看org.nutz.dao.impl.DaoRunner接口, 判断一下是不是读操作,然后换个DataSource取链接

@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 不太理解 在哪里判断 读和写呢 能给个代码例子么 发红包

都是假把式 没人能写出来

今晚我用nutzcn的源码做一个吧, 到时候下源码看

提交代码了

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;

这个包 在那下的啊 怎么没找到啊

@qq_2a1c6850 那个类在daocache插件里面。

你改成继承NutDaoRunner就是了

来自炫酷的 NutzCN

@qq_2a1c6850 马丹,我写的不对么?你搞笑不

@Wizzercn 你写的就是不对 ,这个我也会

@qq_2a1c6850 你会就代表不对?呵呵

@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);//这个地方显示错误
        }

贴错误 log

@Rekoe The method exec(Connection, DaoStatement) is undefined for the type NutDaoRunner

估计是你继承的类不对
贴类代码吧

@Rekoe

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);
                }
        }
    }
}


继承这个
NutDaoExecutor

@Rekoe 这个不知道在哪里下载

nutz 包自带的

@Rekoe 没有吧 nutz包 没有引用到这个类,是pluin的

这都变成骂战了.封贴了.

添加回复
该帖子已被锁定,不能回复.
回到顶部