package net.paoding.rose.jade; import java.beans.PropertyDescriptor; import net.paoding.rose.jade.annotation.ShardBy; import net.paoding.rose.jade.statement.Interpreter; import net.paoding.rose.jade.statement.StatementRuntime; import org.springframework.beans.BeanUtils; import org.springframework.core.annotation.Order; /** * 这个类是散表实现的一个示例,您可以copy到您的项目中,再详细实现一下,对不同的表设置相应的散表策略<br> * 真正的表名可以通过runtime.getProperty(ShardAttributes.targetTable)知道, * 这个属性可以和DataSourceFactory结合使用,从而实现散库; * * @author 王志亮 [qieqie.wang@gmail.com] * */ @Order(-10) public class ShardInterpreter implements Interpreter { private int shardCount = 100;//默认散表100份 private char prefixChar = '$';//默认的在@SQL中写要散的表名要以$开始 public ShardInterpreter() { } public ShardInterpreter(char prefixChar, int shardCount) { this.setPrefixChar(prefixChar); this.setShardCount(shardCount); } public void setPrefixChar(char prefixChar) { this.prefixChar = prefixChar; } public char getPrefixChar() { return prefixChar; } public void setShardCount(int shardCount) { this.shardCount = shardCount; } public int getShardCount() { return shardCount; } //@SQL("insert into $user(id, name) values(:1.id, :1.name);") //-->"insert into $user_xx (id, name) values(:1.id, :1.name); @Override public void interpret(StatementRuntime runtime) { String sql = runtime.getSQL(); int index = 0; while (true) { index = sql.indexOf(prefixChar, index); if (index == -1) { break; } int end = sql.length() - 1; for (int i = index + 1; i < sql.length(); i++) { char ch = sql.charAt(i); if (ch == '_') { continue; } if (ch >= '0' && ch <= '9') { continue; } if (ch >= 'a' && ch <= 'z') { continue; } if (ch >= 'A' && ch <= 'z') { continue; } end = i; break; } String origin = sql.substring(index, end); String target = convert(origin, runtime); if (target != null && target.length() > 0) { runtime.setProperty(ShardAttributes.originTable, origin); runtime.setProperty(ShardAttributes.targetTable, target); sql = sql.substring(0, index) + target + sql.substring(end); index += target.length(); } else { index = end; } } runtime.setSQL(sql); } /** * 重新实现此方法自定义转化规则 * * @param term * @param runtime * @return */ protected String convert(String term, StatementRuntime runtime) { int shardIndex = runtime.getMetaData().getShardByIndex(); if (shardIndex < 0) { throw new IllegalStateException("nou found @" + ShardBy.class.getSimpleName() + " in " + runtime.getMetaData().getDAOMetaData().getDAOClass().getName() + "#" + runtime.getMetaData().getMethod().getName()); } Object objectShardBy = runtime.getParameters().get(":" + (shardIndex + 1)); Number value; if (objectShardBy instanceof Number) { value = (Number) objectShardBy; } else { ShardBy annotationShardBy = runtime.getMetaData().getShardBy(); String propertyName = annotationShardBy.value(); PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor( objectShardBy.getClass(), propertyName); try { value = (Number) propertyDescriptor.getReadMethod().invoke(objectShardBy); } catch (Exception e) { throw new IllegalStateException(runtime.getMetaData().getDAOMetaData() .getDAOClass().getName() + "#" + runtime.getMetaData().getMethod().getName(), e); } } int shard = 1 + value.intValue() % shardCount; return term.substring(1) + "_" + shard; } }