MySQL Replication 同步复制技术介绍
2012-03-27 15:52
357 查看
问题:
使用mybatis时都是用的sqlmapper来做的数据库到java对象的映射,因此在针对一些特定数据库方言使用时无法在多个数据库上切换。解决方案:
mybatis篇
思路:
通过定义environment的id来指定使用不同的数据库映射文件,如下<!--WizRtf2Html Charset=0 --><?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root" /> <property name="password" value="pwd" /> </dataSource> </environment> </environments> <mappers> <mapper resource="cn/dcr/mybatis/entity/UserMapper.xml" /> </mappers> </configuration> environment的id是mysql映射文件是cn/dcr/mybatis/entity/UserMapper.xml 那么mybatis实际是读取的mysql/cn/dcr/mybatis/entity/UserMapper.xml
实现:
以org.apache.ibatis.builder.xml.XMLConfigBuilder类为蓝本创建一个新类org.apache.ibatis.builder.xml.XMLConfigBuilderEx 添加一个成员变量private String dialect; 修改environmentsElement方法设置方言private voidenvironmentsElement(XNode context) throwsException {if (context != null) {if (environment == null){environment =context.getStringAttribute("default");}for (XNode child :context.getChildren()) {String id = child.getStringAttribute("id");dialect = id.toLowerCase();//设置方言if (isSpecifiedEnvironment(id)){TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));DataSourceFactorydsFactory = dataSourceElement(child.evalNode("dataSource"));Environment.BuilderenvironmentBuilder = newEnvironment.Builder(id).transactionFactory(txFactory).dataSource(dsFactory.getDataSource());configuration.setEnvironment(environmentBuilder.build());}}}}修改mapperElement方法[code]
private voidmapperElement(XNode parent) throws Exception{if (parent != null) {for (XNode child :parent.getChildren()) {String resource = child.getStringAttribute("resource");String url = child.getStringAttribute("url");InputStreaminputStream;if (resource!= null && url== null) {if(dialect !=null){resource = dialect+ "/" + resource;//从方言指定位置查找}ErrorContext.instance().resource(resource);inputStream=Resources.getResourceAsStream(resource);XMLMapperBuildermapperParser = newXMLMapperBuilder(inputStream, configuration, resource,configuration.getSqlFragments());mapperParser.parse();}else if (url!= null &&resource == null) {if(dialect !=null){url = dialect + "/" + url;//从方言指定位置查找}ErrorContext.instance().resource(url);inputStream=Resources.getUrlAsStream(url);XMLMapperBuildermapperParser = newXMLMapperBuilder(inputStream, configuration, url,configuration.getSqlFragments());mapperParser.parse();}else {throw newBuilderException("A mapper element may only specify a url orresource, but notboth.");}}}}继承org.apache.ibatis.session.SqlSessionFactoryBuilder类创建一个新类org.apache.ibatis.session.SqlSessionFactoryBuilderEx用来加载org.apache.ibatis.builder.xml.XMLConfigBuilderEx覆盖父类中的build方法
public SqlSessionFactory build(InputStreaminputStream, String environment, Properties props) {try {XMLConfigBuilderEx parser = newXMLConfigBuilderEx(inputStream, environment,props);Configuration config =parser.parse();returnbuild(config);} catch (Exceptione) {throwExceptionFactory.wrapException("Error buildingSqlSession.", e);} finally{ErrorContext.instance().reset();try{inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previouserror.}}}调用org.apache.ibatis.builder.xml.XMLConfigBuilderEx来加载配置文件
spring篇
思路:
自定义mybatis配置加载Bean在spring的配置文件中添加方言的配置让自定义Bean在加载mybatis的配置时可以使用不同的数据库映射文件,如下<beanid="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBeanEx"><propertyname="dataSource"ref="dataSource" /><property name="configLocation"value="classpath:configuration.xml" /><propertyname="mapperLocations" value="classpath*:${jdbc.dialect}/mappers/*.xml"/></bean>${jdbc.dialect}在配置文件中设置,如mysql,那么spring会把mysql/mappers下的所有映射文件加载进来
实现:
以org.mybatis.spring.SqlSessionFactoryBean为蓝本创建org.mybatis.spring.SqlSessionFactoryBeanEx类将成员变量private SqlSessionFactoryBuildersqlSessionFactoryBuilder = newSqlSessionFactoryBuilder();修改为
private SqlSessionFactoryBuilderExsqlSessionFactoryBuilderEx = newSqlSessionFactoryBuilderEx();并去掉setSqlSessionFactoryBuilder方法添加setSqlSessionFactoryBuilderEx方法覆盖buildSqlSessionFactory方法
protected SqlSessionFactory buildSqlSessionFactory()throws IOException, IllegalAccessException,InstantiationException {XMLConfigBuilderExxmlConfigBuilderEx;Configurationconfiguration;if (this.configLocation !=null) {try{xmlConfigBuilderEx = new XMLConfigBuilderEx(this.configLocation.getInputStream(), null, this.configurationProperties);configuration= xmlConfigBuilderEx.parse();} catch (Exception ex) {throw newNestedIOException("Failed to parse config resource: "+ this.configLocation, ex);} finally{ErrorContext.instance().reset();}if (this.logger.isDebugEnabled()){this.logger.debug("Parsed configuration file: '" +this.configLocation + "'");}} else {if (this.logger.isDebugEnabled()){this.logger.debug("Property 'configLocation' not specified, using default MyBatisConfiguration");}configuration = newConfiguration();}if (this.transactionFactory == null) {this.transactionFactory =new SpringManagedTransactionFactory(this.dataSource);}Environmentenvironment = newEnvironment(this.environment, this.transactionFactory, this.dataSource);configuration.setEnvironment(environment);if (!ObjectUtils.isEmpty(this.mapperLocations)) {Map<String, XNode>sqlFragments = newHashMap<String, XNode>();for (Resource mapperLocation : this.mapperLocations){if (mapperLocation == null) {continue;}// MyBatis holds a Map using "resource" name as akey.// If a mapper file isloaded, it searches for a mapper// interface type.// If the type is found then it tries to load the mapperfile// again looking forthis://// StringxmlResource = type.getName().replace('.', '/') +// ".xml";//// So if a mapperinterface exists, resource cannot be an// absolute path.//Otherwise MyBatis will throw an exceptionbecause// it will load both amapper interface and the mapper xml file,// and throw an exception telling that a mapperStatementcannot// be loadedtwice.String path;if (mapperLocation instanceof ClassPathResource){path = ((ClassPathResource)mapperLocation).getPath();} else {//this won't work if there is also a mapper interfacein//classpathpath =mapperLocation.toString();}try {XMLMapperBuilderxmlMapperBuilder = newXMLMapperBuilder(mapperLocation.getInputStream(), configuration, path,sqlFragments);xmlMapperBuilder.parse();}catch (Exception e){throw new NestedIOException("Failed toparse mapping resource: '" + mapperLocation+ "'",e);} finally{ErrorContext.instance().reset();}if (this.logger.isDebugEnabled()){this.logger.debug("Parsed mapperfile: '" + mapperLocation + "'");}}}else {if (this.logger.isDebugEnabled()){this.logger.debug("Property 'mapperLocations' was not specified, only MyBatis mapperfiles specified in the config xml wereloaded");}}return this.sqlSessionFactoryBuilderEx.build(configuration);}
相关文章推荐
- SQL Server 2005 同步复制技术
- SQL SERVER 2005 同步复制技术
- OracleDataguard数据同步复制的容灾技术方案
- 同步复制技术实现步骤
- SQL SERVER 2005 同步复制技术
- SQLServer2000同步复制技术实现步骤
- MariaDB数据库主从复制、双主复制、半同步复制、基于SSL的安全复制实现及其功能特性介绍 推荐
- SQL SERVER 2005 同步复制技术
- WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- 介绍几种容灾复制技术
- MySQL半同步复制原理配置与介绍
- MySQL5.7半同步复制技术
- WMI技术介绍和应用——使用VC编写一个半同步查询WMI服务的类
- SQLServer2000同步复制技术实现步骤
- 以快照复制为例 SQL SERVER 2005 同步复制技术
- SQLServer2000同步复制技术实现步骤(收藏)
- SQLServer2000同步复制技术实现步骤
- SQLServer2000同步复制技术实现步骤
- SQLServer2000同步复制技术实现步骤