青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cc

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  38 隨筆 :: 14 文章 :: 21 評(píng)論 :: 0 Trackbacks

1水平分庫(kù)

最近在做一個(gè)IM系統(tǒng),之前的舊系統(tǒng)沒有考慮到用戶量會(huì)增長(zhǎng)得這么龐大,導(dǎo)致現(xiàn)在數(shù)據(jù)庫(kù)性能瓶頸非常嚴(yán)重,迫切需要分庫(kù),用于減少每個(gè)庫(kù)的用戶數(shù)量,進(jìn)而分?jǐn)傌?fù)載,最終達(dá)到數(shù)據(jù)庫(kù)橫向擴(kuò)展的目的。

數(shù)據(jù)庫(kù)水平分庫(kù)是以用戶Id為分庫(kù)的依據(jù),同一個(gè)用戶的所有數(shù)據(jù)都在同一個(gè)庫(kù)上,每個(gè)庫(kù)有著相同的表結(jié)構(gòu)。為了實(shí)現(xiàn)開發(fā)人員來說對(duì)數(shù)據(jù)庫(kù)的透明訪問,分庫(kù)框架需要解決二個(gè)問題:
1、 方法參數(shù)中有用戶id的數(shù)據(jù)的新增,查詢及修改
2、 方法參數(shù)中無用戶id的數(shù)據(jù)的查詢

 

2用戶id

把用戶名和密碼所在的表定義為用戶表,用戶id即是用戶表中的惟一性標(biāo)識(shí)的整形值,如果用戶的用戶名只有一種方式,那么id可以是用戶名的hash值,此時(shí)用戶表也是分庫(kù)的;如果用戶的用戶名有多種方式,比如允許用戶使用email登陸,也允許用戶使用手機(jī)號(hào)碼登陸,那么用戶id應(yīng)該是用戶表中的遞增字段值,此時(shí)用戶表應(yīng)該是不分庫(kù)的,這時(shí)可以把用戶表獨(dú)立為另一個(gè)庫(kù),稱之為認(rèn)證庫(kù)。我們的項(xiàng)目應(yīng)用是屬于后者。

1 3 解決方案

3.1    說明

簡(jiǎn)單服務(wù)即為DAO,每個(gè)domain都對(duì)應(yīng)一個(gè)簡(jiǎn)單服務(wù),簡(jiǎn)單服務(wù)之間不允許互相依賴;復(fù)雜服務(wù)可以依賴多個(gè)簡(jiǎn)單服務(wù),但不能直接訪問數(shù)據(jù)庫(kù),復(fù)雜服務(wù)對(duì)數(shù)據(jù)庫(kù)的操作必須通過單簡(jiǎn)單服務(wù)。

使用hibernate作為訪問數(shù)據(jù)庫(kù)的中間層,結(jié)合SpringAop攔截方法,簡(jiǎn)單服務(wù)代理與簡(jiǎn)單服務(wù)實(shí)現(xiàn)相同的接口,一個(gè)簡(jiǎn)單服務(wù)對(duì)應(yīng)二個(gè)實(shí)例,一個(gè)引用動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接的sessionFactory,另一個(gè)引用Hibernate ShardssessionFactory

3.2    方法參數(shù)中有用戶Id

Spring Aop攔截簡(jiǎn)單服務(wù)代理的所有方法,如果方法的第一個(gè)參數(shù)為userid,則將userid

放到當(dāng)前線程中,并選擇引用動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接的sessionFactory的簡(jiǎn)單服務(wù)實(shí)例,在獲取數(shù)據(jù)庫(kù)連接時(shí)根據(jù)當(dāng)前線程的userid選擇相應(yīng)連接,流程如下:

 分庫(kù),有id

 

3.3    方法參數(shù)中無用戶Id

Spring Aop攔截簡(jiǎn)單服務(wù)代理的所有方法,如果方法的第一個(gè)參數(shù)為非userid,選擇引用Hibernate ShardssessionFactory的簡(jiǎn)單服務(wù)實(shí)例,遍歷所有數(shù)據(jù)庫(kù),并返回匯總后的數(shù)據(jù)。這種情況下只允許讀,不允許寫。流程如下:

分庫(kù),無id

1  4實(shí)現(xiàn)

4.1    簡(jiǎn)單服務(wù)代理

對(duì)每個(gè)簡(jiǎn)單服務(wù)用jdk動(dòng)態(tài)代理生成一個(gè)代理對(duì)像,復(fù)雜服務(wù)依賴代理對(duì)像。

4.2    實(shí)例化

在簡(jiǎn)單服務(wù)類上標(biāo)注@DetachDbService,則會(huì)產(chǎn)生三個(gè)實(shí)例(框架實(shí)現(xiàn)):

1.       簡(jiǎn)單服務(wù)代理實(shí)例

2.       引用動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接的sessionFactory的簡(jiǎn)單服務(wù)實(shí)例

3.       引用Hibernate ShardssessionFactory簡(jiǎn)單服務(wù)實(shí)例

4.3    方法參數(shù)

如果是到某個(gè)庫(kù)獲取數(shù)據(jù),則第一個(gè)參數(shù)必須為Long或者UseridAble類型,用于獲取userid

4.4    userid與數(shù)據(jù)庫(kù)關(guān)系

 

可選方案

優(yōu)點(diǎn)

缺點(diǎn)

按號(hào)段分

可部分遷移

數(shù)據(jù)分布不均

取模

數(shù)據(jù)分布均勻

遷移數(shù)據(jù)量是1/(n+1),不能按服務(wù)器性能分配

在認(rèn)證庫(kù)中保存數(shù)據(jù)庫(kù)配置

靈活,可部分遷移

查詢前需要先從數(shù)據(jù)庫(kù)或緩存中獲得此配置

 

總的來說,取模是最優(yōu)方案,但是考慮到服務(wù)器性能可能不一致,而又需要充分利用服務(wù)器資源,所以需要在取模的同時(shí)加上權(quán)重。比如現(xiàn)在有二臺(tái)數(shù)據(jù)庫(kù),權(quán)重為12,那么用戶id先對(duì)3取模,0的為第一臺(tái)服務(wù)器,12的為第二臺(tái)服務(wù)器。

 

 

4.5精確分頁

由于hibernate shards不能到某個(gè)庫(kù)或者其中的幾個(gè)庫(kù)中去查詢,并且它的分頁是先到所有的庫(kù)中將所有符合條件的數(shù)據(jù)取回到內(nèi)存中再進(jìn)行分頁,所以不可能使用它的分頁。      

hibernate shards到各個(gè)庫(kù)上查出符合條件的數(shù)目及數(shù)據(jù)庫(kù)標(biāo)識(shí)(標(biāo)識(shí)為查詢表中最小用戶id),返回結(jié)果后對(duì)標(biāo)識(shí)進(jìn)行排序(這樣確保同樣的查詢條件在翻頁的時(shí)候能夠以同樣的順序查詢數(shù)據(jù)庫(kù),以達(dá)到精確查詢的目的)。根據(jù)這個(gè)結(jié)果計(jì)算出每個(gè)數(shù)據(jù)庫(kù)取值的段,然后用動(dòng)態(tài)數(shù)據(jù)庫(kù)連接按之前排好的順序遍歷數(shù)據(jù)庫(kù)進(jìn)行查找,段為0的直接跳過,找滿結(jié)果則返回。

比如現(xiàn)在有3個(gè)庫(kù),要查詢所在地為深圳的用戶,通過hibernate shards查得數(shù)據(jù)如下:

 

 

深圳地區(qū)用戶總數(shù)

深圳特區(qū)用戶最小id

DB1

7

2

DB2

5

1

DB3

30

3

這時(shí)按用戶最小id排序結(jié)果是DB2,DB1,DB3

假設(shè)每頁10條記錄,

第一頁的數(shù)據(jù)是從DB2中取5條,DB1中取前5條,不需要到DB3去取

第二頁的數(shù)據(jù)是從DB1中取后2條,在DB3中取前8條,不需要到DB1中去取

第三頁數(shù)據(jù)是從DB3中取第9到第18條,不需要到DB1DB2中去取

… …

缺點(diǎn):不能精確排序

 

 

 

5關(guān)鍵代碼

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.annotation;   
  2.   
  3. import java.lang.annotation.Documented;   
  4. import java.lang.annotation.ElementType;   
  5. import java.lang.annotation.Retention;   
  6. import java.lang.annotation.RetentionPolicy;   
  7. import java.lang.annotation.Target;   
  8.   
  9. import org.springframework.beans.factory.annotation.Autowire;   
  10.   
  11. /**  
  12.  * 簡(jiǎn)單服務(wù)類實(shí)例化標(biāo)注  
  13.  * @author Jwin  
  14.  *  
  15.  */  
  16. @Retention(RetentionPolicy.RUNTIME)   
  17. @Target( { ElementType.TYPE })   
  18. @Documented  
  19. public @interface DetachDbService   
  20. {   
  21.     boolean lazy() default false;   
  22.     Autowire autoWire() default Autowire.BY_NAME;   
  23.     String init() default "";   
  24.     String destroy() default "";   
  25. }  
package com.konceptusa.infinet.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Autowire;
/**
* 簡(jiǎn)單服務(wù)類實(shí)例化標(biāo)注
* @author Jwin
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.TYPE })
@Documented
public @interface DetachDbService
{
boolean lazy() default false;
Autowire autoWire() default Autowire.BY_NAME;
String init() default "";
String destroy() default "";
}

 

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.annotation.handler;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.List;   
  5.   
  6. import org.apache.commons.logging.Log;   
  7. import org.apache.commons.logging.LogFactory;   
  8. import org.springframework.aop.framework.ProxyFactoryBean;   
  9. import org.springframework.beans.MutablePropertyValues;   
  10. import org.springframework.beans.factory.config.RuntimeBeanReference;   
  11. import org.springframework.beans.factory.support.RootBeanDefinition;   
  12.   
  13. import com.konceptusa.framework.annotation.IllegalConfigException;   
  14. import com.konceptusa.framework.annotation.spring.support.AbstractSpringListAnnotationHandler;   
  15. import com.konceptusa.framework.annotation.spring.support.SpringAnnotationUtils;   
  16. import com.konceptusa.infinet.annotation.DetachDbService;   
  17.   
  18. /**  
  19.  * 向spring中注冊(cè)簡(jiǎn)單服務(wù)代理實(shí)例,引用動(dòng)態(tài)數(shù)據(jù)庫(kù)連結(jié)的簡(jiǎn)單服務(wù)實(shí)例,引用hibernate shards的簡(jiǎn)單服務(wù)實(shí)例  
  20.  * @author Jwin  
  21.  *   
  22.  */  
  23. public class DetachDbServiceAnnotationHandler extends AbstractSpringListAnnotationHandler<DetachDbService>   
  24. {   
  25.     private final static String SESSIONFACTORYNAME = "sessionFactory";   
  26.     public final static String DYNAMIC_POSTFIX = "Dynamic";   
  27.     public final static String SHARDS_POSTFIX = "Shards";   
  28.     private final static String DETACHDBINTERCEPTOR = "detachDBInterceptor";   
  29.   
  30.     private final static Log LOG = LogFactory.getLog(DetachDbServiceAnnotationHandler.class);   
  31.   
  32.     public Class annotation()   
  33.     {   
  34.         return DetachDbService.class;   
  35.     }   
  36.   
  37.     @Override  
  38.     protected void handle(DetachDbService s, Class target)   
  39.     {   
  40.         String name = target.getSimpleName();   
  41.         if (!name.endsWith("ServiceImpl"))   
  42.         {   
  43.             throw new IllegalConfigException(target.getName()   
  44.                     + " is not a service bean.service bean 's class name must be end with 'ServiceImpl'");   
  45.         }   
  46.         name = getBeanName(name);   
  47.         String dynamicName = name + DYNAMIC_POSTFIX;   
  48.         String dynamicSessionFactory = SESSIONFACTORYNAME + DYNAMIC_POSTFIX;   
  49.         //生成動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接的簡(jiǎn)單服務(wù)實(shí)例   
  50.         createBean(s, target, dynamicName, dynamicSessionFactory);                 
  51.         String shardsName = name + SHARDS_POSTFIX;   
  52.         String shardsFactory = SESSIONFACTORYNAME + SHARDS_POSTFIX;   
  53.         //生成查詢所有數(shù)據(jù)庫(kù)的簡(jiǎn)單服務(wù)實(shí)例   
  54.         createBean(s, target, shardsName, shardsFactory);   
  55.         //生成簡(jiǎn)單服務(wù)代理類   
  56.         RootBeanDefinition definition = createBeanDefinition(s, ProxyFactoryBean.class, name);   
  57.         MutablePropertyValues mpv = new MutablePropertyValues();   
  58.         mpv.addPropertyValue("target"new RuntimeBeanReference(shardsName));   
  59.         List<String> interceptorNamesList = new ArrayList<String>();   
  60.         interceptorNamesList.add(DETACHDBINTERCEPTOR);   
  61.         mpv.addPropertyValue("interceptorNames", interceptorNamesList);   
  62.         definition.setPropertyValues(mpv);   
  63.         registerBeanDefinition(name, definition);          
  64.     }   
  65.   
  66.     private void createBean(DetachDbService s, Class target, String name, String sessionFactory)   
  67.     {   
  68.         RootBeanDefinition beanDefinition = createBeanDefinition(s, target, name);   
  69.         MutablePropertyValues mpv = new MutablePropertyValues();   
  70.         mpv.addPropertyValue(SESSIONFACTORYNAME, new RuntimeBeanReference(sessionFactory));   
  71.         beanDefinition.setPropertyValues(mpv);   
  72.         registerBeanDefinition(name, beanDefinition);   
  73.     }   
  74.   
  75.     private RootBeanDefinition createBeanDefinition(DetachDbService s, Class target, String name)   
  76.     {   
  77.         RootBeanDefinition definition = new RootBeanDefinition();   
  78.         definition.setAbstract(false);   
  79.         definition.setBeanClass(target);   
  80.         definition.setSingleton(true);   
  81.         definition.setLazyInit(s.lazy());   
  82.         definition.setAutowireCandidate(true);   
  83.         definition.setAutowireMode(s.autoWire().value());   
  84.   
  85.         if (!"".equals(s.init()))   
  86.         {   
  87.             definition.setInitMethodName(s.init().trim());   
  88.         }   
  89.         if (!"".equals(s.destroy()))   
  90.         {   
  91.             definition.setDestroyMethodName(s.destroy().trim());   
  92.         }   
  93.   
  94.         if (LOG.isDebugEnabled())   
  95.         {   
  96.             LOG.debug("Reader Bean Definition[" + definition + "] with name[" + name + "]");   
  97.         }   
  98.         SpringAnnotationUtils.readProperties(target, definition);   
  99.         return definition;   
  100.     }   
  101.   
  102.     private String getBeanName(String name)   
  103.     {   
  104.         name = name.substring(0, name.length() - "Impl".length());   
  105.         name = name.substring(01).toLowerCase() + name.substring(1, name.length());   
  106.         return name;   
  107.     }   
  108.   
  109. }  
package com.konceptusa.infinet.annotation.handler;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import com.konceptusa.framework.annotation.IllegalConfigException;
import com.konceptusa.framework.annotation.spring.support.AbstractSpringListAnnotationHandler;
import com.konceptusa.framework.annotation.spring.support.SpringAnnotationUtils;
import com.konceptusa.infinet.annotation.DetachDbService;
/**
* 向spring中注冊(cè)簡(jiǎn)單服務(wù)代理實(shí)例,引用動(dòng)態(tài)數(shù)據(jù)庫(kù)連結(jié)的簡(jiǎn)單服務(wù)實(shí)例,引用hibernate shards的簡(jiǎn)單服務(wù)實(shí)例
* @author Jwin
*
*/
public class DetachDbServiceAnnotationHandler extends AbstractSpringListAnnotationHandler<DetachDbService>
{
private final static String SESSIONFACTORYNAME = "sessionFactory";
public final static String DYNAMIC_POSTFIX = "Dynamic";
public final static String SHARDS_POSTFIX = "Shards";
private final static String DETACHDBINTERCEPTOR = "detachDBInterceptor";
private final static Log LOG = LogFactory.getLog(DetachDbServiceAnnotationHandler.class);
public Class annotation()
{
return DetachDbService.class;
}
@Override
protected void handle(DetachDbService s, Class target)
{
String name = target.getSimpleName();
if (!name.endsWith("ServiceImpl"))
{
throw new IllegalConfigException(target.getName()
+ " is not a service bean.service bean 's class name must be end with 'ServiceImpl'");
}
name = getBeanName(name);
String dynamicName = name + DYNAMIC_POSTFIX;
String dynamicSessionFactory = SESSIONFACTORYNAME + DYNAMIC_POSTFIX;
//生成動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接的簡(jiǎn)單服務(wù)實(shí)例
createBean(s, target, dynamicName, dynamicSessionFactory);
String shardsName = name + SHARDS_POSTFIX;
String shardsFactory = SESSIONFACTORYNAME + SHARDS_POSTFIX;
//生成查詢所有數(shù)據(jù)庫(kù)的簡(jiǎn)單服務(wù)實(shí)例
createBean(s, target, shardsName, shardsFactory);
//生成簡(jiǎn)單服務(wù)代理類
RootBeanDefinition definition = createBeanDefinition(s, ProxyFactoryBean.class, name);
MutablePropertyValues mpv = new MutablePropertyValues();
mpv.addPropertyValue("target", new RuntimeBeanReference(shardsName));
List<String> interceptorNamesList = new ArrayList<String>();
interceptorNamesList.add(DETACHDBINTERCEPTOR);
mpv.addPropertyValue("interceptorNames", interceptorNamesList);
definition.setPropertyValues(mpv);
registerBeanDefinition(name, definition);
}
private void createBean(DetachDbService s, Class target, String name, String sessionFactory)
{
RootBeanDefinition beanDefinition = createBeanDefinition(s, target, name);
MutablePropertyValues mpv = new MutablePropertyValues();
mpv.addPropertyValue(SESSIONFACTORYNAME, new RuntimeBeanReference(sessionFactory));
beanDefinition.setPropertyValues(mpv);
registerBeanDefinition(name, beanDefinition);
}
private RootBeanDefinition createBeanDefinition(DetachDbService s, Class target, String name)
{
RootBeanDefinition definition = new RootBeanDefinition();
definition.setAbstract(false);
definition.setBeanClass(target);
definition.setSingleton(true);
definition.setLazyInit(s.lazy());
definition.setAutowireCandidate(true);
definition.setAutowireMode(s.autoWire().value());
if (!"".equals(s.init()))
{
definition.setInitMethodName(s.init().trim());
}
if (!"".equals(s.destroy()))
{
definition.setDestroyMethodName(s.destroy().trim());
}
if (LOG.isDebugEnabled())
{
LOG.debug("Reader Bean Definition[" + definition + "] with name[" + name + "]");
}
SpringAnnotationUtils.readProperties(target, definition);
return definition;
}
private String getBeanName(String name)
{
name = name.substring(0, name.length() - "Impl".length());
name = name.substring(0, 1).toLowerCase() + name.substring(1, name.length());
return name;
}
}

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.detach.aop;   
  2.   
  3. import org.aopalliance.intercept.MethodInterceptor;   
  4. import org.aopalliance.intercept.MethodInvocation;   
  5. import org.apache.commons.logging.Log;   
  6. import org.apache.commons.logging.LogFactory;   
  7. import org.springframework.util.MethodInvoker;   
  8.   
  9. import com.konceptusa.framework.annotation.IllegalConfigException;   
  10. import com.konceptusa.framework.core.support.ObjectFactory;   
  11. import com.konceptusa.infinet.annotation.handler.DetachDbServiceAnnotationHandler;   
  12. import com.konceptusa.infinet.detach.UseridAble;   
  13. import com.konceptusa.infinet.detach.datasource.DataSourceIdContextHolder;   
  14. import com.konceptusa.infinet.detach.datasource.UseridContextHolder;   
  15.   
  16. /**  
  17.  * 分庫(kù)簡(jiǎn)單服務(wù)代理  
  18.  * @author Jwin  
  19.  *  
  20.  */  
  21. public class DetachDBInterceptor implements MethodInterceptor   
  22. {   
  23.     private final static Log LOG = LogFactory.getLog(DetachDBInterceptor.class);   
  24.     public Object invoke(MethodInvocation invoke) throws Throwable   
  25.     {   
  26.         int len = invoke.getArguments().length;   
  27.         Long id = null;   
  28.         if(len >= 1)   
  29.         {              
  30.             Object arg = invoke.getArguments()[0];   
  31.             if(arg instanceof UseridAble)   
  32.             {   
  33.                 UseridAble useridAble = (UseridAble) arg;   
  34.                 id = useridAble.getUserid();   
  35.             }   
  36.             else if(arg instanceof Long)   
  37.             {   
  38.                 id = (Long) arg;   
  39.             }   
  40.         }   
  41.         if(id != null)   
  42.         {   
  43.             UseridContextHolder.setUserid(id);   
  44.             try  
  45.             {              
  46.                 return invoke(invoke, id);   
  47.             }finally  
  48.             {   
  49.                 UseridContextHolder.removeUserid();   
  50.             }              
  51.         }   
  52.         else  
  53.         {   
  54.             return invoke(invoke, id);             
  55.         }   
  56.     }   
  57.     private Object invoke(MethodInvocation invoke, Long id) throws Throwable   
  58.     {   
  59.         String str = invoke.getThis().toString();   
  60.         int start = str.lastIndexOf(".");   
  61.         int end = str.lastIndexOf("@");   
  62.         String className = str.substring(start + 1, end);   
  63.         String postFix = DetachDbServiceAnnotationHandler.DYNAMIC_POSTFIX;   
  64.         if(id == null && DataSourceIdContextHolder.getDataSourceId() == null)   
  65.         {   
  66.             postFix = DetachDbServiceAnnotationHandler.SHARDS_POSTFIX;   
  67.         }   
  68.         String serviceName = className.substring(0,1).toLowerCase() + className.substring(1,className.length() - "Impl".length()) + postFix;   
  69.         if(LOG.isDebugEnabled())   
  70.             LOG.debug("select service " + serviceName + " for userid = " + id);   
  71.         Object service = ObjectFactory.getManagedObject(serviceName);   
  72.         if(service == null)   
  73.         {   
  74.             throw new IllegalConfigException("service name " + serviceName + " is not defined in spring context");   
  75.         }   
  76.         MethodInvoker invoker = new MethodInvoker();   
  77.         invoker.setArguments(invoke.getArguments());   
  78.         invoker.setTargetObject(service);   
  79.         invoker.setTargetMethod(invoke.getMethod().getName());   
  80.         invoker.prepare();   
  81.         return invoker.invoke();   
  82.     }   
  83.   
  84. }  
package com.konceptusa.infinet.detach.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.MethodInvoker;
import com.konceptusa.framework.annotation.IllegalConfigException;
import com.konceptusa.framework.core.support.ObjectFactory;
import com.konceptusa.infinet.annotation.handler.DetachDbServiceAnnotationHandler;
import com.konceptusa.infinet.detach.UseridAble;
import com.konceptusa.infinet.detach.datasource.DataSourceIdContextHolder;
import com.konceptusa.infinet.detach.datasource.UseridContextHolder;
/**
* 分庫(kù)簡(jiǎn)單服務(wù)代理
* @author Jwin
*
*/
public class DetachDBInterceptor implements MethodInterceptor
{
private final static Log LOG = LogFactory.getLog(DetachDBInterceptor.class);
public Object invoke(MethodInvocation invoke) throws Throwable
{
int len = invoke.getArguments().length;
Long id = null;
if(len >= 1)
{
Object arg = invoke.getArguments()[0];
if(arg instanceof UseridAble)
{
UseridAble useridAble = (UseridAble) arg;
id = useridAble.getUserid();
}
else if(arg instanceof Long)
{
id = (Long) arg;
}
}
if(id != null)
{
UseridContextHolder.setUserid(id);
try
{
return invoke(invoke, id);
}finally
{
UseridContextHolder.removeUserid();
}
}
else
{
return invoke(invoke, id);
}
}
private Object invoke(MethodInvocation invoke, Long id) throws Throwable
{
String str = invoke.getThis().toString();
int start = str.lastIndexOf(".");
int end = str.lastIndexOf("@");
String className = str.substring(start + 1, end);
String postFix = DetachDbServiceAnnotationHandler.DYNAMIC_POSTFIX;
if(id == null && DataSourceIdContextHolder.getDataSourceId() == null)
{
postFix = DetachDbServiceAnnotationHandler.SHARDS_POSTFIX;
}
String serviceName = className.substring(0,1).toLowerCase() + className.substring(1,className.length() - "Impl".length()) + postFix;
if(LOG.isDebugEnabled())
LOG.debug("select service " + serviceName + " for userid = " + id);
Object service = ObjectFactory.getManagedObject(serviceName);
if(service == null)
{
throw new IllegalConfigException("service name " + serviceName + " is not defined in spring context");
}
MethodInvoker invoker = new MethodInvoker();
invoker.setArguments(invoke.getArguments());
invoker.setTargetObject(service);
invoker.setTargetMethod(invoke.getMethod().getName());
invoker.prepare();
return invoker.invoke();
}
}

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.detach.datasource;   
  2.   
  3. import java.util.HashMap;   
  4. import java.util.List;   
  5. import java.util.Map;   
  6. import java.util.Properties;   
  7.   
  8. import javax.sql.DataSource;   
  9.   
  10. import org.apache.commons.lang.StringUtils;   
  11. import org.apache.commons.logging.Log;   
  12. import org.apache.commons.logging.LogFactory;   
  13. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;   
  14. import org.springframework.util.Assert;   
  15.   
  16. import com.konceptusa.framework.annotation.IllegalConfigException;   
  17. import com.konceptusa.infinet.detach.config.MultiHibernateProperties;   
  18. import com.konceptusa.infinet.detach.service.ISelectDBService;   
  19.   
  20. /**  
  21.  * 動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接基類  
  22.  * @author Jwin  
  23.  *   
  24.  */  
  25. public abstract class AbstractDynamicDataSource extends AbstractRoutingDataSource   
  26. {   
  27.     private final static Log LOG = LogFactory.getLog(AbstractDynamicDataSource.class);   
  28.     public final static int defaultDataSourceId = -1;   
  29.     protected MultiHibernateProperties multiHibernateProperties;   
  30.     protected ISelectDBService selectDBService;   
  31.     private String newWeights;   
  32.     private String oldWeights;   
  33.     private Map<Integer, DataSource> dataSourceMap = new HashMap<Integer, DataSource>();   
  34.     public void setSelectDBService(ISelectDBService selectDBService)   
  35.     {   
  36.         this.selectDBService = selectDBService;   
  37.     }   
  38.     public void setMultiHibernateProperties(MultiHibernateProperties multiHibernateProperties)   
  39.     {   
  40.         this.multiHibernateProperties = multiHibernateProperties;   
  41.     }   
  42.     @Override  
  43.     protected Object determineCurrentLookupKey()   
  44.     {   
  45.         Long id = UseridContextHolder.getUserid();   
  46.         return selectDBService.selectDb(id);   
  47.     }   
  48.        
  49.     @Override  
  50.     public void afterPropertiesSet()   
  51.     {   
  52.         LOG.info("init dynamic datasource start");   
  53.         Assert.notNull(multiHibernateProperties);   
  54.         Assert.notNull(selectDBService);   
  55.         List<Properties> properties = multiHibernateProperties.getShardProperties();   
  56.         Assert.notEmpty(properties);   
  57.         int dataSourceCount = 0;   
  58.         for(Properties p : properties)   
  59.         {   
  60.             dataSourceCount++;   
  61.             createDataSource(dataSourceMap, p);   
  62.         }   
  63.         createDefaultDataSource(dataSourceMap);   
  64.         selectDBService.setDefaultDataSourceId(defaultDataSourceId);   
  65.         selectDBService.setDataSourceCount(dataSourceCount);   
  66.         setTargetDataSources(dataSourceMap);   
  67.         setDefaultTargetDataSource(dataSourceMap.get(defaultDataSourceId));   
  68.         initWeight(dataSourceCount);   
  69.         super.afterPropertiesSet();   
  70.         LOG.info("init dynamic datasource success");   
  71.     }   
  72.     public void initWeight(int dataSourceCount)   
  73.     {   
  74.         Map<Integer, Integer> oldWeightMap = new HashMap<Integer, Integer>();   
  75.         Map<Integer, Integer> newWeightMap = new HashMap<Integer, Integer>();   
  76.         int totalOldWeight = 0;   
  77.         int totalNewWeight = 0;   
  78.         if(newWeights != null)   
  79.         {   
  80.             if(LOG.isInfoEnabled())   
  81.                 LOG.info("newWeights " + newWeights);   
  82.             String[] weights = StringUtils.split(newWeights,";");   
  83.             if(weights.length > dataSourceCount)   
  84.             {   
  85.                 throw new IllegalConfigException("newWeights's length ["+weights.length+"] can't be more than dataSourceCount["+dataSourceCount+"]");   
  86.             }   
  87.             for(int i=0;i<weights.length;i++)   
  88.             {   
  89.                 int w = Integer.parseInt(weights[i]);   
  90.                 for(int j=0;j<w;j++)   
  91.                 {   
  92.                     newWeightMap.put(totalNewWeight + j, i);   
  93.                 }   
  94.                 totalNewWeight += w;   
  95.             }   
  96.         }   
  97.         else  
  98.         {   
  99.             totalNewWeight = dataSourceCount;   
  100.             for(int i=0;i<dataSourceCount;i++)   
  101.             {   
  102.                 newWeightMap.put(i, i);   
  103.             }   
  104.         }   
  105.         if(oldWeights != null)   
  106.         {   
  107.             if(LOG.isInfoEnabled())   
  108.                 LOG.info("oldWeights " + oldWeights);   
  109.             String[] weights = StringUtils.split(oldWeights,";");   
  110.             if(weights.length > dataSourceCount)   
  111.             {   
  112.                 throw new IllegalConfigException("oldWeights's length ["+weights.length+"] can't be more than dataSourceCount["+dataSourceCount+"]");   
  113.             }   
  114.             for(int i=0;i<weights.length;i++)   
  115.             {   
  116.                 int w = Integer.parseInt(weights[i]);   
  117.                 for(int j=0;j<w;j++)   
  118.                 {   
  119.                     oldWeightMap.put(totalOldWeight + j, i);   
  120.                 }   
  121.                 totalOldWeight += w;   
  122.             }   
  123.         }   
  124.         else  
  125.         {   
  126.             totalOldWeight = dataSourceCount;   
  127.             for(int i=0;i<dataSourceCount;i++)   
  128.             {   
  129.                 oldWeightMap.put(i, i);   
  130.             }   
  131.         }   
  132.         if(LOG.isInfoEnabled())   
  133.             LOG.info("totalNewWeight " + totalNewWeight + " totalOldWeight " + totalOldWeight);   
  134.         selectDBService.setTotalNewWeight(totalNewWeight);   
  135.         selectDBService.setNewWeightIdMap(newWeightMap);   
  136.         selectDBService.setTotalOldWeight(totalOldWeight);   
  137.         selectDBService.setOldWeightIdMap(oldWeightMap);   
  138.     }   
  139.     protected abstract void createDataSource(Map<Integer, DataSource> dataSourceMap, Properties p);   
  140.     protected abstract void createDefaultDataSource(Map<Integer, DataSource> dataSourceMap);   
  141.     public void setNewWeights(String newWeights)   
  142.     {   
  143.         this.newWeights = newWeights;   
  144.     }   
  145.     public void setOldWeights(String oldWeights)   
  146.     {   
  147.         this.oldWeights = oldWeights;   
  148.     }   
  149.     public Map<Integer, DataSource> getDataSourceMap()   
  150.     {   
  151.         return dataSourceMap;   
  152.     }   
  153.   
  154. }  
package com.konceptusa.infinet.detach.datasource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.util.Assert;
import com.konceptusa.framework.annotation.IllegalConfigException;
import com.konceptusa.infinet.detach.config.MultiHibernateProperties;
import com.konceptusa.infinet.detach.service.ISelectDBService;
/**
* 動(dòng)態(tài)獲取數(shù)據(jù)庫(kù)連接基類
* @author Jwin
*
*/
public abstract class AbstractDynamicDataSource extends AbstractRoutingDataSource
{
private final static Log LOG = LogFactory.getLog(AbstractDynamicDataSource.class);
public final static int defaultDataSourceId = -1;
protected MultiHibernateProperties multiHibernateProperties;
protected ISelectDBService selectDBService;
private String newWeights;
private String oldWeights;
private Map<Integer, DataSource> dataSourceMap = new HashMap<Integer, DataSource>();
public void setSelectDBService(ISelectDBService selectDBService)
{
this.selectDBService = selectDBService;
}
public void setMultiHibernateProperties(MultiHibernateProperties multiHibernateProperties)
{
this.multiHibernateProperties = multiHibernateProperties;
}
@Override
protected Object determineCurrentLookupKey()
{
Long id = UseridContextHolder.getUserid();
return selectDBService.selectDb(id);
}
@Override
public void afterPropertiesSet()
{
LOG.info("init dynamic datasource start");
Assert.notNull(multiHibernateProperties);
Assert.notNull(selectDBService);
List<Properties> properties = multiHibernateProperties.getShardProperties();
Assert.notEmpty(properties);
int dataSourceCount = 0;
for(Properties p : properties)
{
dataSourceCount++;
createDataSource(dataSourceMap, p);
}
createDefaultDataSource(dataSourceMap);
selectDBService.setDefaultDataSourceId(defaultDataSourceId);
selectDBService.setDataSourceCount(dataSourceCount);
setTargetDataSources(dataSourceMap);
setDefaultTargetDataSource(dataSourceMap.get(defaultDataSourceId));
initWeight(dataSourceCount);
super.afterPropertiesSet();
LOG.info("init dynamic datasource success");
}
public void initWeight(int dataSourceCount)
{
Map<Integer, Integer> oldWeightMap = new HashMap<Integer, Integer>();
Map<Integer, Integer> newWeightMap = new HashMap<Integer, Integer>();
int totalOldWeight = 0;
int totalNewWeight = 0;
if(newWeights != null)
{
if(LOG.isInfoEnabled())
LOG.info("newWeights " + newWeights);
String[] weights = StringUtils.split(newWeights,";");
if(weights.length > dataSourceCount)
{
throw new IllegalConfigException("newWeights's length ["+weights.length+"] can't be more than dataSourceCount["+dataSourceCount+"]");
}
for(int i=0;i<weights.length;i++)
{
int w = Integer.parseInt(weights[i]);
for(int j=0;j<w;j++)
{
newWeightMap.put(totalNewWeight + j, i);
}
totalNewWeight += w;
}
}
else
{
totalNewWeight = dataSourceCount;
for(int i=0;i<dataSourceCount;i++)
{
newWeightMap.put(i, i);
}
}
if(oldWeights != null)
{
if(LOG.isInfoEnabled())
LOG.info("oldWeights " + oldWeights);
String[] weights = StringUtils.split(oldWeights,";");
if(weights.length > dataSourceCount)
{
throw new IllegalConfigException("oldWeights's length ["+weights.length+"] can't be more than dataSourceCount["+dataSourceCount+"]");
}
for(int i=0;i<weights.length;i++)
{
int w = Integer.parseInt(weights[i]);
for(int j=0;j<w;j++)
{
oldWeightMap.put(totalOldWeight + j, i);
}
totalOldWeight += w;
}
}
else
{
totalOldWeight = dataSourceCount;
for(int i=0;i<dataSourceCount;i++)
{
oldWeightMap.put(i, i);
}
}
if(LOG.isInfoEnabled())
LOG.info("totalNewWeight " + totalNewWeight + " totalOldWeight " + totalOldWeight);
selectDBService.setTotalNewWeight(totalNewWeight);
selectDBService.setNewWeightIdMap(newWeightMap);
selectDBService.setTotalOldWeight(totalOldWeight);
selectDBService.setOldWeightIdMap(oldWeightMap);
}
protected abstract void createDataSource(Map<Integer, DataSource> dataSourceMap, Properties p);
protected abstract void createDefaultDataSource(Map<Integer, DataSource> dataSourceMap);
public void setNewWeights(String newWeights)
{
this.newWeights = newWeights;
}
public void setOldWeights(String oldWeights)
{
this.oldWeights = oldWeights;
}
public Map<Integer, DataSource> getDataSourceMap()
{
return dataSourceMap;
}
}

 

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.detach.datasource;   
  2.   
  3. import java.beans.PropertyVetoException;   
  4. import java.util.Map;   
  5. import java.util.Properties;   
  6.   
  7. import javax.sql.DataSource;   
  8.   
  9. import org.apache.commons.logging.Log;   
  10. import org.apache.commons.logging.LogFactory;   
  11.   
  12. import com.konceptusa.framework.annotation.IllegalConfigException;   
  13. import com.konceptusa.infinet.detach.config.MultiHibernateProperties;   
  14. import com.mchange.v2.c3p0.ComboPooledDataSource;   
  15.   
  16. /**  
  17.  * 基于c3p0連接池的動(dòng)態(tài)獲取連接類  
  18.  * @author Jwin  
  19.  *   
  20.  */  
  21. public class DynamicC3p0DataSource extends AbstractDynamicDataSource   
  22. {   
  23.     private final static Log LOG = LogFactory.getLog(DynamicC3p0DataSource.class);   
  24.     private int initialSize = 1;   
  25.     private int maxActive = 1;   
  26.     private int minActive = 1;   
  27.     private int maxIdleTime = 30;   
  28.     private String automaticTestTable = "Test";   
  29.     private int acquireIncrement = 3;   
  30.     private int maxStatements = 100;   
  31.     private int maxStatementsPerConnection = 3;   
  32.     private int numHelperThreads = 3;   
  33.     private int idleConnectionTestPeriod = 30;   
  34.     protected void createDefaultDataSource(Map<Integer, DataSource> dataSourceMap)   
  35.     {   
  36.         ComboPooledDataSource dataSource = new ComboPooledDataSource();   
  37.         dataSource.setUser("sa");   
  38.         dataSource.setPassword("");   
  39.         dataSource.setJdbcUrl("jdbc:hsqldb:mem:" + getClass().getSimpleName().toLowerCase());   
  40.         try  
  41.         {   
  42.             dataSource.setDriverClass("org.hsqldb.jdbcDriver");   
  43.         } catch (PropertyVetoException e)   
  44.         {   
  45.             throw new IllegalConfigException(e);   
  46.         }   
  47.         dataSource.setInitialPoolSize(initialSize);   
  48.         dataSource.setMaxPoolSize(maxActive);   
  49.         dataSource.setMinPoolSize(minActive);   
  50.         dataSource.setMaxIdleTime(maxIdleTime);   
  51.         dataSource.setAcquireIncrement(acquireIncrement);   
  52.         dataSource.setNumHelperThreads(numHelperThreads);   
  53.         dataSource.setAutomaticTestTable(automaticTestTable);   
  54.         dataSource.setMaxStatements(maxStatements);   
  55.         dataSource.setMaxStatementsPerConnection(maxStatementsPerConnection);   
  56.         dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);   
  57.         dataSourceMap.put(defaultDataSourceId, dataSource);   
  58.     }   
  59.     @Override  
  60.     protected void createDataSource(Map<Integer, DataSource> dataSourceMap, Properties p)   
  61.     {   
  62.         ComboPooledDataSource dataSource = new ComboPooledDataSource();   
  63.         dataSource.setJdbcUrl(p.getProperty(MultiHibernateProperties.connectionUrlKey));   
  64.         LOG.info("init datasource url " + dataSource.getJdbcUrl());   
  65.         dataSource.setUser(p.getProperty(MultiHibernateProperties.connectionUsernameKey));   
  66.         dataSource.setPassword(p.getProperty(MultiHibernateProperties.connectionPasswordKey));   
  67.         try  
  68.         {   
  69.             dataSource.setDriverClass(p.getProperty(MultiHibernateProperties.connectionDriverClassKey));   
  70.         } catch (PropertyVetoException e)   
  71.         {   
  72.             throw new IllegalConfigException(e);   
  73.         }   
  74.         dataSource.setInitialPoolSize(initialSize);   
  75.         dataSource.setMaxPoolSize(maxActive);   
  76.         dataSource.setMinPoolSize(minActive);   
  77.         dataSource.setMaxIdleTime(maxIdleTime);   
  78.         dataSource.setAcquireIncrement(acquireIncrement);   
  79.         dataSource.setNumHelperThreads(numHelperThreads);   
  80.         dataSource.setAutomaticTestTable(automaticTestTable);   
  81.         dataSource.setMaxStatements(maxStatements);   
  82.         dataSource.setMaxStatementsPerConnection(maxStatementsPerConnection);   
  83.         dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);   
  84.         String id = p.getProperty(MultiHibernateProperties.shardIdKey);   
  85.         dataSourceMap.put(Integer.parseInt(id), dataSource);   
  86.     }   
  87.     public void setInitialSize(int initialSize)   
  88.     {   
  89.         this.initialSize = initialSize;   
  90.     }   
  91.     public void setMaxActive(int maxActive)   
  92.     {   
  93.         this.maxActive = maxActive;   
  94.     }   
  95.     public void setMaxIdleTime(int maxIdle)   
  96.     {   
  97.         this.maxIdleTime = maxIdle;   
  98.     }      
  99.     public void setAcquireIncrement(int acquireIncrement)   
  100.     {   
  101.         this.acquireIncrement = acquireIncrement;   
  102.     }   
  103.     public void setMaxStatements(int maxStatements)   
  104.     {   
  105.         this.maxStatements = maxStatements;   
  106.     }   
  107.     public void setMaxStatementsPerConnection(int maxStatementsPerConnection)   
  108.     {   
  109.         this.maxStatementsPerConnection = maxStatementsPerConnection;   
  110.     }   
  111.     public void setNumHelperThreads(int numHelperThreads)   
  112.     {   
  113.         this.numHelperThreads = numHelperThreads;   
  114.     }   
  115.     public void setAutomaticTestTable(String automaticTestTable)   
  116.     {   
  117.         this.automaticTestTable = automaticTestTable;   
  118.     }   
  119.     public void setMinActive(int minActive)   
  120.     {   
  121.         this.minActive = minActive;   
  122.     }   
  123.     public void setIdleConnectionTestPeriod(int idleConnectionTestPeriod)   
  124.     {   
  125.         this.idleConnectionTestPeriod = idleConnectionTestPeriod;   
  126.     }   
  127.        
  128.   
  129. }  
package com.konceptusa.infinet.detach.datasource;
import java.beans.PropertyVetoException;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.konceptusa.framework.annotation.IllegalConfigException;
import com.konceptusa.infinet.detach.config.MultiHibernateProperties;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 基于c3p0連接池的動(dòng)態(tài)獲取連接類
* @author Jwin
*
*/
public class DynamicC3p0DataSource extends AbstractDynamicDataSource
{
private final static Log LOG = LogFactory.getLog(DynamicC3p0DataSource.class);
private int initialSize = 1;
private int maxActive = 1;
private int minActive = 1;
private int maxIdleTime = 30;
private String automaticTestTable = "Test";
private int acquireIncrement = 3;
private int maxStatements = 100;
private int maxStatementsPerConnection = 3;
private int numHelperThreads = 3;
private int idleConnectionTestPeriod = 30;
protected void createDefaultDataSource(Map<Integer, DataSource> dataSourceMap)
{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("sa");
dataSource.setPassword("");
dataSource.setJdbcUrl("jdbc:hsqldb:mem:" + getClass().getSimpleName().toLowerCase());
try
{
dataSource.setDriverClass("org.hsqldb.jdbcDriver");
} catch (PropertyVetoException e)
{
throw new IllegalConfigException(e);
}
dataSource.setInitialPoolSize(initialSize);
dataSource.setMaxPoolSize(maxActive);
dataSource.setMinPoolSize(minActive);
dataSource.setMaxIdleTime(maxIdleTime);
dataSource.setAcquireIncrement(acquireIncrement);
dataSource.setNumHelperThreads(numHelperThreads);
dataSource.setAutomaticTestTable(automaticTestTable);
dataSource.setMaxStatements(maxStatements);
dataSource.setMaxStatementsPerConnection(maxStatementsPerConnection);
dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);
dataSourceMap.put(defaultDataSourceId, dataSource);
}
@Override
protected void createDataSource(Map<Integer, DataSource> dataSourceMap, Properties p)
{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl(p.getProperty(MultiHibernateProperties.connectionUrlKey));
LOG.info("init datasource url " + dataSource.getJdbcUrl());
dataSource.setUser(p.getProperty(MultiHibernateProperties.connectionUsernameKey));
dataSource.setPassword(p.getProperty(MultiHibernateProperties.connectionPasswordKey));
try
{
dataSource.setDriverClass(p.getProperty(MultiHibernateProperties.connectionDriverClassKey));
} catch (PropertyVetoException e)
{
throw new IllegalConfigException(e);
}
dataSource.setInitialPoolSize(initialSize);
dataSource.setMaxPoolSize(maxActive);
dataSource.setMinPoolSize(minActive);
dataSource.setMaxIdleTime(maxIdleTime);
dataSource.setAcquireIncrement(acquireIncrement);
dataSource.setNumHelperThreads(numHelperThreads);
dataSource.setAutomaticTestTable(automaticTestTable);
dataSource.setMaxStatements(maxStatements);
dataSource.setMaxStatementsPerConnection(maxStatementsPerConnection);
dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);
String id = p.getProperty(MultiHibernateProperties.shardIdKey);
dataSourceMap.put(Integer.parseInt(id), dataSource);
}
public void setInitialSize(int initialSize)
{
this.initialSize = initialSize;
}
public void setMaxActive(int maxActive)
{
this.maxActive = maxActive;
}
public void setMaxIdleTime(int maxIdle)
{
this.maxIdleTime = maxIdle;
}
public void setAcquireIncrement(int acquireIncrement)
{
this.acquireIncrement = acquireIncrement;
}
public void setMaxStatements(int maxStatements)
{
this.maxStatements = maxStatements;
}
public void setMaxStatementsPerConnection(int maxStatementsPerConnection)
{
this.maxStatementsPerConnection = maxStatementsPerConnection;
}
public void setNumHelperThreads(int numHelperThreads)
{
this.numHelperThreads = numHelperThreads;
}
public void setAutomaticTestTable(String automaticTestTable)
{
this.automaticTestTable = automaticTestTable;
}
public void setMinActive(int minActive)
{
this.minActive = minActive;
}
public void setIdleConnectionTestPeriod(int idleConnectionTestPeriod)
{
this.idleConnectionTestPeriod = idleConnectionTestPeriod;
}
}

 

Java代碼 復(fù)制代碼
  1. package com.konceptusa.infinet.imsupport.detach;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Collection;   
  5. import java.util.Collections;   
  6. import java.util.List;   
  7.   
  8. import org.apache.commons.logging.Log;   
  9. import org.apache.commons.logging.LogFactory;   
  10. import org.springframework.transaction.annotation.Propagation;   
  11. import org.springframework.transaction.annotation.Transactional;   
  12.   
  13. import com.konceptusa.framework.annotation.IllegalConfigException;   
  14. import com.konceptusa.framework.core.dao.HibernateQueryListCallback;   
  15. import com.konceptusa.framework.core.dao.hql.Hql;   
  16. import com.konceptusa.framework.core.service.BaseServiceSupport;   
  17. import com.konceptusa.framework.core.service.Page;   
  18. import com.konceptusa.framework.core.support.ObjectFactory;   
  19. import com.konceptusa.infinet.annotation.handler.DetachDbServiceAnnotationHandler;   
  20. import com.konceptusa.infinet.detach.CountId;   
  21. import com.konceptusa.infinet.detach.CountIdComparetor;   
  22. import com.konceptusa.infinet.detach.MagrateAble;   
  23. import com.konceptusa.infinet.detach.QueryListAble;   
  24. import com.konceptusa.infinet.detach.datasource.UseridContextHolder;   
  25.   
  26. /**  
  27.  * 多個(gè)數(shù)據(jù)庫(kù)綜合查詢,簡(jiǎn)單服務(wù)類父類  
  28.  * @author Jwin  
  29.  *  
  30.  * @param <T>  
  31.  */  
  32. @Transactional(readOnly=true, rollbackFor = Exception.class)   
  33. public abstract class BaseServiceSupportForMulti<T> extends BaseServiceSupport<T> implements QueryListAble<T>,MagrateAble<T>   
  34. {   
  35.     private final static Log LOG = LogFactory.getLog(BaseServiceSupportForMulti.class);   
  36.     @Override  
  37.     protected int findCountByHql(Hql hql)   
  38.     {   
  39.         List<Long> countList = (List<Long>) getHibernateTemplate().execute(   
  40.                 new HibernateQueryListCallback(new Hql("select count(*) "  
  41.                         + hql.getHql(), hql.getCache(), hql.getParameters())));   
  42.         Long counts = 0L;   
  43.         for(Long count : countList)   
  44.         {   
  45.             counts += count;   
  46.         }   
  47.         return counts.intValue();   
  48.     }   
  49.     @Transactional(readOnly=true, rollbackFor = Exception.class,propagation=Propagation.NOT_SUPPORTED)   
  50.     public List<T> queryList(Hql hql, int from, int offset)   
  51.     {   
  52.         return queryListByHql(hql, from, offset);   
  53.     }   
  54.   
  55.     public List<CountId> queryCount(Hql hql)   
  56.     {   
  57.         List<Object[]> list = queryListByHql(hql);   
  58.         List<CountId> countList = new ArrayList<CountId>(list.size());    
  59.         for(Object[] l : list)   
  60.         {   
  61.             if(l[1] != null)   
  62.             {                  
  63.                 CountId count = new CountId((Long) l[1],(Long)l[0]);   
  64.                 countList.add(count);   
  65.             }   
  66.         }   
  67.         Collections.sort(countList, new CountIdComparetor());   
  68.         return countList;   
  69.     }   
  70.     protected String getBeanName(String name)   
  71.     {   
  72.         name = name.substring(0, name.length() - "Impl".length());   
  73.         name = name.substring(01).toLowerCase() + name.substring(1, name.length());   
  74.         return name;   
  75.     }   
  76.     protected Page queryPageByHql(Hql hql,String useridName, int start, int offset)   
  77.     {   
  78.         Hql countHql = new Hql("select count(*),min(" + useridName + ") "  
  79.                 + hql.getHql(), hql.getCache(), hql.getParameters());   
  80.         return queryPageByHql(countHql, hql, start, offset);   
  81.     }   
  82.     //先查出各個(gè)數(shù)據(jù)庫(kù)的總數(shù)及標(biāo)識(shí),然后對(duì)標(biāo)識(shí)進(jìn)行排序,最后根據(jù)這個(gè)結(jié)果遍歷數(shù)據(jù)庫(kù)進(jìn)行分頁查找,找滿結(jié)果則返回。   
  83.     private Page queryPageByHql(Hql countHql,Hql listHql,int start, int offset)   
  84.     {   
  85.         QueryListAble<T> serviceShards = getShardsService();   
  86.         QueryListAble<T> serviceDynamic = getDynamicService();   
  87.         List<CountId> countList = serviceShards.queryCount(countHql);   
  88.         //相對(duì)于當(dāng)前之前所有數(shù)據(jù)庫(kù)的總數(shù)偏移   
  89.         int totalCount = 0;   
  90.         //相對(duì)于所有數(shù)據(jù)庫(kù)的結(jié)束偏移   
  91.         int end = start + offset;   
  92.         //相對(duì)于當(dāng)前數(shù)據(jù)庫(kù)的開始偏移量   
  93.         int startRelative = -1;   
  94.         List<T> queryList = new ArrayList<T>(offset);   
  95.         for(CountId count : countList)   
  96.         {   
  97.             totalCount += count.getCount();   
  98.             //之前所有庫(kù)總數(shù)小于開始偏移量,繼續(xù)下一個(gè)數(shù)據(jù)庫(kù)   
  99.             if(totalCount < start)   
  100.             {   
  101.                 continue;   
  102.             }   
  103.             //之前所有庫(kù)總數(shù)第一次大于開始偏移量   
  104.             if(startRelative == -1)   
  105.             {                  
  106.                 startRelative = count.getCount().intValue() - (totalCount - start);   
  107.             }   
  108.             else  
  109.             {   
  110.                 startRelative = 0;   
  111.             }   
  112.             int relativeCount = totalCount - end;   
  113.             if(relativeCount >= 0)   
  114.             {   
  115.                 UseridContextHolder.setUserid(count.getId());   
  116.                 try  
  117.                 {   
  118.                     //計(jì)算相對(duì)于當(dāng)前庫(kù)的偏移   
  119.                     int offsetRelative = count.getCount().intValue() - relativeCount - startRelative;   
  120.                     LOG.debug("query from " + startRelative + " offset " + offsetRelative + " for min(userid)=" + count.getId());   
  121.                     queryList.addAll(serviceDynamic.queryList(listHql, startRelative, offsetRelative));                    
  122.                 }finally  
  123.                 {   
  124.                     UseridContextHolder.removeUserid();   
  125.                 }   
  126.                 break;   
  127.             }   
  128.             UseridContextHolder.setUserid(count.getId());   
  129.             try  
  130.             {                  
  131.                 //計(jì)算相對(duì)于當(dāng)前庫(kù)的偏移   
  132.                 int offsetRelative = totalCount - startRelative;   
  133.                 LOG.debug("query from " + startRelative + " offset " + offsetRelative + " for min(userid)=" + count.getId());   
  134.                 queryList.addAll(serviceDynamic.queryList(listHql, startRelative, offsetRelative));                    
  135.             } finally  
  136.             {   
  137.                 UseridContextHolder.removeUserid();   
  138.             }   
  139.         }   
  140.         totalCount = 0;   
  141.         for(CountId count : countList)   
  142.         {   
  143.             totalCount += count.getCount();   
  144.         }   
  145.         return new Page<T>(totalCount, queryList);                   
  146.     }   
  147.     protected Page queryPageByHql(String hqlstr,String useridName, int start, int offset,Object ... values)   
  148.     {   
  149.         Hql listHql = Hql.createIndexHql(  
posted on 2009-10-14 23:42 醒目西西 閱讀(1839) 評(píng)論(2)  編輯 收藏 引用

評(píng)論

# re: 數(shù)據(jù)庫(kù)水平分庫(kù)框架設(shè)計(jì) 2009-10-14 23:43 醒目西西
http://jwin.javaeye.com/blog/231846  回復(fù)  更多評(píng)論
  

# re: 數(shù)據(jù)庫(kù)水平分庫(kù)框架設(shè)計(jì) 2013-06-01 09:16 aaaaaaaaaaaaaaaaaaaa
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq  回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品免费区二区三区观看| 欧美区一区二区三区| 激情视频一区二区| 久久av在线| 欧美91大片| 亚洲女性裸体视频| 国产精品久久久久国产a级| 免费国产一区二区| 亚洲欧美成人一区二区三区| 亚洲免费av电影| 极品av少妇一区二区| 国内成人精品2018免费看| 欧美日韩一区二区在线| 亚洲国产欧美一区二区三区丁香婷| 国产视频在线观看一区二区三区| 午夜精品成人在线| 性做久久久久久久免费看| 欧美亚洲成人精品| 亚洲精品一区在线观看| 中文一区在线| 国产综合久久| 欧美日韩高清在线| 午夜久久久久| 亚洲国产日韩美| 亚洲欧美国产高清va在线播| 韩国欧美一区| 国产精品久久久亚洲一区| 欧美日韩国产一区| 欧美mv日韩mv国产网站app| 亚洲一区网站| 亚洲小说春色综合另类电影| 中文有码久久| 亚洲视频碰碰| 新狼窝色av性久久久久久| 亚洲影院在线| 欧美怡红院视频一区二区三区| 亚洲另类自拍| 亚洲综合久久久久| 9国产精品视频| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 亚洲国产日韩一区| 国产一区二区三区久久 | 亚洲特色特黄| 欧美理论电影网| 欧美一区二区成人| 亚洲精选视频在线| 午夜日韩激情| 浪潮色综合久久天堂| 国模大胆一区二区三区| 亚洲视频电影在线| 亚洲一区二区高清| 蜜臀99久久精品久久久久久软件| 欧美日韩网址| 日韩一区二区精品视频| 久久精品亚洲一区二区| 欧美久久久久久| 亚洲国产精品日韩| 亚洲日本电影| 狠狠狠色丁香婷婷综合久久五月 | 亚洲乱码国产乱码精品精天堂 | 欧美aa国产视频| 在线成人av| 国产一区二区日韩精品| 久久精品噜噜噜成人av农村| 亚洲激情第一区| 欧美亚洲免费电影| 久久久久久夜| 牛人盗摄一区二区三区视频| 亚洲国产另类久久久精品极度| 久久国产精品亚洲va麻豆| 久久成人在线| 亚洲精品在线电影| 亚洲欧美国产视频| 欧美精品久久久久a| 国产精品日韩欧美综合| 欧美午夜视频一区二区| 欧美日韩成人网| 亚洲日本久久| 在线午夜精品自拍| 欧美在线一级va免费观看| 一区二区三区久久精品| 亚洲永久精品国产| 亚洲欧美一区在线| 亚洲欧美日本日韩| 亚洲女优在线| 久久久久成人精品| 亚洲精品国产精品国自产观看| 欧美日韩成人在线| 猛干欧美女孩| 国产精品一区二区男女羞羞无遮挡 | 国产亚洲一区二区三区在线观看 | 香蕉成人久久| 久久国产视频网站| 亚洲精品美女| 欧美高清视频在线播放| 久久精品国产清自在天天线| 99re在线精品| 欧美三级视频在线| 久久久久在线观看| 在线视频日韩精品| 亚洲欧美伊人| 亚洲国产欧美一区| 亚洲一区国产一区| 亚洲午夜伦理| 老鸭窝亚洲一区二区三区| 国产精品久久久久久户外露出| 国产一区二区欧美日韩| 亚洲激情欧美| 日韩系列在线| 久久九九精品99国产精品| 欧美激情精品久久久久久免费印度 | 亚洲精品中文字幕在线| 激情婷婷欧美| 亚洲成色777777在线观看影院| 午夜精品一区二区三区在线视| 国产一区二区看久久| 久久成人精品视频| 美日韩精品免费| 亚洲精品日韩综合观看成人91| 99re成人精品视频| 在线看片第一页欧美| 亚洲视屏一区| 一区二区三区免费观看| 久久精品91久久香蕉加勒比| 亚洲午夜精品一区二区| 欧美激情在线| 欧美激情欧美狂野欧美精品| 一区二区亚洲| 亚洲欧美日韩视频一区| 亚洲素人在线| 欧美三区在线观看| 一区二区av在线| 欧美怡红院视频| 欧美在线免费观看视频| 亚洲电影免费观看高清完整版在线 | 亚洲高清资源综合久久精品| 亚洲人成网站999久久久综合| 亚洲激情另类| 免费亚洲电影在线| 欧美激情按摩在线| 久久精品国产综合精品| 影音先锋久久久| 欧美国产精品一区| 欧美日韩精品二区| 亚洲香蕉网站| 在线性视频日韩欧美| 狠狠入ady亚洲精品| 亚洲免费不卡| 亚洲麻豆一区| 免费永久网站黄欧美| 亚洲人成7777| 久久久久久久久久码影片| 欧美日韩一区二区三| 美女视频黄a大片欧美| 久久裸体视频| 亚洲视屏在线播放| 亚洲免费观看| 久久精品一区二区| 美女露胸一区二区三区| 久久久久久久91| 午夜亚洲福利在线老司机| 欧美日韩国产专区| 欧美+亚洲+精品+三区| 国产精品国产三级国产专区53 | 欧美亚洲三级| 欧美成人午夜剧场免费观看| 日韩西西人体444www| 国产香蕉久久精品综合网| 久久久人成影片一区二区三区 | 久久大综合网| 日韩视频不卡| 欧美大片免费观看| 欧美在线视频观看| 久久国产天堂福利天堂| 99在线|亚洲一区二区| 亚洲国产视频一区| 99天天综合性| 久久综合久久美利坚合众国| 亚洲麻豆一区| 欧美成人激情视频免费观看| 国产精品一区免费观看| 99精品久久免费看蜜臀剧情介绍| 午夜激情综合网| 欧美高清视频一二三区| 亚洲国产欧美日韩另类综合| 久久精品五月婷婷| 亚洲在线视频免费观看| 午夜综合激情| 久久久久久一区| 欧美视频在线观看 亚洲欧| 99视频在线观看一区三区| 亚洲精品日韩在线观看| 亚洲免费成人| 欧美在线视频网站| 欧美aa国产视频| 国产亚洲综合性久久久影院| 亚洲大黄网站| 小黄鸭精品密入口导航| 最新国产成人av网站网址麻豆| 一区二区三区欧美视频|