數據庫連接的擴展以及動態切換

前幾天完成了一個很小的java項目,儘管項目很小,但是有不錯的設計,與大家分享下遇到的問題以及解決方案。

問題:項目中需要能夠操作多個數據庫,並且要有不錯的擴展性,隨時添加數據庫連接。

其實這個需求還是挺正常的,比如說:有一個網站在不同的地區涉及業務,而不同地區的數據存儲在不同的數據庫,並且日後擴展規模擴展區域會增添數據庫。

首先想到的是使用Spring來管理MyBatis的SqlSession,因爲最近項目也一直使用Spring,但是Spring容器初始化之後,很難再添加數據源,而且多個數據庫在Spring中xml配置文件需要複製多份datasource,sqlSessionFactory以及sqlSession,代碼很不優雅,擴展不足。

隨後設想使用MyBatis自己來創建SqlSessionFactory以及SqlSession,MyBatis創建SqlSessionFactory是通過讀取xml配置文件,每個數據源使用一個配置文件,增加一個配置文件也就能夠動態增加一個SqlSession(數據連接)。


部分代碼如下:

	area_one.xml中的主要配置(<mappers> 等配置省略):
	<configuration >
		<environments default="development">
			<environment id="development">
				<transactionManager type="JDBC">
			 	   </transactionManager>
		
				<dataSource type="POOLED">
					<property name="driver" value="com.mysql.jdbc.Driver" />
					<property name="url" value="jdbc:localhost:3306/area_one?characterEncoding=utf-8" />
					<property name="username" value="root" />
					<property name="password" value="root" />
				</dataSource>
			</environment>
		</environments>
	</configuration>

	area_two.xml中的主要配置(<mappers> 等配置省略):
	<configuration >
		<environments default="development">
			<environment id="development">
				<transactionManager type="JDBC">
			 	   </transactionManager>
		
				<dataSource type="POOLED">
					<property name="driver" value="com.mysql.jdbc.Driver" />
					<property name="url" value="jdbc:localhost:3306/area_two?characterEncoding=utf-8" />
					<property name="username" value="root" />
					<property name="password" value="root" />
				</dataSource>
			</environment>
		</environments>
	</configuration>

	CustomSqlSessionFactoryBuilder類用來根據xml配置文件創建SqlSessionFctory,並且據此創建SqlSession對象
	public class CustomSqlSessionFactoryBuilder
	{
		public static void buildSqlSessions()	// 靜態方法,用來創建以及更新所有的SqlSession,當有新增的xml配置文件添加到res文件夾時更新SqlSesion集
		{
			File resource_directory = new File("res");  // 讀取資源文件夾(xml配置文件保存於資源文件夾res中)	
			File[] resources = resource_directory.listFiles();
			for(File resource : resources) // 循環所有配置文件
			{
				if(resource.getName().endsWith(".xml"))
				{
					System.out.println(resource.getName());
					
					if(!CustomSqlSessionHolder.getExistedSqlSessions().keySet().contains(resource.getName())) //CustomSqlSessionHolder類保存已有的SqlSession,若已存在則跳過
					{
						try
						{
							SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
							InputStream is = Resources.getResourceAsStream(resource.getName());
							SqlSessionFactory sqlSessionFactory = builder.build(is);
							SqlSession sqlSession = sqlSessionFactory.openSession();
							String key = resource.getName().substring(0, resource.getName().indexOf(".xml"));
							CustomSqlSessionHolder.getExistedSqlSessions().put(key, sqlSession); // 以地區的名字爲key,對應的SqlSession對象爲value進行存儲
							
							System.out.println(sqlSessionFactory);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
			}
			
			System.out.println("SqlSessionHolder Updated!");
		}    

	CustomSqlSessionHolder類用來保存現有的SqlSession,以及當有新增的xml配置文件添加到res文件夾時更新SqlSesion集合
	public class CustomSqlSessionHolder
	{
		private static Map<String, SqlSession> sqlSessions = new HashMap<String, SqlSession>();
		
		public static Map<String, SqlSession> getExistedSqlSessions()
		{
			return sqlSessions;
		}
		
		public static void updateSqlSessions()
		{
			CustomSqlSessionFactoryBuilder.buildSqlSessions();
		}
		
		public static SqlSession getNeededSqlSession(String area_name)
		{
			return getExistedSqlSessions().get(area_name);
		}
	}

可以開啓一個線程一天(或12小時,其他固定時間段)運行一次CustomSqlSessionFactoryBuilder.buildSqlSessions()。

這個小項目中仍然使用了Spring不過是用作他途,真正的管理SqlSession主要代碼如上,

擁有不錯的擴展性與配置性。項目發佈到服務器上,使用cron定期執行數據庫操作。


One Week Has Gone, Good Bye, Readers! See You Next Post.....


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章