跨db的动态数据源的transaction- 2.动态数据源

来源:互联网 发布:linux禁用网卡 编辑:程序博客网 时间:2024/06/05 01:50


DynamicDataSource 初始化时会从dynamicDataSourceManager里面将所有数据源读入到dynamicDataSource 的TargetDataSources. 从而取代了在springcontext中配置它的targetDataSources。

 

@Component("dynamicDataSource")public class DynamicDataSource extends AbstractRoutingDataSource implements InitializingBean{@Autowired@Qualifier("dynamicDataSourceManager")IDynamicDataSourceManager dynamicDataSourceManager;@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSourceType();}public void afterPropertiesSet() {if(dynamicDataSourceManager==null){logger.info("property dynamicDataSourceManager is unset.");return ;}Assert.notNull(dynamicDataSourceManager,"Property 'dynamicDataSourceManager' is Null");Map<Object,Object> targetDS=new HashMap<Object,Object>();for(ShardDataSource ds:dynamicDataSourceManager.getAllDataSources()){targetDS.put(ds.getId(),ds);}this.setTargetDataSources(targetDS);this.setDefaultTargetDataSource(dynamicDataSourceManager.getDefaultDataSource());super.afterPropertiesSet();}}

如果仅是使用动态数据源,将DynamicDataSource配置到sqlSessionFactory的datasource 属性中,然后在DAO里面先用DataSourceContextHolder.setDataSourceType()指定数据源即可。

根据http://www.itblog8.cn/java/20130425101.html,在使用transaction是,需要每个数据源一个独立的SqlSessionFactory。然后通过getSqlSession来实现动态切换。

其中TargetSqlSessionFactorys可以在spring context里面配置。此处是从DynamicSqlSessionFactory里面读取。该类负责为每个datasource创建一个新的SqlSessionFactory.

public class DynamicSqlSessionDaoSupport extends JdbcDaoSupport implements InitializingBean{private static Logger logger=(Logger) LoggerFactory.getLogger(DynamicSqlSessionDaoSupport.class);private Map<String,SqlSessionFactory> targetSqlSessionFactorys;private SqlSessionFactory defaultTargetSqlSessionFactory;private SqlSession sqlSession;private boolean externalSqlSession;@Autowired@Qualifier("nsDefaultSqlSessionFactory")private DynamicSqlSessionFactoryBean dynamicFactoryBean;public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){if(!this.externalSqlSession){this.sqlSession=new SqlSessionTemplate(sqlSessionFactory);}}public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate){this.sqlSession=sqlSessionTemplate;this.externalSqlSession=true;} /**     * Users should use this method to get a SqlSession to call its statement methods     * This is SqlSession is managed by spring. Users should not commit/rollback/close it     * because it will be automatically done.     * Note:Mybatis use SqlSessionFacory as Lock key @cmei     * @return Spring managed thread safe SqlSession      */    public final SqlSession getSqlSession() {;     if(targetSqlSessionFactorys!=null){     String dataSourceID = DataSourceContextHolder.getDataSourceType();    SqlSessionFactory  targetSqlSessionFactory=targetSqlSessionFactorys.get(dataSourceID);    if(targetSqlSessionFactory==null){    logger.warn("Default sqlSessionFactory is used!");    setSqlSessionFactory(defaultTargetSqlSessionFactory);    }else{    setSqlSessionFactory(targetSqlSessionFactory);    }        }else{    setSqlSessionFactory(defaultTargetSqlSessionFactory);    }    return this.sqlSession;    }@Overrideprotected void checkDaoConfig() throws IllegalArgumentException {Assert.notNull(this.dynamicFactoryBean, "Property 'dynamicFactoryBean' is required");targetSqlSessionFactorys=this.dynamicFactoryBean.getTargetSqlSessionFactorys();this.defaultTargetSqlSessionFactory=this.dynamicFactoryBean.getDefaultTargetSqlSessionFactory();}public void setTargetSqlSessionFactorys(Map<String,SqlSessionFactory> targetSqlSessionFactorys){this.targetSqlSessionFactorys=targetSqlSessionFactorys;}public void setDefaultTargetSqlSessionFactory(SqlSessionFactory defaultTargetSqlSessionFactory){this.defaultTargetSqlSessionFactory=defaultTargetSqlSessionFactory;}public SqlSessionFactory getDefaultTargetSqlSessionFactory(){return this.defaultTargetSqlSessionFactory;}}</pre><p><br />先参考:<a href="http://www.itblog8.cn/java/20130425101.html" target="_blank">http://www.itblog8.cn/java/20130425101.html</a></p><pre class="java" name="code">public class DataSourceContextHolder {private static final ThreadLocal<String> contextHolder=new ThreadLocal<String>();/** * @param dsIndex */public static void setDataSourceType(int dsIndex,DataSourceGroup dsGroup){contextHolder.set(ShardDataSource.getDataSourceId(dsIndex, dsGroup));}public static String getDataSourceType(){return contextHolder.get();}public static void clearDataSourceType(){contextHolder.remove();}}</pre>

为每个datasource创建自己的SqlSessionFactory:

/** * To sync transaction at dynamic data source, creating separate <code>SqlSessionFactory</code> for each data source is necessary. * This class 's will create SqlSessionFactory dynamically and store them by cloning <code>Configure</code> from defaultSqlSessionFactory. * Note that please set <code>DataSourceContextHolder</code> before using transaction. * @author cmei * */public class DynamicSqlSessionFactoryBean extends SqlSessionFactoryBean implements InitializingBean{private static Logger logger=(Logger) LoggerFactory.getLogger(DynamicSqlSessionFactoryBean.class);private Map<String,SqlSessionFactory> targetSqlSessionFactorys;private SqlSessionFactory defaultTargetSqlSessionFactory;private Resource[] mapperLocations;private String typeAliasesPackage;private IDynamicDataSourceManager dynamicDataSourceManager;public void setDynamicDataSourceManager(IDynamicDataSourceManager dynamicDataSourceManager){this.dynamicDataSourceManager=dynamicDataSourceManager;}public void setMapperLocations(Resource[] mapperLocations){this.mapperLocations=mapperLocations;}public Resource[] getMapperLocations( ) {     return  this.mapperLocations;}public void setTypeAliasesPackage(String typeAliasesPackage){this.typeAliasesPackage=typeAliasesPackage;}public String getTypeAliasesPackage( ) {     return this.typeAliasesPackage;}// Be careful to avoid recursion call.public void afterPropertiesSet() throws Exception{super.setMapperLocations(mapperLocations);super.setTypeAliasesPackage(typeAliasesPackage);super.afterPropertiesSet();this.defaultTargetSqlSessionFactory=super.getObject();buildTargetSqlSessionFactorys(); }private void buildTargetSqlSessionFactorys() throws Exception{if(dynamicDataSourceManager==null){logger.info("property 'dynamicDataSourceManager' is unset.");Assert.notNull(defaultTargetSqlSessionFactory,"Property defaultTargetSqlSessionFactory is Null");return ;}targetSqlSessionFactorys=new HashMap<String,SqlSessionFactory>();for(ShardDataSource ds:dynamicDataSourceManager.getAllDataSources()){SqlSessionFactoryBean fb=new SqlSessionFactoryBean();fb.setMapperLocations(this.getMapperLocations());fb.setTypeAliasesPackage(this.getTypeAliasesPackage());fb.setDataSource(ds);targetSqlSessionFactorys.put(ds.getId(),fb.getObject());}this.defaultTargetSqlSessionFactory=targetSqlSessionFactorys.get(dynamicDataSourceManager.getDefaultDataSource().getId());}public void setDefaultTargetSqlSessionFactory(SqlSessionFactory sqlSessionFactory){this.defaultTargetSqlSessionFactory=sqlSessionFactory;}public SqlSessionFactory getDefaultTargetSqlSessionFactory(){return this.defaultTargetSqlSessionFactory;}public Map<String,SqlSessionFactory> getTargetSqlSessionFactorys(){return this.targetSqlSessionFactorys;}}

最后 class MybatisDAO<T> extends DynamicSqlSessionDaoSupport 。


 


 

原创粉丝点击